"The first question in any security investigation is: what happened on the wire? The answer is always in a packet capture, if you kept one." -- Richard Bejtlich, The Practice of Network Security Monitoring (No Starch, 2013), Ch. 1
Lecture (100 min, two 50-min blocks)
10.1 Network Security Monitoring: The Discipline
Network Security Monitoring (NSM) is the collection, detection, and analysis of network data for the purpose of identifying and characterizing threats. NSM is not intrusion prevention -- it is the forensic foundation that makes post-incident investigation possible and that provides enough real-time signal to catch active threats.
Three tiers of NSM data:
- Full packet capture (FPC): every byte of every packet, stored as PCAP. Complete forensic record. Storage-intensive; typically stored for 24-72 hours on high-volume links, longer on lower-volume ones.
- Flow data: connection metadata without payload (source/destination IP, port, protocol, bytes, packets, duration). Long-term retention is practical; provides behavioral baselines. Generated by NetFlow v5/v9, IPFIX, sFlow.
- Protocol logs: structured records of what happened at the application layer (HTTP request logs, DNS query logs, TLS certificate logs). Zeek excels at this.
NSM answers: who talked to whom, for how long, on what port, with what application-layer behavior, at what time?
10.2 Wireshark: Deep-Dive Beyond NET-101
NET-101 introduced Wireshark. This week builds the skills required for real security analysis.
Display filter syntax (Wireshark dfilter):
# IP address filters
ip.addr == 192.168.1.10
ip.src == 10.0.0.0/8 # CIDR notation supported
ip.dst != 192.168.1.1
# Protocol filters
tcp
udp
dns
http
tls
ospf
bgp
# Field comparison
tcp.flags.syn == 1 && tcp.flags.ack == 0 # SYN only (connection initiation)
http.request.method == "GET"
dns.flags.response == 1 && dns.qry.name contains "malware"
tls.handshake.type == 1 # ClientHello
# Combining filters
(ip.addr == 10.0.0.1) && (tcp.port == 443)
frame.len > 1400 # large frames (potential data exfiltration)
Capture filter syntax (BPF, applied at capture time -- much faster):
tcpdump -i eth0 -n "host 192.168.1.10"
tcpdump -i eth0 -n "tcp port 80 or tcp port 443"
tcpdump -i eth0 -n "not port 22" # exclude SSH (noisy in remote capture)
tcpdump -i eth0 -n "proto ospf"
Expert mode indicators: Wireshark marks packets with severity levels: Note (cyan), Warning (yellow), Error (red). Red packets indicate checksum errors, malformed segments, or retransmissions. In a capture from a troubled network, sort by Expert Info to find the problem quickly.
Statistics tools in Wireshark:
- Conversations (Ctrl+Alt+C): shows all IP pairs with bytes transferred; immediately reveals the "top talkers"
- Protocol Hierarchy (Ctrl+Shift+I): breakdown of protocol distribution in the capture
- I/O Graphs: time-series packet rate; useful for identifying traffic spikes
- Follow TCP/TLS/UDP Stream: reassembles all packets in a session into readable text
10.3 Suricata: Signature-Based Detection
Suricata is a multi-threaded IDS/IPS/NSM engine that processes network traffic against a rule set. It can run inline (blocking mode, IPS) or passively (NFQUEUE, PCAP, or AF_PACKET for monitoring).
Suricata rule anatomy:
action protocol src_ip src_port direction dst_ip dst_port (rule_options)
# Example: detect HTTP GET to a known malware C2 domain
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"Malware C2 HTTP GET";
http.method; content:"GET";
http.host; content:"evil.example.com"; nocase;
classtype:trojan-activity;
sid:9000001; rev:1;
)
# Detect outbound DNS TXT query (possible DNS tunneling)
alert dns $HOME_NET any -> any 53 (
msg:"Possible DNS Tunneling TXT Query";
dns.query; content:"|00 10|"; # TXT record type in DNS wire format
threshold: type both, track by_src, count 10, seconds 60;
sid:9000002; rev:1;
)
Suricata rule options vocabulary:
| Option | Meaning |
|---|---|
content:"STRING" |
match literal string in payload |
nocase |
case-insensitive match |
pcre:"/REGEX/i" |
Perl-compatible regex match |
http.uri |
match in HTTP URI |
http.host |
match in HTTP Host header |
http.method |
match HTTP method |
threshold: |
rate limiting / suppression for noisy rules |
flow:established |
only match on established TCP sessions |
classtype: |
categorizes the alert type |
sid: |
unique rule identifier; 1-999999 reserved for official rules; 1000000+ for local |
Running Suricata against a PCAP:
sudo suricata -c /etc/suricata/suricata.yaml \
-r /path/to/capture.pcap \
-l /tmp/suricata-output/
# View alerts
cat /tmp/suricata-output/fast.log
# or structured JSON:
cat /tmp/suricata-output/eve.json | jq '.[] | select(.event_type == "alert")'
Suricata Eve JSON log: all events (alerts, DNS, HTTP, TLS, flows) are logged to eve.json in structured JSON. This makes Suricata output trivially parseable by SIEM systems, ELK stack, or Python scripts.
10.4 Zeek: Protocol Analysis as Code
Zeek (formerly Bro) is a network analysis framework. Rather than matching byte patterns, Zeek dissects protocol state machines and generates structured log records. The conn.log records every connection; dns.log records every DNS transaction; http.log records every HTTP request; ssl.log records every TLS session.
Zeek log format (TSV, with header):
# conn.log sample
ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state
1234567890.0 CiJoFa... 192.168.1.10 52341 93.184.216.34 443 tcp ssl 0.254 1234 56789 SF
Zeek scripting (detecting long-duration connections -- possible exfiltration):
event connection_state_remove(c: connection)
{
if (c$duration > 3600 sec && c$resp_bytes > 1000000)
{
print fmt("ALERT: Long connection with large transfer: %s -> %s:%d duration=%s bytes=%d",
c$id$orig_h, c$id$resp_h, c$id$resp_p,
c$duration, c$resp_bytes);
}
}
Running Zeek against a PCAP:
zeek -C -r capture.pcap /opt/zeek/share/zeek/base/init-default.zeek
# View generated logs
ls -la *.log
# conn.log, dns.log, http.log, ssl.log, files.log, x509.log, ...
# Query conn.log for connections to port 443 with > 1MB transferred
zeek-cut ts id.orig_h id.resp_h resp_bytes conn_state < conn.log | \
awk '$4 > 1000000 {print}'
Zeek vs. Suricata: complementary roles
| Dimension | Suricata | Zeek |
|---|---|---|
| Detection model | Signature-based (rules) | Protocol-state + scripted behavioral analysis |
| Output | Alert events + protocol logs | Comprehensive protocol logs (no alerts by default) |
| Customization | Rule authoring (low barrier) | Script authoring in Zeek language (higher barrier) |
| Best for | Known-bad detection; IDS/IPS deployment | Unknown-bad investigation; behavioral baselining; forensic analysis |
NSM practitioners use both: Suricata for real-time alerting; Zeek for comprehensive protocol logging and custom behavioral detections.
10.5 The NSM Corpus
The NET-201 NSM corpus ships as a directory of ~20-30 PCAP files representing named TTPs (Tactics, Techniques, and Procedures). Each file has a corresponding ground-truth answer (what is in it). Lab 8 uses this corpus to evaluate Suricata rule and Zeek script effectiveness.
Sample corpus entries:
corpus/arp_poisoning.pcap: ARP poisoning attack with MITM traffic capturecorpus/dns_tunneling.pcap: DNS queries with encoded data in FQDN labelscorpus/tls_cert_anomaly.pcap: TLS connection with self-signed certificate to unusual destinationcorpus/bgp_update_anomaly.pcap: BGP UPDATE announcing a prefix not belonging to the announcing AScorpus/port_scan_syn.pcap: SYN scan against a /24 subnetcorpus/lateral_movement_smb.pcap: SMB lateral movement with PSEXEC-style execution
Lab Preview
Lab 8 processes the NSM corpus with both Suricata and Zeek:
- Run the full corpus through Suricata; examine false-positive and false-negative rates against ground truth
- Author one custom Suricata rule targeting a specific TTP; test against the relevant corpus file
- Process the DNS tunneling corpus file through Zeek; write a Zeek script that computes average FQDN label length per source; flag sources with unusually long labels (DNS tunneling signature)
- Generate a combined alert + log report: for each corpus file, list Suricata alerts triggered + Zeek log anomalies detected
Homework
Reading (45 min): Bejtlich, The Practice of Network Security Monitoring, Ch. 1 (What Is NSM?) and Ch. 9 (NSM in Practice). These chapters provide the operational context behind why Suricata and Zeek are used together. If you have Sanders, Practical Packet Analysis: read Ch. 8 (TCP/IP Analysis in the Real World) for Wireshark technique depth.
Hands-on (60 min): Write a Suricata rule to detect ICMP tunneling (ICMP payloads larger than 64 bytes are anomalous for normal ping traffic):
alert icmp any any -> any any (
msg:"Possible ICMP Tunneling Large Payload";
dsize:>64;
itype:8; # ICMP Echo Request
threshold: type both, track by_src, count 5, seconds 10;
sid:9000010; rev:1;
)
Generate a test PCAP using Scapy:
from scapy.all import *
pkts = [IP(dst="8.8.8.8")/ICMP(type=8)/"A"*200 for _ in range(10)]
wrpcap("/tmp/icmp_tunnel.pcap", pkts)
Run Suricata against /tmp/icmp_tunnel.pcap with your rule; confirm the alert fires. Then explain in your notes why this rule would generate false positives in a network with legitimate network diagnostic tools.
Toolchain Diary Entry
Deepen this week: Suricata (advanced rule authoring); Zeek (log analysis + scripting)
suricata -c CONFIG -r PCAP -l OUTPUT_DIR: run Suricata in PCAP replay mode; outputs logs to OUTPUT_DIR.
jq '.[] | select(.event_type == "alert") | .alert.signature' < eve.json | sort | uniq -c: count unique alert signatures from Suricata's eve.json.
zeek -C -r PCAP SCRIPT: run Zeek on a PCAP with a specific script (-C = ignore checksum errors, common in test captures).
zeek-cut FIELD1 FIELD2 < LOG_FILE: extract specific columns from a Zeek log file.
zeekctl deploy: deploy a Zeek cluster configuration (for live capture on production networks).
suricata-update: update Suricata rule sets from ET Open, ET Pro, and other rule sources.
Wireshark: Edit -> Preferences -> Protocols -> TLS -> (Pre)-Master-Secret log filename: enable TLS decryption using SSLKEYLOGFILE session key material.
Key Terms
- NSM: Network Security Monitoring; collection, detection, and analysis of network data to identify and characterize security threats; produces full packet capture, flow data, and protocol logs
- Suricata: multi-threaded IDS/IPS/NSM engine; rule-based detection; outputs alerts and structured protocol logs (eve.json); supports inline (IPS) and passive (IDS) modes
- Zeek: network analysis framework (formerly Bro); dissects protocol state machines; generates comprehensive structured logs; scripting language for behavioral detection
- Eve JSON: Suricata's primary structured output format; all event types (alerts, DNS, HTTP, TLS, flows) in one NDJSON log; ideal for SIEM ingestion
- Flow data: connection metadata (src/dst IP, port, protocol, bytes, duration) without payload; generated by NetFlow/IPFIX; long-term retention baseline for behavioral analysis
- Signature-based detection: matching network traffic against known-bad patterns (byte strings, regex, protocol states); high precision on known threats; blind to novel/unknown threats
- Behavioral detection: identifying anomalies against a baseline of normal network behavior; effective against novel threats; requires tuning to reduce false positives
- DNS tunneling: encoding arbitrary data in DNS query FQDNs or TXT record payloads to exfiltrate data or establish covert C2 channels through DNS-permitting firewalls
- PCAP: Packet Capture format; libpcap binary format for storing full network captures; universal input for Wireshark, Suricata, Zeek, and all NSM tools