Writing Suricata Rules for Dummies
Writing Suricata Rules for Dummies
Introduction
You’ve got Suricata running. Great. But then you open the rules file and see something like this:
alert tcp any any -> any 80 (msg:"Example rule"; sid:1000001; rev:1;)
Looks like gibberish, right? If you’re thinking “How am I ever supposed to write my own rules?” — you’re not alone.
Here’s the truth: Suricata rules aren’t magic, and they’re not as complicated as they first look. They’re just simple “if-then” statements for network traffic.
In this guide, you’ll learn how to read a rule, write your first custom one, and test it without breaking anything. By the end, you’ll go from staring blankly at rule syntax to writing working rules with confidence.
---
What is a Suricata Rule, Really?
At its core, a Suricata rule is just a simple instruction: “If this happens, then do that.”
Think of it like a security guard at the door. You tell the guard:
If someone walks in wearing a red hat, sound the alarm.
If someone tries to sneak in after midnight, write it down in the log.
Suricata works the same way — except instead of hats and doors, it’s watching packets on your network.
A rule tells Suricata three things:
1. What to look for — the traffic pattern or content (e.g. HTTP request, DNS query, suspicious keyword).
2. Where to look — the protocol, IPs, or ports it applies to.
3. What to do about it — alert, drop, or log the traffic.
Once you see rules as if-then statements, they stop being intimidating.
---
Anatomy of a Basic Rule
Let’s take the example again:
alert tcp any any -> any 80 (msg:"Example rule"; sid:1000001; rev:1;)
Here’s what each piece means:
Action: alert → what to do when traffic matches (alert, drop, pass).
Protocol: tcp → which protocol to inspect (tcp, udp, icmp, etc.).
Source & Destination: any any -> any 80 → traffic from any IP/port going to port 80.
Options: (msg:"Example rule"; sid:1000001; rev:1;) → the details inside brackets.
Put it all together, and in plain English it says:
👉 “If TCP traffic goes from anywhere to port 80, raise an alert with the message ‘Example rule’ (rule ID 1000001, version 1).”
---
Writing Your First Custom Rule
Let’s write a simple one to spot HTTP traffic:
alert tcp any any -> any 80 (msg:"HTTP traffic detected"; sid:1000001; rev:1;)
How to test it:
1. Add it to your local rules file:
/var/lib/suricata/rules/local.rules
2. Check the syntax:
sudo suricata -T -c /etc/suricata/suricata.yaml -v
3. Restart Suricata:
sudo systemctl restart suricata
4. Visit an HTTP site (e.g. http://example.com).
5. Check the logs:
tail -f /var/log/suricata/fast.log
If you see your alert message, congrats — you wrote your first rule 🎉.
---
Common Keywords Explained Simply
Inside the brackets, options define the details of your rule. The most useful ones for beginners are:
msg → alert message. Example:
msg:"Possible SSH brute force";
sid → unique rule ID. Use 1,000,000+ for your custom rules. Example:
sid:1000001;
rev → revision number. Start at rev:1; and bump it whenever you edit the rule.
content → match specific text. Example:
content:"/wp-login.php";
http_uri → check the URI in HTTP requests. Example:
content:"/admin"; http_uri;
flow → traffic direction. Example:
flow:to_server,established;
classtype → optional category for the alert. Example:
classtype:web-application-attack;
Example Rule:
alert http any any -> any 80 (msg:"Attempt to access admin page"; content:"/admin"; http_uri; sid:1000002; rev:1; classtype:web-application-attack;)
Plain English: “If HTTP traffic goes to port 80 and the URI contains ‘/admin’, raise an alert with this message.”
---
SID Ranges (Cheat Sheet)
Keep SIDs organised to avoid clashes:
1–999,999 → Reserved for official/public rulesets (e.g. Emerging Threats).
1,000,000–1,999,999 → Your custom rules.
2,000,000+ → Rarely used, sometimes by vendors or researchers.
👉 Tip: Create your own numbering scheme. Example:
1000000–1000099 → HTTP rules
1000100–1000199 → DNS rules
1000200–1000299 → SSH rules
---
Testing Your Rule Safely
1. Add rule to local.rules:
/var/lib/suricata/rules/local.rules
2. Test syntax before restarting:
sudo suricata -T -c /etc/suricata/suricata.yaml -v
3. Restart Suricata:
sudo systemctl restart suricata
4. Generate test traffic (visit site, run curl, or replay a PCAP).
5. Check alerts in:
/var/log/suricata/fast.log
✅ Always test in a lab or with PCAPs before putting rules into production.
---
Avoiding Common Mistakes
Reusing SIDs → Always pick unique IDs.
Not updating rev → Increment when you edit a rule.
Rules that are too broad → Avoid any any -> any any.
Overusing any → Be specific with ports/protocols.
Testing on live systems → Use a lab or PCAPs first.
Performance issues → Keep rules simple and targeted.
Vague msg values → Be descriptive so alerts are meaningful.
---
Next Steps
Now that you’ve written and tested your first rules, here’s how to keep going:
1. Stay organised
Keep all custom rules in:
/var/lib/suricata/rules/local.rules
Track your SIDs to avoid duplicates.
2. Learn from existing rules
Check the Emerging Threats Open ruleset.
Study how experienced rule writers use keywords.
3. Experiment
Try new keywords like dns_query, http_host, or pcre (regex).
Build rules step by step, testing as you go.
4. Use PCAPs for safe testing
Replay packet captures to check if your rules trigger.
5. Keep learning
Docs: https://suricata.io/documentation/
Rulesets: https://rules.emergingthreats.net/
---
👉 Bottom line: Suricata rules are just structured “if-then” statements for network traffic. Start simple, be specific, and test carefully. With practice, you’ll go from “dummy” rules to powerful detections tailored to your network.
Comments
Post a Comment