If you have ever spent 3:00 AM digging through multi-terabyte raw PCAP files while an incident commander breathes down your neck, you know the fundamental tragedy of network security operations: raw network packets contain complete truth, but they are far too heavy, unstructured, and expensive to search at enterprise scale. Conversely, traditional signature-based Intrusion Detection Systems (IDS) like Suricata or Snort fire off thousands of alerts a day, leaving your tier-1 analysts drowned in false positives while sophisticated adversaries slide by undetected using living-off-the-land techniques.
This is where Zeek (formerly Bro) transforms your SOC. Zeek is not a signature alert engine, nor is it a simple flow collector. It is an open-source, event-driven network analysis platform that translates unmanaged, high-speed packet streams into structured, protocol-aware transactional logs in real time.
To effectively hunt across your network, your SOC team must master four fundamental Zeek core logs:
### 1. `conn.log` (Connection Tracker)
This is the foundational network backplane of Zeek. Every single IP communication attempt—whether TCP, UDP, or ICMP—generates a `conn.log` entry upon connection termination or timeout.
* `uid`: A unique alphanumeric identifier (e.g., `C8jX7a3Zt6n2MvK9L`) assigned to the connection. This `uid` spans across all other log files (`dns.log`, `http.log`, `ssl.log`), allowing seamlessly correlated queries across protocols.
* `id.orig_h` / `id.orig_p`: Originating (source) IP address and port.
* `id.resp_h` / `id.resp_p`: Responding (destination) IP address and port.
* `proto`: Transport layer protocol (`tcp`, `udp`, `icmp`).
* `duration`: Elapsed time of the session in seconds.
* `orig_bytes` / `resp_bytes`: Payload bytes sent by originator vs. responder.
* `conn_state`: State tracking flags. Critical flags include:
* `S0`: Connection attempt seen, no reply (potential scanner or dead host).
* `SF`: Normal establishment and termination (SYN/ACK/FIN).
* `REJ`: Connection attempt rejected (RST sent by responder).
* `RSTO`: Connection established, but aborted by originator (RST sent).
* `history`: A compact letter string showing sequence of TCP control packets (e.g., `ShADdfF` indicates SYN, SYN-ACK, ACK, Data exchange, FIN).
### 2. `dns.log` (Domain Name Service Resolution)
DNS is the primary mechanism adversaries use for infrastructure bootstrap, command-and-control (C2), and data exfiltration.
* `query`: Domain string requested (e.g., `api.malicious-c2-domain.com`).
* `qtype_name`: Type of query (`A`, `AAAA`, `TXT`, `MX`, `CNAME`).
* `rcode_name`: Response code returned by the server (`NOERROR`, `NXDOMAIN`, `SERVFAIL`).
* `answers`: Array of IP addresses or strings returned to the client.
* `RTT`: Round-trip time of the resolution request.
### 3. `ssl.log` and `x509.log` (Cryptographic Session Analysis)
Because over 85% of modern web traffic and threat actor communications are encrypted via TLS, deep packet payload inspection is often blinded. Zeek bypasses payload encryption by auditing the unencrypted TLS handshake protocols and certificate chains.
* `server_name`: Server Name Indication (SNI) extension passed in the client hello.
* `version`: Negotiated TLS version (`TLSv12`, `TLSv13`).
* `cipher`: Selected cryptographic cipher suite.
* `ja3` / `ja3s`: Client and Server TLS fingerprint hashes. Essential for detecting specific C2 frameworks (e.g., Cobalt Strike profiles, Mythic agents) regardless of the domain name or IP used.
* `validation_status`: Results of OpenSSL certificate chain validation (e.g., `self signed certificate`, `certificate has expired`, `ok`).
### 4. `http.log` (Web Application Transactions)
For unencrypted web traffic, API endpoints, or proxied internal networks, `http.log` provides immediate application context.
* `host`: HTTP Host header.
* `uri`: Full request path and parameter strings (e.g., `/admin/upload.php?id=104`).
* `user_agent`: Client browser string or custom automated script identifier.
* `method`: HTTP verbs (`GET`, `POST`, `PUT`, `CONNECT`).
* `status_code`: Server return status (`200`, `403`, `404`, `500`).
* `request_body_len` / `response_body_len`: Content payload sizes.
Direct Practical Verdict:
Zeek transforms raw network packet streams into rich, structured behavioral logs (such as conn.log, dns.log, and ssl.log) without the storage overhead of full PCAP. Unlike signature IDS engines that alert only on known IOCs, Zeek records protocol state and application transaction ground truth, giving enterprise SOCs the exact telemetry required for proactive threat hunting and historical incident reconstruction at 10Gbps+ scale.
Why Does Your Enterprise SOC Need Zeek Instead of Pure IDS Alerting?
To build a resilient Security Operations Center, you must understand the operational boundary between signature detection, flow capture, and Network Security Monitoring (NSM). Most security teams rely on a triad of network tools, yet confuse their architectural roles: 1. NetFlow / IPFIX: Provides basic 5-tuple operational telemetry (source IP, destination IP, source port, destination port, protocol) along with byte and packet counters. It is lightweight and cheap to store, but completely blind to protocol payloads, hostnames, SSL certificates, and application-layer metadata. 2. Signature IDS (Suricata / Snort): Evaluates packet payloads against a static database of regular expressions and rules. When a match occurs, it generates an alert. If an attacker subtlely modifies their payload or uses non-standard protocol constructs, the IDS remains silent. 3. Full Packet Capture (PCAP): Captures every single bit on the wire. While it provides complete fidelity, running full PCAP on a modern 10Gbps or 40Gbps enterprise trunk requires massive SAN infrastructure, degrades analytical search performance to a crawl, and often violates compliance and privacy directives. Zeek sits at the critical intersection of these technologies. It parses network traffic at line rate, reconstructs session states across Layer 3 through Layer 7, and emits normalized, high-fidelity transaction records. “` +————————-+ | Raw Network Packet | | SPAN / TAP Stream | +————+————+ | v +————+————+ | Packet Capture Layer | | (AF_PACKET / DPDK) | +————+————+ | v +————+————+ | Zeek Protocol Decoders | | (HTTP, DNS, TLS, SMB) | +————+————+ | +————–+————–+ | | v v +————+————+ +————+————+ | Event Engine & Scripts | | Structured Log Output | | (Custom SOC Logic) | | (JSON / Tab-Separated) | +————+————+ +————+————+ | | v v +————+————+ +————+————+ | Notice & File Extraction| | SIEM / Log Pipeline | | (Sandbox / SOAR Pipeline)| | (Elastic, OpenSearch) | +————————-+ +————————-+ “` When an analyst asks, *”Did host 10.0.4.15 connect to a malicious command-and-control server standard over port 443?”*, a signature IDS yields zero hits if the C2 IP is unknown. NetFlow shows a simple port 443 connection with 45 KB transferred. Full PCAP requires querying terabytes of disk space to pull the session capture file. Zeek instantly provides a structured line in `ssl.log` and `x509.log` displaying the exact JA3 fingerprint, the self-signed TLS certificate subject name, the SNI hostname, and the server key exchange attributes—giving threat hunters immediate context within seconds.What Are the Key Zeek Log Schemas and How Do You Audit Them?
Zeek generates over 30 modular log streams depending on the protocols running across your enterprise. Understanding these schemas is mandatory for building high-performing SIEM parsing rules and effective threat hunting queries.| Telemetry Technology | Data Granularity | Storage Footprint (per 1Gbps/24h) | Primary SOC Analytic Function | Key Operational Limitation |
|---|---|---|---|---|
| Full PCAP | Complete payload & header (100% byte fidelity) | ~10.8 Terabytes | Deep packet inspection, protocol reverse engineering | Prohibitive storage cost; extremely slow query speeds |
| NetFlow / IPFIX | L3/L4 5-Tuple summary, byte/packet statistics | ~1.5 – 5 Gigabytes | Volumetric DDoS detection, bandwidth tracking | Zero payload awareness, no hostname or cert details |
| Signature IDS (Suricata) | Alert-only metadata matching static signature rules | ~500 Megabytes – 10 Gigabytes (rule dependent) | Known vulnerability exploitation detection | Fails on novel/zero-day attacks; high alert fatigue |
| Zeek NSM Engine | L3–L7 protocol state logging, file metadata, certificates | ~30 – 80 Gigabytes | Behavioral threat hunting, session timeline reconstruction | Requires log pipeline setup (Elastic/OpenSearch) |
How Do You Execute Advanced Threat Hunting in Zeek Logs?
Threat hunting is not randomly running searches in a dashboard; it is hypothesis-driven exploration against structural baseline anomalies. Let’s look at three practical threat hunting methodologies using Zeek logs. ### 1. Detecting DNS Tunneling and Data Exfiltration Adversaries use DNS tunneling tools (such as Iodine, DNSCat2, or custom PowerShell stagers) to exfiltrate data or maintain C2 backchannels over networks where external web traffic is tightly restricted. DNS tunneling relies on encoding binary data into the subdomain space of a attacker-controlled authoritative name server. Hunting Logic: 1. High volume of `TXT` or `NULL` DNS record queries. 2. Abnormally long hostnames inside the `query` field. 3. High Shannon entropy (randomness) in requested subdomains. 4. Large ratios of `NXDOMAIN` status codes. “`bash # Example Threat Hunting CLI: Extract top 10 suspicious subdomains based on query length and TXT types from dns.log zeek-cut query qtype_name answers < dns.log \ | awk '$2 == "TXT" || length($1) > 45 {print $1}’ \ | sort \ | uniq -c \ | sort -nr \ | head -n 20 “` When analyzing this output in your SIEM, look for subdomains like `aNzR4eKs9qW2L.exfil.attacker.com`. Calculate the character length and statistical entropy of the prefix. Standard corporate domain requests follow recognizable word patterns (`mail.google.com`, `cdn.office.com`); DNS exfiltration manifests as random base64 or hex-encoded character distributions. ### 2. Identifying C2 Beaconing via `conn.log` Clustering Command-and-control agents periodically check in (“beacon”) with their controller to receive queued tasking. While malware authors insert “jitter” (randomized sleep intervals) to evade basic timing thresholds, structural patterns remain visible in `conn.log`. Hunting Logic: Group connections by source (`id.orig_h`), destination (`id.resp_h`), and destination port (`id.resp_p`). Evaluate the statistical variance of three attributes: 1. Delta Time ($\Delta t$): The time difference between sequential connection setups. 2. Originating Bytes (`orig_bytes`): Beacon requests usually send uniform packet sizes (e.g., exact 450-byte POST payloads). 3. Responding Bytes (`resp_bytes`): Empty beacon responses return uniform size distributions (e.g., 0-byte or 120-byte polling responses). If a internal workstation generates 1,400 connections over 24 hours to an external IP on port 8443, where `orig_bytes` maintains a standard deviation near 0 and connection intervals exhibit tight clustering, you have identified a live C2 beacon. ### 3. Spotting Rogue TLS Certificates and Malicious JA3 Hashes Malware authors frequently set up C2 infrastructure using quickly provisioned infrastructure with default, self-signed, or recycled SSL/TLS certificates. Hunting Logic: Query `ssl.log` and join with `x509.log` focusing on anomalous certificate parameters: * `ssl.log` where `validation_status != “ok”`. * Certificates where the `issuer` matches the `subject` (Self-Signed) targeting non-internal IP addresses. * TLS connections operating without Server Name Indication (`server_name` field is null or empty). * High-risk JA3 fingerprints. For example, Cobalt Strike’s default TLS client handshake exhibits a known JA3 hash: `72a589da586844d7f0818ce684948eea`. “`bash # Filter ssl.log for established sessions lacking SNI hostnames but pointing to public IP addresses zeek-cut id.orig_h id.resp_h id.resp_p server_name ja3 validation_status < ssl.log \ | awk '$4 == "-" && $6 != "ok" {print $1 " -> ” $2 “:” $3 ” | JA3: ” $5}’ “`How Do You Write Custom Event-Driven Zeek Scripts for Automated Defense?
Zeek’s true power lies in its Turing-complete, domain-specific scripting language. Zeek runs an asynchronous event-loop engine: when the protocol parsers detect a network event (e.g., a complete HTTP header, a DNS query, or TCP connection tear-down), Zeek fires an internal event that your custom scripts can intercept. ### Custom Script 1: Automated SSH Brute Force Detection with Notice Emission While basic firewall rules block obvious scanners, advanced attackers execute slow-and-low SSH brute-force attacks across multiple destination IPs. The following operational script tracks failed SSH login patterns and raises an automated security alert via Zeek’s Notice Framework. Create a file named `detect-ssh-bruteforce.zeek`: “`zeek module EnterpriseSOC::SSHBruteForce; export { redef enum Notice::Type += { SSH_BruteForce_Threshold_Exceeded }; ## Maximum failed login attempts allowed within the tracking window const failed_threshold: double = 10.0 &redef; ## Time window to track failures (e.g., 5 minutes) const tracking_expiration: interval = 5 mins &redef; } # State table tracking source IP -> failed attempt count global failed_ssh_table: table[addr] of count &create_expire=tracking_expiration; event ssh_auth_failed(c: connection) { local src_ip = c$id$orig_h; if ( src_ip !in failed_ssh_table ) { failed_ssh_table[src_ip] = 1; } else { failed_ssh_table[src_ip] += 1; } if ( failed_ssh_table[src_ip] == double_to_count(failed_threshold) ) { NOTICE([$note=SSH_BruteForce_Threshold_Exceeded, $conn=c, $src=src_ip, $msg=fmt(“Host %s performed %d failed SSH logins within %s”, src_ip, failed_ssh_table[src_ip], tracking_expiration), $identifier=cat(src_ip)]); } } “` How This Script Works: 1. `module EnterpriseSOC::SSHBruteForce;`: Namespaces our logic to prevent collisions. 2. `redef enum Notice::Type`: Extends Zeek’s native alerting engine with a new enum type. 3. `table[addr] of count &create_expire=…`: Allocates an in-memory state table indexed by attacker IP. Entries automatically expire after 5 minutes to prevent memory leaks. 4. `event ssh_auth_failed(c: connection)`: Intercepts every failed SSH session identified by Zeek’s SSH analyzer. 5. `NOTICE(…)`: Emits a structured alert to `notice.log`. Log shippers (like Filebeat) immediately consume this event to trigger SIEM alerts or SOAR playbooks (e.g., dynamically executing a firewall drop rule). ### Custom Script 2: Dynamic File Extraction for
Behavioral Network Protocol Analysis & Transaction Logs
Triggering automated endpoint host responses relies on correlating host-level logs with deep network session telemetry. For Zeek SOC deployment blueprints, review Wazuh Active Response: Automated SOC Threat Defense.

