Skip to main content
Rules tell Snort what network conditions are significant and what action to take when they are detected.

Rule structure

Every rule follows this format:
action proto source dir dest ( body )
FieldDescription
actionWhat Snort does when the rule fires: alert, block, drop, pass, reject, etc.
protoProtocol: ip, icmp, tcp, udp, or a service name like http
sourceSending IP address and port. Use any as a wildcard.
dirDirection: -> (unidirectional) or <> (bidirectional)
destReceiving IP address and port.
bodyDetection options and metadata inside parentheses.

Basic example

alert tcp any any -> 192.168.1.1 80 ( msg:"A ha!"; content:"attack"; sid:1; )
This fires on any TCP packet to 192.168.1.1:80 that contains the string attack.

Port-based vs service-based rules

Snort 3 supports two rule styles that differ in how traffic matching works.
The protocol and ports in the rule header are always evaluated:
# All header fields (proto, source, dest, ports) are checked
alert tcp any 90 -> any 5321 ( msg:"Port group rule"; )
Port-based rules are grouped into multipattern search engines keyed on protocol and port.
To match a service-based rule against a specific IP protocol, use the ip_proto IPS option:
alert ip ( ip_proto:2; content:"foo"; service:igmp; )
This guards against false positives from the rule also appearing in the “any” port group.

Common rule options

OptionDescription
msgHuman-readable description of the alert
sidSignature ID (unique within a GID)
gidGenerator ID. Text rules default to GID 1; SO rules to GID 3
revRevision number of the rule
OptionDescription
flowConstrain to flow state, e.g. established, to_server
contentMatch a literal byte string
nocaseMake the preceding content match case-insensitive
fast_patternMark this content as the fast pattern for the rule
pcreMatch a Perl-compatible regular expression
http_uriMatch in the HTTP URI buffer
file_dataMatch in the file data buffer
pkt_dataMatch in raw packet/TCP stream bytes
OptionDescription
classtypeAlert classification (maps to a priority)
referenceExternal vulnerability reference, e.g. reference:cve,2023-1234
serviceForce assignment to a service group
metadataArbitrary key-value pairs

Rule identification: gid:sid:rev

Rules are uniquely identified by the triplet gid:sid:rev.
  • GID 1 — text rules (the default)
  • GID 3 — shared-object (SO) rules
  • GID 1xx — internal Snort components (decoder is GID 116, etc.)
To list all internal GIDs and their built-in SIDs:
snort --list-gids
snort --list-builtin

Rule comments

Snort rules files support several commenting styles:
# Single-line comment

#begin
Every line in here is ignored by the rule parser.
#end

alert tcp any any -> any any ( msg:"test"; rem:"this is an inline comment"; sid:999; )

/* C-style block comment */

Fast patterns and rule groups

At startup, Snort compiles rules into multipattern search engines (MPSE). Rules are grouped by protocol, port, and service so that a single parallel search covers all patterns in a group.

Selecting the search algorithm

Configure via search_engine.search_method:
MethodTrade-off
ac_bnfaDefault. Balanced speed and memory.
ac_fullFastest search, significantly more memory.
HyperscanBest performance and reasonable memory. Requires Intel Hyperscan library.

Fast pattern selection

Snort automatically selects the longest content in a rule as its fast pattern. Add fast_pattern explicitly to override this choice:
alert tcp any any -> any any
(
    msg:"Targeted pattern";
    content:"common";             -- long but matches frequently
    content:"rare_marker"; fast_pattern;  -- short but highly specific
    sid:100;
)
Snort 3 automatically skips the fast pattern re-check during rule evaluation when it is redundant. You do not need the old fast_pattern:only Snort 2 option.
Certain contents are not eligible for fast pattern selection:
  • Negated contents that are also relative, case-sensitive, or have a non-zero offset/depth.

Rule group summary

At startup, Snort prints a summary under port rule counts and service rule counts. Use this to verify that rules land in the expected groups.

Stateful evaluation

When a match spans multiple packets (e.g., a file transferred over TCP), Snort pauses rule evaluation at the packet boundary and resumes when more data arrives. This is supported for:
BufferDescription
pkt_dataContiguous TCP session bytes, split by direction (client→server, server→client)
file_dataBytes from the same file transfer, across packets

Loading rules

1

ips.include in the config file

ips =
{
    include = 'rules.txt',          -- path to your rules file
    variables = default_variables   -- makes $HOME_NET etc. available
}
Rules files can themselves contain include statements to pull in additional files.
2

-R on the command line

snort -c snort.lua -R cool.rules
You can combine -R with ips.include; both sets of rules are loaded.
3

Inline with --lua

# Enable built-in decoder and inspector rules
snort -c snort.lua --lua 'ips = { enable_builtin_rules = true }'
4

From stdin

Pass rules through standard input using the --stdin-rules flag:
cat local.rules | snort -c snort.lua --stdin-rules
You can only specify one ips.include file directly, but that file can include others. Use the -R flag for additional top-level files.

Build docs developers (and LLMs) love