Snort规则语法:规则头与规则选项

Snort的规则,说白了就是一张「攻击行为描述卡」。你告诉Snort:看到什么样的流量,就给我报警。我刚开始接触Snort时,觉得这语法挺啰嗦的。但用久了你会发现,它的设计其实很巧妙——把「谁跟谁通信」和「通信内容长什么样」分开了。

嗯,咱们今天就把规则拆成两半来讲:规则头和规则选项。

规则头:定义「谁跟谁」

规则头决定了这条规则匹配什么样的网络会话。它的结构长这样:

action protocol src_ip src_port direction dst_ip dst_port

我一个个说。

1. action(动作)

Snort匹配到规则后干什么?常见的有:

  • alert:报警,记录日志
  • log:只记录,不报警
  • pass:忽略这条流量
  • drop:直接丢弃(inline模式)
  • reject:丢弃并回复RST

我个人习惯,刚开始写规则时先用alert。等确认规则没问题了,再改成drop或reject。不然误封了正常业务,运维同事会来找你喝茶的。

2. protocol(协议)

支持tcp、udp、icmp、ip。大部分攻击走TCP,所以这个字段最常见。

3. src_ip 和 dst_ip(源/目的IP)

可以写单个IP、网段,或者用any表示任意IP。举个例子:

alert tcp 192.168.1.0/24 any -> 10.0.0.1 80

这条规则只匹配内网192.168.1.x访问10.0.0.1的80端口。

避坑指南:我曾经在写规则时把src_ip和dst_ip写反了,结果内网扫描器扫外网,Snort死活不报警。排查了半天才发现方向反了。你想想看,方向错了,规则就废了。

4. src_port 和 dst_port(源/目的端口)

可以写具体端口,也可以用any。支持范围写法,比如1:1024表示1到1024端口。

5. direction(方向)

两个符号:

  • ->:单向,只匹配从左到右
  • <>:双向,两边都匹配

大部分场景用单向就够了。双向一般用在DNS、NTP这类请求-响应不对称的协议上。

规则选项:定义「长什么样」

规则头搞定了「谁跟谁通信」,规则选项则描述「通信内容有什么特征」。这才是Snort规则的精髓。

1. content(内容匹配)

这是最核心的选项。你告诉Snort:在数据包里找某个字符串或十六进制数据。

alert tcp any any -> any 80 (content:"GET /admin"; msg:"访问后台";)

这条规则匹配HTTP请求里包含"GET /admin"的流量。

content支持很多修饰符,常用的有:

  • nocase:忽略大小写
  • depth:只在前N个字节里搜索
  • offset:从第N个字节开始搜索
  • within:在N个字节范围内必须出现

举个例子:

content:"|0d 0a|"; depth:10;

这条规则只在前10个字节里找0d 0a(回车换行)。为什么要限制depth?因为数据包可能很大,不限制范围的话,Snort的性能会崩。我在项目中遇到过,有人写了一条content规则没加depth,结果Snort直接把CPU跑满了。

2. sid(规则ID)

每条规则必须有一个唯一的ID。Snort官方规则用100万以下的ID,用户自定义规则建议用100万以上。比如:

sid:1000001;

sid不能重复,否则Snort会报错。我习惯用日期加序号来命名,比如20241001_001。

3. rev(版本号)

规则修改一次,rev加1。方便你追踪规则版本。比如:

rev:3;

表示这是第三条版本。

4. msg(报警信息)

报警时显示的文字。写清楚点,方便后续分析。比如:

msg:"检测到SQL注入尝试 - union select";

别写「可疑流量」这种模糊的描述。你想想看,半夜收到报警,看到「可疑流量」四个字,你根本不知道该怎么办。

5. classtype(分类)

把规则归到某个攻击类别里。Snort预定义了很多分类,比如:

classtype说明
attempted-admin尝试获取管理员权限
attempted-user尝试获取普通用户权限
web-application-attackWeb应用攻击
shellcode-detect检测到shellcode
successful-admin已成功获取管理员权限

分类有什么用?方便你后续做统计和过滤。比如我只想看「成功入侵」类的报警,直接按classtype过滤就行。

一个完整的规则示例

把上面这些拼起来,一条完整的Snort规则长这样:

alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (
  msg:"检测到SQL注入 - union select尝试";
  content:"union"; nocase;
  content:"select"; nocase; within:20;
  classtype:web-application-attack;
  sid:20241001;
  rev:1;
)
重点总结:规则头定义「谁跟谁」,规则选项定义「长什么样」。写规则时,先想清楚你要检测什么流量,再决定用哪些选项。content是最强大的武器,但一定要加范围限制,不然性能会崩。

好了,Snort规则的基本语法就这些。说白了就是「告诉Snort看什么、怎么看、看到了怎么办」。下一章咱们聊聊如何用这些规则去绕过IDS——嗯,攻防是一体的,懂攻击才能更好地防御。