Suricata Setup
Suricata is a high-performance network intrusion detection (IDS), inline prevention (IPS), and network security monitoring (NSM) engine. Unlike Zeek (which focuses on structured logging of all activity), Suricata's primary mode is signature-based: rules are applied against traffic in real-time and alerts are generated when traffic matches. Suricata also produces protocol logs like Zeek (EVE JSON) — the two tools are complementary in a production NSM stack.
A SOC deploys both Zeek and Suricata on the same network tap. Zeek provides the structured metadata record (conn.log, ssl.log, dns.log) that supports hunting and historical investigation. Suricata provides real-time alert generation based on ET Open rules and custom rules written by the detection engineering team. When Suricata fires an alert, the analyst looks up the corresponding uid in Zeek's logs for full protocol context.
Suricata Architecture
Suricata Processing Pipeline ═══════════════════════════════════════════════════════════════════ Packet input sources: ├── AF_PACKET: zero-copy, multi-threaded (recommended for Linux) ├── PF_RING: commercial high-speed option ├── PCAP file: offline analysis (suricata -r capture.pcap) └── Inline (IPS mode): via NFQ (netfilter queue) or AF_PACKET XDP Packet processing: ├── Decode threads (N): decode Ethernet/IP/TCP/UDP headers ├── Stream engine: TCP reassembly, stateful tracking ├── App layer detection: HTTP, TLS, DNS, SMTP, SMB, SSH, ... │ (DPI, not port-based — identifies protocols on any port) └── Worker threads (N): apply detection rules to decoded traffic Detection: ├── Rules loaded from: /etc/suricata/rules/ ├── Rule evaluation: fast pattern matching → detailed checks ├── Alert generation on match → eve.json └── Threshold engine: suppress repeated alerts Output: ├── eve.json: JSON events (alerts + protocol logs) │ alert events: rule match details │ dns events: queries + responses │ http events: requests + responses │ tls events: handshake metadata + JA3 │ flow events: connection summaries (like Zeek conn.log) ├── fast.log: one line per alert (less detail than eve.json) └── stats.log: performance counters
Installation and Configuration
#!/bin/bash
echo "=== Install Suricata (Ubuntu) ==="
add-apt-repository ppa:oisf/suricata-stable
apt-get update
apt-get install -y suricata suricata-update
echo ""
echo "=== Update rules with suricata-update ==="
suricata-update update-sources # List available rule sources
suricata-update enable-source et/open # Enable Emerging Threats Open rules
suricata-update # Download and install rules
echo ""
echo "=== Key suricata.yaml settings ==="
cat > /tmp/suricata-key-settings.yaml << 'YAML'
# /etc/suricata/suricata.yaml — key settings
vars:
address-groups:
HOME_NET: "[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16]"
EXTERNAL_NET: "!$HOME_NET"
port-groups:
HTTP_PORTS: "80"
HTTPS_PORTS: "443"
DNS_PORTS: "53"
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: /var/log/suricata/eve.json
types:
- alert:
payload: yes # Include raw packet bytes (base64)
payload-buffer-size: 4kb
metadata: yes
tagged-packets: yes
- dns:
enabled: yes
- http:
enabled: yes
extended: yes
- tls:
enabled: yes
extended: yes # Includes JA3
- flow:
enabled: yes
- smtp:
enabled: yes
af-packet:
- interface: eth0
threads: auto
cluster-id: 99
cluster-type: cluster_flow # Hash by flow 5-tuple (critical!)
defrag: yes
use-mmap: yes
ring-size: 200000
detect:
threads: auto
profile: medium # low/medium/high — tradeoff between speed and memory
app-layer:
protocols:
tls:
enabled: yes
detection-ports:
dp: 443
dp: "[4444, 31337, 8443, 8080]" # Catch C2 on common alt ports
http:
enabled: yes
dns:
enabled: yes
smtp:
enabled: yes
ssh:
enabled: yes
YAML
echo ""
echo "=== Test configuration ==="
suricata --test -c /etc/suricata/suricata.yaml
echo ""
echo "=== Start Suricata ==="
systemctl start suricata
systemctl enable suricata
echo ""
echo "=== Run against PCAP (testing) ==="
suricata -r capture.pcap -c /etc/suricata/suricata.yaml -l /tmp/suricata-output/
ls /tmp/suricata-output/
They're not duplicates — they provide fundamentally different data. Suricata answers: "Did something in this traffic match a known-bad pattern right now?" Zeek answers: "What was the complete structured record of all network activity over the last 30 days?" Suricata is your alert engine — it fires when a rule matches, requiring no prior knowledge by the analyst. Zeek is your investigation database — you can query it for any attribute of any connection from the past month without needing to have predicted in advance what you'd want to look for. In practice: Suricata alerts are the trigger for an investigation; Zeek logs are the primary data source for that investigation. Without Suricata you miss real-time detection of known threats. Without Zeek you have no retrospective visibility — when Suricata fires an alert, you'd have no way to check what the same host was doing yesterday, or whether the beaconing started 2 weeks ago.
Q & A
Q: Suricata is generating thousands of alerts per day. Most are low-quality. How do I reduce noise?
High alert volume from Suricata is almost always a ruleset tuning problem, not a Suricata configuration problem. Approach: (1) Threshold frequently-firing rules: for rules that fire hundreds of times per day, add a threshold.conf entry: threshold gen_id 1, sig_id 2019401, type threshold, track by_src, count 5, seconds 60 — this fires the alert only once per source per minute. (2) Suppress known-good sources: if your patch management system triggers a Nessus scan rule, suppress it for the scanner's IP: suppress gen_id 1, sig_id 2019401, track by_src, ip 10.0.0.5. (3) Disable low-value rule categories: in suricata-update's suricata.rules, comment out entire categories like "emerging-info" (informational, rarely actionable) and "emerging-games" (game traffic detection, not useful in enterprise). (4) Score-based triage: route all alerts to Elasticsearch and build a Kibana dashboard that shows alert counts by rule. Identify the top 10 rules generating the most volume and tune each one. (5) Drop-in alert enrichment: enrich alerts with asset context (is the affected IP a production server vs. a test machine?) — a high-severity alert against a staging host may be low-priority.