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

Popular Posts