Network Intermediate IDS / Network Detection / Rule Writing

Suricata IDS � Rules & Analysis

A practical guide to Suricata � rule anatomy, actions, protocol keywords, writing custom detection rules, analysing EVE JSON alerts, and tuning for low-noise detection.

20 min read 20+ example rules Blue Team

// What is Suricata?

Suricata is a free, open-source network threat detection engine developed by the Open Information Security Foundation (OISF). It functions as an Intrusion Detection System (IDS), Intrusion Prevention System (IPS), and Network Security Monitor (NSM). Suricata inspects network traffic in real time and matches packets against a rule set to generate alerts, drop traffic, or log network metadata.

Suricata supports the same rule syntax as Snort, making existing Snort rule sets directly compatible. It also extends beyond Snort with multi-threading, file extraction, TLS fingerprinting (JA3), and native EVE JSON output for SIEM ingestion.

EmergingThreats (ET) Open and ET Pro rule sets are the most widely used free and commercial rule sets for Suricata. Install them with suricata-update to get thousands of community-maintained detections.

// Rule Anatomy

Every Suricata rule follows the same structure: action protocol src_ip src_port direction dst_ip dst_port (options)

# Full rule example � detect Mimikatz LSASS dump over the network
alert tcp $HOME_NET any -> $HOME_NET any (
    msg:"ET LATERAL MOVEMENT Mimikatz LSASS Dump";
    content:"|4c 4d 41 53 53|"; /* LMASS */
    depth:8;
    sid:9001001;
    rev:1;
    classtype:credential-theft;
    metadata:affected_product Windows, attack_target Client_Endpoint;
)

// Actions

ActionModeEffect
alertIDS / IPSGenerate an alert and log the packet. Does not block traffic.
dropIPS onlyDrop the packet and generate an alert. Requires inline/IPS mode.
rejectIPS onlyDrop packet and send TCP RST (or ICMP unreachable for UDP) to both sides.
passIDS / IPSAllow the packet through and skip further rule matching � used for whitelisting.
logIDSLog the packet without alerting � useful for capturing specific traffic silently.

// Protocol Headers

FieldOptionsNotes
Protocoltcp, udp, icmp, http, dns, tls, smtp, sshLayer 7 protocols enable keyword matching specific to that protocol
Source/Dest IPany, $HOME_NET, $EXTERNAL_NET, 192.168.1.0/24, !10.0.0.0/8Variables defined in suricata.yaml
Source/Dest Portany, 80, !443, [80,8080], [1024:65535]Port ranges use colon notation
Direction-> (one-way), <> (bidirectional)Use <> to match traffic in either direction

// Key Rule Options

OptionPurposeExample
msgAlert message shown in logsmsg:"ET MALWARE Beacon";
contentMatch a specific string or byte patterncontent:"User-Agent|3a|";
nocaseCase-insensitive content matchcontent:"powershell"; nocase;
pcrePerl-compatible regex matchpcre:"/[a-z]{15,}\.ru/i";
depthOnly search first N bytesdepth:100;
offsetStart searching from byte Noffset:4;
distanceN bytes after last matchdistance:0;
withinMatch within N bytes of previouswithin:50;
thresholdLimit alert frequency (rate limiting)threshold:type limit, track by_src, count 5, seconds 60;
flowSpecify traffic direction in sessionflow:to_server,established;
http.uriMatch on HTTP URI (normalised)http.uri; content:"/admin/login";
http.user_agentMatch on HTTP User-Agent headerhttp.user_agent; content:"curl/7";
dns.queryMatch on DNS query namedns.query; content:".onion.ly";
sidUnique rule ID (required)sid:1000001; � use >1000000 for custom rules
revRule revision number (required)rev:1;

// Example Rules

Detect PowerShell download over HTTP

alert http $HOME_NET any -> $EXTERNAL_NET any (
    msg:"ET MALWARE PowerShell DownloadString";
    flow:to_server,established;
    http.user_agent; content:"WindowsPowerShell"; nocase;
    http.uri; content:"DownloadString"; nocase;
    sid:1000001; rev:1;
)

Detect Cobalt Strike default HTTPS certificate

alert tls $EXTERNAL_NET any -> $HOME_NET any (
    msg:"ET C2 Cobalt Strike Default TLS Certificate";
    tls.cert_subject; content:"CN=Major Cobalt Strike";
    sid:1000002; rev:1;
)

Detect DNS query to .onion relay domain

alert dns $HOME_NET any -> any 53 (
    msg:"ET TOR DNS Query to .onion Relay Domain";
    dns.query; content:".onion"; endswith;
    sid:1000003; rev:1;
)

Detect unusually long DNS query (tunneling)

alert dns $HOME_NET any -> any 53 (
    msg:"ET DNS Unusually Long DNS Query - Possible Tunneling";
    dns.query; isdataat:60,relative;
    sid:1000004; rev:1;
)

// EVE JSON Logs

Suricata outputs alerts, DNS, HTTP, TLS, and file transaction logs in EVE JSON format � a single structured log file that can be ingested into Elasticsearch (ELK Stack), Splunk, or Microsoft Sentinel.

# Example EVE JSON alert event
{
  "timestamp": "2025-01-15T10:22:31.001234+0000",
  "event_type": "alert",
  "src_ip": "10.1.1.50",
  "src_port": 54321,
  "dest_ip": "185.220.101.47",
  "dest_port": 443,
  "proto": "TCP",
  "alert": {
    "action": "allowed",
    "gid": 1,
    "signature_id": 2019401,
    "rev": 4,
    "signature": "ET C2 Known Bad SSL Cert",
    "category": "Malware Command and Control Activity"
  }
}

Enable eve-log types beyond alerts � HTTP, DNS, and TLS logs provide context even when no alert fires. A malware connection to an unknown IP may not trigger an alert, but the TLS certificate in the TLS log may reveal the C2 infrastructure.

// Tuning

Suppress noisy rules. Use the suppress directive to silence known-good traffic without disabling the rule entirely. Example: suppress gen_id 1, sig_id 2001219, track by_src, ip 10.1.1.100

Use threshold to rate-limit alerts. A single port scan can generate thousands of alerts. Use threshold:type both, track by_src, count 10, seconds 60; to get one alert per minute per source.

Custom SIDs must be above 1,000,000. SIDs 1�999999 are reserved for the Snort/ET rule set. Using low SIDs in custom rules causes conflicts when updating the official rule set.