Mastering Network Visibility: A Hands-on Guide to Zeek on Linux

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Why Packet Inspection Often Fails

Years ago, while working as a junior security analyst, I hit a wall with traditional IDS tools like Snort and Suricata. They are fantastic at matching signatures against known threats, but they often left me in the dark during zero-day attacks or lateral movement. That is when I discovered Zeek (formerly Bro).

A standard IDS screams when it hits a “bad” string. Zeek is different; it acts as a high-fidelity flight recorder. It transforms raw packets into structured, searchable logs, giving you the context to understand what happened, rather than just alerting you that something went wrong.

Signature-Based vs. Policy-Driven Analysis

Most security tools rely on Signature-based detection. They look for specific patterns—a file hash, a malicious IP, or a unique string. If an attacker changes a single byte in their malware, the signature fails. Zeek takes a Policy-driven approach. Instead of looking for “bad” things, it parses protocols like HTTP, DNS, and SSL/TLS to record metadata.

It doesn’t just see TCP traffic on port 80. It records a GET request for a specific URI and the exact User-Agent used. This allows you to hunt for behavioral shifts. For instance, if a user who typically browses 10MB of data daily suddenly downloads 5GB from an internal server, Zeek flags the behavior regardless of whether a signature exists for that specific action.

The Reality of Using Zeek

  • The Good:
    • Granular Logging: You get dedicated logs for DNS queries, SSL handshakes, and even file hashes extracted mid-stream.
    • Turing-Complete Scripting: You can automate complex detection logic using Zeek’s own language.
    • High Performance: It scales. Large organizations use Zeek clusters to monitor 100Gbps links without breaking a sweat.
  • The Bad:
    • Learning Curve: Mastering the scripting language takes weeks, not hours.
    • Storage Demands: On a busy 1Gbps link, Zeek can easily generate 100GB of logs in a single day. You need fast, high-capacity storage.
    • Passive Only: Zeek is a monitor. It won’t drop packets or block IPs natively; it’s there to provide visibility.

Production Hardware Requirements

For a production environment, I recommend a dedicated physical server or a high-performance VM with a mirrored (SPAN/TAP) port. A small office environment can start with 4-8 CPU cores and 16GB of RAM.

Security starts with the basics. When setting up administrative accounts for a new Zeek node, I use the generator at toolcraft.app/en/tools/security/password-generator. I prefer this tool because it runs entirely in your browser. This ensures your sensitive credentials never touch the network during the generation process.

Installation Guide: Zeek on Ubuntu 22.04/24.04

Skip the headache of compiling from source. Using pre-built packages from the Open Build Service (OBS) is the fastest way to get a stable version running.

Step 1: Repository Setup

# Add the repository key
curl -fsSL https://download.opensuse.org/repositories/security:zeek/xUbuntu_22.04/Release.key | sudo gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/security_zeek.gpg > /dev/null

# Add the Zeek repository
echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_22.04/ /' | sudo tee /etc/apt/sources.list.d/security:zeek.list

# Update and install
sudo apt update
sudo apt install zeek-6.0

When prompted for the installation directory, stick with the default /opt/zeek. It keeps the core system directories organized and predictable.

Step 2: Environment and Path

Add Zeek’s binaries to your system PATH to avoid typing full directory paths every time.

echo "export PATH=$PATH:/opt/zeek/bin" >> ~/.bashrc
source ~/.bashrc

Step 3: Defining Local Networks

Zeek needs to know which IP ranges are “home.” This distinction is vital for identifying outbound data exfiltration versus internal lateral movement. Edit networks.cfg:

sudo nano /opt/zeek/etc/networks.cfg

Define your subnets like this:

10.0.0.0/8          Internal Private Space
192.168.1.0/24      Main Office
172.16.0.0/12       Dev Lab

Step 4: Interface Selection

Identify your sniffing interface (e.g., enp0s3) using ip link show. Then, configure node.cfg:

sudo nano /opt/zeek/etc/node.cfg

Update the interface line under the [zeek] section:

[zeek]
type=standalone
host=localhost
interface=enp0s3

Step 5: Deployment

Use zeekctl to initialize and launch the engine. This tool manages the background processes for you.

sudo zeekctl install
sudo zeekctl start
sudo zeekctl status

Navigating the Logs

Check /opt/zeek/logs/current to see the data in real-time. This is where the magic happens. You’ll see several .log files that categorize your traffic:

  • conn.log: The master list of every TCP, UDP, and ICMP connection.
  • dns.log: A record of every query, response, and TTL.
  • http.log: Metadata for unencrypted web traffic, including hostnames and referrers.
  • ssl.log: Details on encrypted sessions, showing certificate issuers and TLS versions.
  • files.log: A log of files seen on the wire, often including MD5/SHA1 hashes.

To extract value quickly, use zeek-cut. For example, to find the top 10 most requested domains on your network, run:

cat dns.log | zeek-cut query | sort | uniq -c | sort -rn | head -n 10

Detecting Threats with Scripts

Zeek’s real strength is its ability to react to events. You can write a script to flag potential SSH brute-forcing by monitoring failed authentication events. Create /opt/zeek/share/zeek/site/detect-brute.zeek:

event ssh_auth_failed(c: connection)
{
    print fmt("Alert: SSH Failure from %s to %s", c$id$orig_h, c$id$resp_h);
}

Load this by adding @load detect-brute.zeek to your local.zeek file, then run sudo zeekctl deploy to apply the changes.

Hard-Won Lessons from the Field

Don’t ignore log rotation. Zeek is a data firehose. If you don’t configure zeekctl cron, your drive will likely hit 100% capacity within 48 hours. I set a cron job to run every five minutes to handle log maintenance and health checks.

Keep an eye on packet drops. If your CPU spikes, Zeek will start missing traffic, leaving gaps in your security history. Use zeekctl capstats to monitor performance. If you see drops exceeding 5%, it’s time to switch from a “standalone” setup to a “cluster” configuration in node.cfg to distribute the load across multiple cores.

Lastly, treat the CLI as a starting point. While zeek-cut is great for quick troubleshooting, you should eventually pipe these logs into an ELK stack or Wazuh. Having a visual dashboard makes it much easier to spot the “slow and low” attacks that usually hide in the noise of daily logs.

Share: