Skip to content

Zeek Hands-on Labs

Choose the route that fits your available time and computing resources. Use the Interactive Lab for a short guided log-correlation exercise, or the Full Lab to install Zeek, process authorised traffic, and produce a reproducible finding.

Hands-on proof of concept

Observe it. Correlate it. Explain it.

Build or validate a Zeek sensor, process controlled traffic, correlate activity across structured logs, and retain enough evidence for another analyst to reproduce your conclusion.

⏱ 2–3 hours core ◆ Guided beginner ✓ Evidence required
Self-hosted · Several hours

Zeek Full Lab

Installation required

How this differs from the guided walkthrough

The guided journeys retain the detailed commands, configuration examples, captured output, and expected records from the proof of concept. This page asks you to build your own environment, preserve source integrity, correlate evidence, and write a reproducible analyst conclusion.

Use an isolated, authorised environment

Monitor or capture traffic only where you have explicit permission. Treat PCAPs and Zeek logs as potentially sensitive evidence. Use a dedicated lab network, avoid production traffic, and remove temporary intelligence data and captures when the exercise is complete.

Before you begin

You need: one isolated Ubuntu sensor or analysis VM, administrator access, Zeek and zeek-cut, approximately 20 GB of free disk space, and an authorised copy of the sample.pcap used in the log-inspection procedure.

How to use this lab

Complete one session at a time. Stop at a milestone if the expected log or field is missing. Fix that boundary before attempting another correlation or adding an integration.

Optional extension

Complete Analysis Lab

After the core milestones pass, add live monitoring, JSON analysis, a safe intelligence indicator, or a Suricata comparison.

Expected time: one or more additional sessions.

  1. Session 1Build and snapshot
  2. Session 2Process and verify
  3. Session 3Correlate and explain

Objective

You are investigating network activity from the lab workstation 10.0.0.25. Determine which HTTP service it contacted, which DNS evidence provides context, what resource and file metadata Zeek observed, and what the network records do not prove.

The Beginner Core Lab uses one Ubuntu VM and one authorised sample.pcap. Complete the core path before attempting the optional live, JSON, intelligence, or Suricata extensions.

01

Activity 1: Build and baseline the sensor

Build record

Before installing packages or transferring a PCAP, record the following:

Item Value to record
Validation date YYYY-MM-DD
Zeek Exact version, package filename, repository or source URL, and checksum
Analysis host Ubuntu release, architecture, memory, storage, and timezone
Network configuration Monitored interface, local networks, address, and gateway
Source PCAP Source, retrieval date, filename, size, and SHA-256 checksum
Supporting tools Versions of zeek-cut, jq, tcpdump, and Suricata if used
Lab isolation Virtual network mode, disabled integrations, and clean snapshot name

Use the official Zeek documentation and the package source recorded in the installation procedure as the authoritative references for this exercise.

Prepare and verify the sensor

  1. Create or select a dedicated Ubuntu VM on an isolated lab network.
  2. Confirm its address, gateway, DNS settings, clock, and monitored interface.
  3. Install Zeek using the relevant installation procedure.
  4. Run the following checks and record their output:
zeek --version
command -v zeek zeek-cut sha256sum
  1. Create a clean workspace that keeps the source capture separate from generated logs and retained evidence:
mkdir -p ~/zeek-lab/{source,logs,evidence}
  1. Copy the authorised sample.pcap into ~/zeek-lab/source/, then record its source, filename, size, and hash:
ls -lh ~/zeek-lab/source/sample.pcap
sha256sum ~/zeek-lab/source/sample.pcap
  1. If you will complete the optional live route, configure the interface and local networks using the live-monitoring procedure, then validate ZeekControl. The offline core route does not require a running ZeekControl node.
  2. Create a clean snapshot named zeek-clean-baseline.
Milestone 1Analysis baseline readyZeek and zeek-cut run, the source capture has a recorded origin and SHA-256 hash, the workspace separates source and generated evidence, and the clean snapshot can be restored.

Expected result Zeek and zeek-cut run successfully, the build record identifies every external artifact, the source capture is hashed before analysis, and the clean VM snapshot can be restored.

02

Activity 2: Process controlled traffic

Start from the zeek-clean-baseline snapshot. Confirm the source-capture hash still matches the value recorded in Activity 1.

Process the core capture

  1. Clear only the generated log directory, then process the capture from that directory so the original remains unchanged:
cd ~/zeek-lab/logs
rm -f ./*.log
zeek -C -r ../source/sample.pcap

The -C option ignores invalid transport checksums commonly introduced by checksum offloading. It does not repair truncated traffic or missing packets. Record that you used it.

Verify Zeek output

  1. List the generated logs:
ls -lh *.log
  1. Confirm that conn.log, dns.log, http.log, and files.log exist. The documented trace may also produce ntp.log, syslog.log, and packet_filter.log.
  2. Count records without treating Zeek header lines as events:
for log in conn dns http files; do
  printf '%-10s ' "$log.log"
  zeek-cut uid < "$log.log" | wc -l
done
  1. Copy the four core logs to the evidence directory and hash them:
cp conn.log dns.log http.log files.log ~/zeek-lab/evidence/
sha256sum ~/zeek-lab/evidence/*.log
  1. Record missing logs, checksum issues, parser notices, or version-dependent differences instead of forcing the documented result.
Milestone 2Four logs verifiedThe unchanged source capture produced connection, DNS, HTTP, and file records; the processing command and generated-log hashes are preserved.
Optional live-traffic route

Use traffic generated only by your own lab systems. Follow the live-monitoring procedure, then generate one ICMP echo, one DNS lookup against your lab resolver, and one HTTP request to a local test server. Record the commands and test window. Preserve these logs separately from the core-capture evidence.

Expected result The source traffic and processing command are recorded, `conn.log` and the expected protocol logs exist, and the retained evidence can be traced back to the controlled activity or source PCAP.

03

Activity 3: Correlate and explain the evidence

Build a connection timeline

Start with the broad connection index. zeek-cut reads the field definitions from the log header, while -d renders the timestamp in a readable form.

cd ~/zeek-lab/evidence
zeek-cut -d ts uid id.orig_h id.resp_h id.resp_p service \
  duration orig_bytes resp_bytes conn_state < conn.log

Find the HTTP connection initiated by 10.0.0.25. Record its generated UID, responder address, port, duration, byte counts, and connection state. Do not copy a UID from the documentation: Zeek may assign different identifiers when the capture is processed again.

Set a shell variable to the UID you found:

CONN_UID='<your-connection-uid>'

Correlate protocol and file activity

  1. Find the HTTP request that shares the connection UID:

    zeek-cut -d ts uid id.orig_h id.resp_h method host uri status_code \
      resp_fuids resp_mime_types < http.log \
      | awk -v uid="$CONN_UID" '$2 == uid'
    
  2. Find the file metadata tied to the same connection:

    zeek-cut -d ts fuid uid mime_type filename seen_bytes total_bytes \
      missing_bytes < files.log \
      | awk -v uid="$CONN_UID" '$3 == uid'
    
  3. Inspect DNS separately:

    zeek-cut -d ts uid id.orig_h query answers < dns.log
    

    Find a DNS answer for the HTTP responder used by 10.0.0.25. Correlate it by source, time, query and answer address—not by the HTTP connection UID. A DNS transaction and the later HTTP connection are different conversations.

    dns.log -- source + time + answer --> conn.log
                                            |
                                          UID
                                            v
                                  http.log -- FUID --> files.log
    
  4. Record the query, host, URI, status code, MIME type, UID, FUID, byte counts, and any missing-byte value. Preserve the commands and relevant output.

  5. Before continuing, answer: does the available network evidence show a file transfer, file execution, or both?

Expected result The timeline correctly distinguishes direct UID correlation from time-and-address correlation, and every claim can be traced to a named log and field.

Milestone 3One evidence chain explainedYou traced one connection into its HTTP and file records, added DNS context using time and address, and distinguished an observed transfer from unproven execution.
Optional: repeat the analysis with JSON logs

Process the same capture into a separate directory with LogAscii::use_json=T, then reproduce the connection and DNS queries with jq. Record whether the format changes your conclusion or only how the fields are queried. Follow Inspect Zeek logs for the starter syntax.

Optional: add intelligence or Suricata evidence

Choose one extension only after Milestone 3 passes:

Record what the extension adds and what it still cannot prove.

Write and validate the conclusion

Write a short analyst note containing:

  • the question you investigated;
  • the source traffic or PCAP and its checksum;
  • relevant timestamps, hosts, domains, ports, UIDs, and FUIDs;
  • the logs, fields, and commands used;
  • intelligence or Suricata results, where applicable;
  • the conclusion supported by the evidence; and
  • limitations or alternative explanations that affect confidence.

Use this structure if you are writing your first analyst note:

Question:
Source evidence and SHA-256:
Observed source and destination:
DNS context:
HTTP request:
File metadata:
What Zeek proves:
What Zeek does not prove:
Confidence, limitations, and next action:

For peer validation, ask another analyst to repeat the queries from your evidence directory. If you are working alone, restore zeek-clean-baseline, reprocess the source capture, and compare the new result with your notes. A matching result is stronger evidence than a screenshot alone.

Expected result Another analyst can reproduce the log queries, follow the correlation chain, and distinguish observed network facts from interpretation.

Full Lab evidence checklist

Retain only authorised evidence and store it in the approved lab or case location. This checklist applies to the VM-based Full Lab. If you completed the Interactive Lab, retain its downloaded evidence summary instead. Record optional live, JSON, intelligence, or Suricata evidence separately.

0 of 8 recorded Mark each item after saving the evidence.
Optional extension evidence

If used, retain the live-traffic commands and timing, JSON queries, intelligence source and match, or Suricata rule and alert alongside the core record. Optional evidence does not replace a missing core milestone.

Troubleshooting

Symptom First check
conn.log is missing Confirm the PCAP path, file size, read permission, and the exact Zeek command. Run tcpdump -n -r ../source/sample.pcap | head to confirm packets are readable.
dns.log, http.log, or files.log is missing Confirm you used the documented trace and did not apply a capture filter. Record the missing protocol rather than creating an expected result.
zeek-cut reports an unknown field Inspect the log's #fields header and substitute the field used by your Zeek version. Record the substitution.
The selected UID returns no HTTP or file row Recheck the UID in conn.log, then find the HTTP row first and use the UID shown there. A connection may not contain every protocol or file record.
DNS and HTTP UIDs differ This is expected. Correlate DNS using the source, timestamp, query answer, and later responder address.
Results differ after reprocessing Confirm the source hash, Zeek version, command, scripts, working directory, and output format before comparing individual identifiers.

Clean up

  1. Stop Zeek or restore the original ZeekControl state.
  2. Remove the temporary training indicator from local.zeek and redeploy if you completed the intelligence extension.
  3. Stop temporary capture tools and local test services.
  4. Preserve authorised notes, hashes, commands, PCAPs, and required logs in the approved evidence location.
  5. Delete unneeded temporary captures and copied logs from transfer locations.
  6. Revert the disposable VM to zeek-clean-baseline, or securely dispose of it according to your lab procedure.
  7. Record who completed the cleanup and when.

Escalate unexpected exposure

If the sensor captured unauthorised or sensitive traffic, stop the exercise, restrict access to the evidence, and follow your organisation's privacy and incident-handling procedures.

Where to go next