拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

snort入侵检测系统实战:规则编写与误报漏报调优指南

snort入侵检测系统实战:规则编写与误报漏报调优指南

简介:围绕 Snort 入侵检测系统使用的一册 PDF 文档,面向网络通信安全课程学习者、高校学生、网络管理员以及准备等级保护相关工作的技术人员。文档从实验目的出发,明确实验所需的软硬件环境,并对照等级保护 2.0 标准,指出应在关键网络节点处监视网络攻击行为(二级)以及检测、防止或限制从外部发起的攻击(三、四级)。实验部分详细讲解如何利用 Nmap 端口扫描工具对配置好 Snort 的主机进行扫描,从而触发并验证入侵检测告警;原理部分系统介绍入侵检测系统(IDS)的概念、1980年的起源与后续发展,以及 Nmap 在信息收集和网络安全审计中的典型用法。资源压缩包共 1 个 PDF 文件,大小 367KB,已有 1238 人学习。文档包含实验拓扑图、Snort 启动步骤、基于 Web 界面的告警查看方法以及 TCP 协议分析示例,读者可按步骤复现整个验证流程,快速掌握 Snort 的基本配置与使用技巧,深入理解主动安全防护技术在真实网络中的应用。

1. snort 入侵检测系统在网络通信安全里的角色:误报与漏报之间取平衡

很多团队第一次接触网络通信安全时,都会拿到一份《网络通信安全:snort 入侵检测系统使用.pdf》,装完 snort 把告警日志跑起来,发现告警特别多,或者特别少,然后就开始怀疑这台设备是不是“白装了”。这不是 snort 的问题,问题在于我们把它当成一个开箱即用的盒子,而不是一套需要持续调校的检测规则引擎。

snort 是开源轻量级网络入侵检测系统(NIDS),它把网卡上镜像过来的流量和规则库做匹配,命中之后输出告警。它不阻断流量,只负责“看见”和“说一声”。它适合那些买不起商业 IPS、或者想在防火墙之外加一双眼睛的运维和安全工程师。最反直觉的一件事是:一台 snort 装了三年、规则没更新、HOME_NET 还留着默认值,它的告警价值还不如不开机——因为误报刷屏会让人忽略真正重要的告警,漏报则让人产生虚假安全感。这篇文章从安装配置、规则编写到排查踩坑,按生产环境能用的标准讲一遍。

2. 从抓包到告警:snort 的工作模式、规则匹配与部署选型

2.1 三种工作模式:嗅探、记录、检测,生产环境只关心第三种

snort 的命令行参数决定了它跑在哪一种模式。很多 PDF 资料习惯把三种模式分开讲,我一般会直接告诉新同事:记住能进生产环境的只有一种,就是使用 -c 指定配置文件的检测模式。

模式启动方式行为用途
嗅探模式snort -v / -vd实时把网卡收到的包打印到终端确认网卡是不是真的收到流量
记录模式snort -l 日志目录把抓到的包按流写入 pcap 文件取证、事后分析
检测模式snort -c /etc/snort/snort.conf按规则匹配流量并输出告警生产环境唯一选择

嗅探模式只适合开局排错。我见过有人拿 snort -vd 当作终极抓包工具用,盯了一屏幕十六进制内容,退出去发现规则一条没跑,原因就是没接 -c。记录模式最容易被忽略的价值在于回放:后面我要讲的 pcap 回放验证规则,依赖的就是 -l 落盘的流量文件。

检测模式下还需要把网卡设成混杂模式(promiscuous),否则抓不到目的 MAC 不是自己的包。常见的做法是安装时勾选,或者在 ifcfg 文件里配置 PROMISC=yes。这一步不做,后面所有基于镜像端口的部署都会是空转。

2.2 snort 2 和 snort 3 怎么选:写给从旧资料起步的人

网上能找到的资料包括那本 .pdf,大部分基于 Snort 2.x:配置文件是 snort.conf,自检命令是 snort -T,回放命令是 -r。Snort 3 的命令和配置体系变成 snort.lua,参数也有变化,这让不少照着老文档操作的人第一步就卡住。

我的建议分两种情况:如果你是要在生产环境长期维护,直接装 Snort 3,规则语法主体和 Snort 2 基本兼容,但性能和多线程支持好得多;如果你只是要对照手边这份 PDF 做学习验证,那就装 2.9.x 系列,命令完全对得上,降低挫败感。最怕的是装了 snort3 却拿 snort2 的文档强行操作,最后检查发现配置文件压根没被读进去。

snort 规则本身是跨版本稳定的:规则头部的动作、协议、源目地址、源目端口、方向箭头,加上规则选项里的 content、msg、sid、rev,这两个版本都认。换版本主要影响配置加载方式和部分预处理器参数,规则文件的编写手感几乎不变。

2.3 一个数据包进来到出告警,中间发生了什么

数据包从网卡到告警日志,中间要过四道工序:采集、预处理、规则检测、输出。采集层由 DAQ 实现,常见后端是 libpcap 和 afpacket,afpacket 在 Linux 上性能更好;预处理层做流重组、分片重组、端口扫描检测,把畸形包和跨分片的攻击还原成完整会话;规则检测引擎拿重组后的流和规则库逐条比对;命中后输出到 fast 日志、unified2 二进制日志或 syslog。

这个流程解释了为什么 snort 对 TCP 的攻击检测必须放在“流重组之后”。一条 HTTP 攻击请求被拆成多个小段也没关系,预处理器先把它们拼回完整的流,规则里的 content 才能匹配到完整特征。这也是后面讲 flow:established 和 http_uri 的底层原因——不做流重组,单包匹配会带来大量误报和漏报。

2.4 部署位置选在哪里,决定了 snort 能不能发挥作用

常见做法是把 snort 放在旁路,通过交换机镜像口收流量,一台小主机、一块独立网卡就够了。镜像口配置的时候要特别注意方向:SPAN 端口默认只镜像单向流量,必须确认入方向和出方向都打开,否则 TCP 握手包只看到一半,后面所有流状态判断都会错位。

如果要做 IPS 阻断,snort 支持串联部署,配合 iptables 的 NFQUEUE 实现丢弃动作。但我见过更多失败案例集中在旁路模式下:交换机上配了镜像口,网卡也设了混杂,告警就是不出。排查到最后往往是镜像方向开反了,或者镜像的是 CPU 口而不是流量口。硬要总结一句部署经验的话:旁路模式先保证 tcpdump 能看到双向流量,再接 snort,这能省掉一大半排查时间。

3. 在 Ubuntu 上把 snort 跑起来:最小安装配置与三条必调参数

3.1 安装方式与最小命令

以 Ubuntu 系统为例,最常见的安装方式是直接用 apt 安装 snort。它会自动安装依赖的 libpcap、daq 等库,并在安装过程中提示你选择检测网段。这个提示对应的是 HOME_NET 的初始值,后面建议手工再改精确一点,不能完全相信安装时的自动探测结果。

sudo apt update sudo apt install snort -y

装完后先确认安装版本和默认配置路径,再验证一条规则都不写的情况下 snort 能否正常启动。这里有一句要说在前面:apt 源里的 snort 版本往往不是最新的,生产环境如果需要跟随规则包版本做严格匹配,就得上官网下载 tarball 编译,但那属于可控范围内的额外成本,新手期没必要。

snort -V sudo snort -T -c /etc/snort/snort.conf

第一条命令查看版本,第二条命令让 snort 做配置自检。自检会逐条解析规则文件并报告加载了多少条规则,如果出现 ERROR,先把配置文件里对应的行修好再继续。很多问题在 -T 阶段就会暴露,不用等到跑起来才在日志里找原因。

3.2 首次启动前必须做的事情:验证配置、检查规则、确认网卡

启动 snort 之前,我习惯按顺序过三件事:看 /etc/snort 目录结构、确定网卡名称、确认日志目录可写。目录结构决定了你后面改规则时去哪里找文件。

ls -R /etc/snort ip link show

/etc/snort 下一般有 snort.conf、rules 目录、threshold.conf 等文件。规则目录里默认带一批社区规则,但那个清单里不少规则在最小安装场景下并不生效,这里不用纠结,重点是确认 local.rules 存在。网卡名称在 Ubuntu 上常见是 eth0 或 ens33,虚机的网卡名更是千奇百怪,不要想当然地用 eth0 启动。

正式启动检测模式,把告警输出到终端,便于首次验证:

sudo snort -c /etc/snort/snort.conf -i eth0 -A fast

如果 snort 成功启动,终端会出现初始化日志并停在抓包状态,Ctrl+C 退出时会打印流量统计。看到这些输出,说明 snort 至少已经在监听网卡了。没有输出或者直接报 pcap 打开失败,先回网卡名称和权限问题上找原因。

3.3 三条必调参数:HOME_NET、规则包含、输出格式

这三条参数决定 snort 对你的网络是否“找得着北”,也是 snort 部署里最容易抄错的地方。

第一是 HOME_NET。打开 /etc/snort/snort.conf,找到 ipvar HOME_NET 的定义,默认值可能是 any 或者安装时探测到的网段。生产环境必须改成自己需要被监控的内网网段,例如 10.0.0.0/24;EXTERNAL_NET 保持为 !$HOME_NET。HOME_NET 设成 any 会让大量基于方向判断的规则失效或误报,这是新手上路第一坑。

第二是规则包含。确认 snort.conf 里有 include $RULE_PATH/local.rules 这一行,确保自己写的规则能被加载。有些资料会建议把全部社区规则都放开,我不建议那样做。规则越少越容易定位问题,先把 local.rules 用起来,再逐步放开需要的规则集。

第三是输出格式。测试阶段用 -A fast 看文本告警最直观;生产环境日志量大,可以换 unified2 二进制格式再配合后处理工具读取。日志目录 /var/log/snort 如果不存在,snort 会拒绝启动或者告警写不进去,需要手工 mkdir 并给 snort 用户写权限。

sudo mkdir -p /var/log/snort sudo chown snort:snort /var/log/snort

日志目录权限问题在编译安装的场景下更常见,apt 安装一般会帮你建好。但权限这事值得单独提醒,因为 snort 启动时若发现日志目录不可写,可能不会立刻退出,而是把告警全丢进 syslog,等你去翻的时候什么都找不到。

3.4 规则文件从哪里来:基础规则和更新机制

snort 的规则一般分三类:社区规则免费但覆盖面有限,官方订阅规则质量高但需要注册;第三类是自己写的 local.rules,用于匹配已知业务的特定威胁特征。订阅规则的更新机制需要跟 snort 版本严格匹配,否则规则里引用的 preprocessor 名和配置项在旧版本里根本不存在,自检时会直接报错。

社区规则包的解压位置通常在 /etc/snort/rules,配置文件里 include 的路径要和实际解压路径完全一致。这里提醒一句:不要下载最新版规则就跑在旧版 snort 上,最常见症状是规则加载了但 preprocessor 相关告警不工作。版本匹配的原则很简单——规则发布说明里写了支持的最低版本,低于那个版本就直接用旧规则集,别硬跑。

4. 手写第一条 snort 规则:从 ICMP 告警到 HTTP 恶意请求的完整实例

4.1 规则骨架:header 加 options 的构成

snort 规则由规则头部和规则选项两部分拼成。规则头部定义了动作、协议、源地址、源端口、方向、目的地址、目的端口;规则选项是括号里的内容,负责描述具体特征和元信息。

一个最基本的、能产生告警的规则是这样:

alert icmp any any -> $HOME_NET any (msg:"ICMP Echo Request"; itype:8; sid:1000001; rev:001;)

规则头部里 alert 表示发现匹配只告警不阻断,icmp 指向协议,方向箭头左侧是源,右侧是目的。规则选项里 msg 定义告警文案,itype:8 限定 ICMP 类型为 Echo Request,sid 是规则唯一编号,rev 是修订版本号。一个比较实用的习惯是一位数编号留着官方用,自定义规则从 1000000 开始,避开跟内置规则冲突。

4.2 让“多出来的 ping”变成告警:写一条 ICMP 规则并验证

拿 ICMP 做第一条规则特别合适,因为不需要起 web 服务,也不用拼复杂 TCP 状态,只要两台机器在同一个二层网络就能验证。把规则追加到 /etc/snort/rules/local.rules:

# /etc/snort/rules/local.rules alert icmp any any -> $HOME_NET any (msg:"ICMP Echo Request detected"; itype:8; sid:1000001; rev:001;)

这里只匹配 itype:8 的 ICMP Echo Request,也就是 ping 请求。如果不写 itype:8,那么 Echo Reply 也会命中,一通 ping 会产生两条告警,在测试阶段容易干扰判断。启动 snort 后再从另一台机器发起一次 ping:

tail -f /var/log/snort/alert

告警文件里应出现这条记录,内容包含时间和 ICMP Echo Request detected。如果 10 秒内没出现,先检查 ping 的流量是否真的经过监控网卡——本机 ping 本机走的是回环接口,snort 不监听回环,这是新手最容易自测失败的原因。

4.3 检测一条真实的 HTTP 探测:content 与 nocase 的配合

规范化、能够落到生产环境的规则,要从 HTTP 路径探测写起。下面这条规则用来匹配访问 /etc/passwd 的路径穿越类探测:

# 追加到 local.rules alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (msg:"HTTP path traversal probe /etc/passwd"; flow:to_server,established; content:"GET "; http_method; content:"/etc/passwd"; http_uri; nocase; sid:1000002; rev:001;)

规则要求匹配从外网到本机 80 端口的 TCP 流量,flow:to_server,established 限定为已完成三次握手、且方向为客户端发给服务器的包。content:"GET " 配合 http_method 修饰符只匹配 HTTP 请求方法位置,避免在响应体里碰巧出现 GET 字符串造成误报;content:"/etc/passwd" 配合 http_uri 只匹配规范化的 URI 部分,nocase 表示大小写不敏感。

验证这条规则需要一个真实接收请求的服务。常见做法是临时起一个 Python 自带服务:

sudo python3 -m http.server 80

然后在客户端发起一次请求:

curl http://10.0.0.10/etc/passwd

回到 snort 日志确认告警。注意 curl 的请求被服务端正常处理后,snort 的关键匹配点有两个:HTTP 方法 GET 必须出现在请求行开头,/etc/passwd 必须是 URI 的一部分。如果改成 curl -I 或者加一堆乱序头,不影响匹配,因为 http_uri 不关心参数顺序。

4.4 规则选项参数进阶:flow、content 修饰符和分类信息

上面那条规则里已经出现几个高频参数,值得单独拆开讲。因为 snort 规则的性能损耗几乎全来自 content 的匹配深度,无意义的长 content 会让检测引擎空耗 CPU。

先看一个常用参数的对照表:

参数作用什么时候用
flow:established只看已完成握手的流检测 TCP 会话内攻击时必须加
flow:to_server仅匹配客户端到服务器的方向HTTP 请求类规则必加
content:"..."匹配原始载荷字节是最基础的检测特征
http_method / http_uri限定 content 匹配的位置避免在压缩、编码后的 HTTP 内容上误报
nocase忽略大小写字符串特征不确定时使用

实际调试中,我经常看到有人把 content 写成一大串完整 URL,比如 content:"http://evil.com/payload" 或 content:"https://...". 这类规则有两个问题:一是 URL 里的协议头几乎不可能出现在原始请求里,因为 HTTP 请求行本身只会写路径;二是 content 默认区分大小写,攻击者把大小写混一下就能绕过。正确写法是把 content 拆成短特征,配合 http_uri 和 nocase 组合使用。

分类信息参数里最常用的是 classtype 和 priority:

alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (msg:"HTTP path traversal probe"; flow:to_server,established; content:"/etc/passwd"; http_uri; nocase; classtype:attempted-recon; priority:2; sid:1000002; rev:001;)

classtype 的作用是给告警归大类,比如 attempted-recon 归为探测行为,priority 表示严重程度,数字越小越严重。虽然这些参数不影响规则是否命中,但会直接影响告警分析平台对事件的分诊排序。规则数量一多,没有分类参数的规则集基本没法看。

5. 网络通信安全场景下 snort 使用中的 5 个常见坑:从网卡混杂模式到规则静默失效

5.1 网卡没进混杂模式,告警少一大截

现象是 snort 正常启动,日志里偶尔有几条告警,但明显比实际流量应有的命中少很多。用 tcpdump 在同一个网卡抓包,发现其他主机之间互访的流量根本没有出现。原因基本是网卡没有进入混杂模式,内核只把目的 MAC 匹配本机的包递交给上层,其余流量在到达 snort 之前就被丢弃了。物理机的网卡可以靠 ifconfig eth0 promisc 打开,但虚拟化平台里还要在虚拟交换机上开启镜像或混杂模式,这是虚机部署最常见的坑。

解决的办法是先做双向验证:用 tcpdump -i eth0 抓 30 秒,看能否抓到非本机 IP 的包;如果能抓到,再确认 snort 命令行里的 -i 参数是否指定了和 tcpdump 相同的网卡。检查 ifconfig 输出时要注意,网卡名称后面有没有出现 PROMISC 标记,如果没出现,使用下面命令临时打开或写入网卡配置文件永久生效。

sudo ip link set eth0 promisc on

ip link set 对物理网卡立即生效,重启后失效;持久化要在系统的网络配置文件中追加 PROMISC=yes。在多数云主机里,即便虚机内部开了混杂模式,底层虚拟交换机不配合也拿不到别人流量,这时候应该考虑流量的镜像和分发方案是否可行,而不是继续在虚机内部折腾。

5.2 规则写对了却从不出告警:sid 冲突和规则被注释

现象是 local.rules 里新加了一条规则,按第 4 章的步骤从另一台机器触发流量,snort 自检也显示规则加载了,但告警文件里就是找不到这条规则的记录。

常见原因有三个:第一,sid 和已有规则冲突。snort 遇到重复 sid 时通常只加载第一条,后一条规则被静默忽略。第二,书写时用了 Windows 文本编辑器的换行符,bash 后续到处乱码影响解析。第三,home_net 网段配置有误,规则里面 $HOME_NET 解析出来的地址范围和你测试来源方向不对应。

解决的方法是先跑一遍自检并过滤自己那条规则:

sudo snort -T -c /etc/snort/snort.conf 2>&1 | grep 1000002

正常情况能看到规则号及规则内容,看不到就是要查规则文件是否被 include,或者该条规则前面有语法错误导致解析中断。用 file 命令检查 local.rules 的编码,dos 格式先转成 unix。再用手工回放测试流量,从根上绕开“对方机器没发包、网络不通”的干扰。

5.3 镜像口方向弄反了,TCP 流重组永远少一半

现象是 snort 对单包类攻击能告警,一切涉及 flow:established 的 TCP 规则都没有任何产出。原因出在交换机镜像口方向配置上。SPAN 端口默认镜像入向流量,很多网络工程师只勾了 ingress 或 egress 单向,snort 只能看到客户端到服务器的请求,看不到响应。

TCP 状态机在这里格外敏感。flow:established 要等握手包出现才认为流建立,连 SYN-ACK 都看不到的话,预处理器会把流量当成半连接,规则命中无从谈起。解决的方法是去交换机上把镜像口方向改为 both,再用 tcpdump 抓包验证能看到两个方向的流量后再重启 snort。如果是 TAP 分光方案,检查分光器物理链路有没有接反。snort 集群部署时烧脑程度成倍上升,但单机场景十有八九就是镜像方向问题。

5.4 误报多,日志被刷满:缺 threshold 和未做规则禁用

现象是部署了一个大规则包之后,告警文件以每分钟上千条的速度增长,业务部门开始投诉网络异常。原因有两条:一是规则包里包含大量扫描探测类规则,这类规则设计上就宽松,倾向于用告警数量引起关注;二是 snort 默认逐包匹配逐条告警,没有做聚合。误报多的本质是检测置信度不够,需要用阈值把零星扫描压掉,只保留确定性的攻击特征。

我常用的做法是在规则或事件过滤器里定义 threshold,让同类型告警在一定时间窗口内只触发一次或达到数量才触发:

threshold gen_id 1, sig_id 1000001, type both, track by_src, count 5, seconds 60

这条配置的含义是:针对 sid 1000001 这条规则,同一来源地址在 60 秒内出现第 5 次时才产生一条告警。type both 表示同时启用了 limit 和 threshold 两种模式。生产场景里扫描类的规则几乎都必须配 threshold,否则告警中心会变成噪声来源。

5.5 Snort 3 用老文档命令操作:配置路径和参数全部错位

现象是照着旧 PDF 里的命令敲 snort -c /etc/snort/snort.conf -T,结果报错说找不到 snort.conf,或者 Lua 解析失败。原因是系统里装的是 Snort 3,它的配置体系是 snort.lua,默认路径在 /usr/local/etc/snort/,不再读取 2.x 的 snort.conf。Snort 3 还改了不少命令行参数,比如用 --pcap 指定回放文件,而不是 -r。

解决的方法是先确认版本再操作:

snort -V

如果输出里带 snort3 字样,直接把所有操作姿势切换到 lua 配置体系:配置文件中定义 HOME_NET 的方式变成 ipvar 语法仍有保留,但规则文件的 include 写法、预处理器参数、输出插件配置都有差异。自检命令变为:

sudo snort -c /usr/local/etc/snort/snort.lua -T

如果业务上离不开老资料里的操作步骤,最简单的思路是退回安装 Snort 2.9.x。不要试图在 Snort 3 上把老配置翻译成一半一半,自检能过,运行时预处理器加载失败会更难排查。

6. 用 pcap 回放验证 snort 规则:一个值得养成的操作习惯

生产网络里往目标机器发探测流量是要承担风险的,尤其是对着数据库主机、生产 web 集群发攻击特征请求,即使规则是安全的,也可能触发其他防护系统告警。我的习惯是用 pcap 回放来验证规则,把一个不产生真实影响的流量文件喂给 snort,观察它有没有告警。回放文件可以来自 tcpdump 日常抓包,也可以来自半仿真环境生成的测试流量。

具体步骤是先抓一对真实流量:

sudo tcpdump -i eth0 -w test.pcap host 10.0.0.20 and port 80

回放时注意抓包必须同时覆盖两个方向。因为 flow:established 规则依赖 TCP 三次握手,只有单方向流量的话预处理器不认为流是建立的,规则就测不出来。用下面命令回放,Snort 2 用 -r 指向 pcap,Snort 3 用 --pcap:

sudo snort -c /etc/snort/snort.conf -r test.pcap -A fast -l /var/log/snort

回放完去 /var/log/snort 查看新增的告警。这个习惯最直接的好处是让规则验证变成一个可重复的离线动作——改了规则就回放同一份流量,观察告警从无到有、从有到无,整个过程不会打扰到任何在线业务。

回到主题,snort 这个入侵检测系统真正有价值的地方不在安装,而在规则调优和验证闭环。我自己用它很多年,最常翻车的仍然是懒得回放、图省事往生产环境里直接发包验证规则;后来强迫自己先抓包再回放,告警的置信度才真正稳定下来。希望这篇 snort 使用笔记能帮你在网络通信安全的监控路上少走一段弯路。

本文还有配套的精品资源,点击获取

返回列表