Cheat sheet — Intrusion Detection (Suricata)¶
Companion to Module 05 — Intrusion Detection · CC BY 4.0 — print it, pin it, share it.
Last reviewed: 2026-07
Run Suricata¶
suricata -r capture.pcap -l ./logs/ # offline: run rules over a PCAP, output to ./logs
suricata -i eth0 # live capture on an interface
suricata -T -c /etc/suricata/suricata.yaml # test config + rules, then exit (do this first)
suricata --list-runmodes # available run modes
suricata-update # fetch/update the ET Open ruleset
Alerts land in logs/eve.json (parse with jq) and logs/fast.log (one line each).
jq -c 'select(.event_type=="alert") | {sig:.alert.signature, sid:.alert.signature_id, src:.src_ip, dst:.dest_ip}' logs/eve.json
Rule anatomy¶
action header (options)
alert tcp $HOME_NET any -> $EXTERNAL_NET 443 (msg:"..."; sid:1000001; rev:1;)
└────┘ └─┘ └──────┬──────┘ └──────┬────────┘
action proto source destination + direction
- action:
alert(IDS) ·drop/reject(IPS, inline) ·pass - proto:
tcpudpicmpip, or app-layerhttpdnstlsssh - direction:
->(one way) or<>(either);anymatches any port/host - Every rule needs a unique
sidand arev(revision).
Rule options — the payload/content matchers¶
alert http $HOME_NET any -> $EXTERNAL_NET any ( \
msg:"Suspicious User-Agent"; flow:established,to_server; \
http.user_agent; content:"EvilBot"; nocase; \
classtype:trojan-activity; sid:1000002; rev:1;)
Common options:
content:"str"; nocase; depth:N; offset:N; distance:N; within:N; # byte matching
pcre:"/regex/i"; # regex (slower)
flow:established,to_server; flowbits:set,name; # state
http.uri; http.host; http.header; dns.query; tls.sni; # sticky buffers
threshold:type limit, track by_src, count 5, seconds 60; # rate-limit noise
reference:cve,2021-44228; metadata:...; classtype:...; # context
Emerging Threats rulesets¶
suricata-update list-sources # available rule feeds
suricata-update enable-source et/open # the free community set (ET Open)
suricata-update # download + merge into /var/lib/suricata/rules
ET rule SIDs live in the 2000000–2999999 range; keep your own in 1000000+ to avoid collisions.
Gotchas worth remembering¶
- IDS alerts; IPS blocks — same engine, different risk. Put a rule inline with
dropand a false positive becomes an outage. Tune in IDS mode first, promote to IPS only when it's proven quiet. - Signatures are exact-match: high-confidence but easy to evade. A new domain, new TLS fingerprint, or a padded payload slips a byte-precise rule. Read the rule to know what it actually keys on before trusting it.
- A noisy ruleset is worse than no IDS. Constant false positives train analysts to ignore alerts, so the one real hit gets ignored too.
threshold/suppressand tuning are the daily job, not an afterthought. - Sticky buffers change scope.
contentafterhttp.uri;matches only the URI; the samecontentwith no buffer matches the raw packet. Getting this wrong is why a rule "should fire" but doesn't. - Run
-Tbefore deploying. One malformed rule can stop the whole engine loading. Test the config offline against a known-bad PCAP so you've seen it fire — you can't trust a rule you've never watched trigger. - Prefer community rules; stand on others' work. ET Open encodes thousands of maintained signatures. Write your own only for the gap the feed doesn't cover.
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).