Tools · Network IDS and detection as code · 02 / 04
Suricata local rules: write one for your network and tune a noisy one
Write a local Suricata rule that flags DNS lookups of a retired internal domain, test it against a lab capture, and suppress a noisy ET rule for one known host with a threshold entry.
Rules that only your network needs
Public rulesets know about public threats. They do not know that billing-v1.hackblue-lab.org was retired and that any lookup of it means a client still has old configuration. A local rule turns that knowledge into an alert. Local rules use SIDs from 1000000 to 1999999 and live in their own file.
The rule
dns.query is a sticky buffer: content that follows it matches only the queried name. nocase handles mixed-case lookups. rev increments every time the rule changes.
# /etc/suricata/rules/local.rules alert dns $HOME_NET any -> any any (msg:"HB local - lookup of retired billing-v1 host"; \ dns.query; content:"billing-v1.hackblue-lab.org"; nocase; endswith; \ classtype:policy-violation; sid:1000101; rev:2;) # suricata.yaml rule-files: - suricata.rules - /etc/suricata/rules/local.rules
Proving it fires, and only when it should
Record a lab client resolving the name, replay it, and count alerts for the SID. Then replay a capture with ordinary traffic and confirm zero. Both pcaps go into the repository next to the rule as regression tests.
dig @10.8.0.53 billing-v1.hackblue-lab.org # on the lab client while capturing suricata -r /lab/pcaps/retired-lookup.pcap -l /tmp/t1 -k none jq 'select(.alert.signature_id==1000101)' /tmp/t1/eve.json | jq -s length 1 suricata -r /lab/pcaps/normal-day.pcap -l /tmp/t2 -k none jq 'select(.alert.signature_id==1000101)' /tmp/t2/eve.json | jq -s length 0
Worked tuning: a scanner that is supposed to scan
The vulnerability scanner at 10.8.0.5 triggers an ET SCAN rule thousands of times a week. Disabling the rule would hide a real scan from anywhere else. A suppress entry in threshold.config silences it for that source only, and a comment names the owner of the scanner.
# /etc/suricata/threshold.config # Nessus scanner, owner: vuln-mgmt team, reviewed 2026-11-01 suppress gen_id 1, sig_id 2010937, track by_src, ip 10.8.0.5 sudo suricatasc -c reload-rules
Diagram
Disabling a rule versus suppressing one source
Suppression keeps coverage for everyone else.
Effect. No alerts from anyone
Risk. A real scan from a new source goes unseen
Use when. The rule is wrong for your network
Effect. No alerts from 10.8.0.5 only
Risk. Small, if the scanner is controlled
Use when. One known system is the noise
Check yourself
1. Which SID range is meant for local rules?
2. What does dns.query do in the rule?
3. A known scanner triggers an ET rule constantly. What keeps coverage for other sources?