ARTICLE DETAIL

资讯详情

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

从零搭建Snort入侵检测实验:规则编写与告警分析实战

从零搭建Snort入侵检测实验:规则编写与告警分析实战 简介这是一份网络安全课程中Snort网络入侵检测实验的完整实验报告适用于高校网络安全、信息安全等专业学生及入门者参考。报告基于遵义师范学院实验教学场景涵盖入侵检测基本原理、Snort三种工作模式及规则匹配响应机制并详细记录了在Windows Server 2003与虚拟机环境下完成Snort、WinPcap、MySQL等组件的安装、配置与检测应用过程。资源包为单个doc文档体积约787KB便于直接打开阅读与打印。目前已有1380人学习下载适合正在完成同类实验或需要撰写实验报告的学习者借鉴。通过这份报告读者可快速理解Snort作为NIDS的核心思路掌握从抓包解码、预处理到规则告警的完整链路同时获得实验目的、仪器环境、原理分析、操作步骤等可复用的结构化内容有助于提高实验效率与报告撰写质量。1. 做了三年安全工作我为什么回头把 Snort 实验重新补了一遍只要聊到网络入侵检测Snort 就是绕不过去的名字。不少新手觉得它“老”一上来就奔着东西更花哨的商业 NDR 平台去可真到了要自己写检测规则、要解释一条告警为什么产生、要在没有厂商兜底的环境里做流量研判时又得灰溜溜回来补 Snort 的课。这个实验的价值不在“会用一条命令跑起来”而在于把网络入侵检测最核心的事——抓流量、写规则、看告警、查漏报——完整地亲手做一遍。它适合刚入行的安全工程师、做等保和重保的服务人员也适合那些想从“用设备”转向“懂检测”的运维。这篇笔记就是按我自己重新搭实验的路径写的照着做能跑通跑通之后你能回答一个很现实的问题一条攻击流量进来Snort 到底怎么认出它、又在哪里漏掉它。2. 搭一套最小可用的 Snort 检测环境从安装到跑出第一条告警做这个实验最容易犯的错是一上来就追求“大而全”装最新版、配最大规则集、接一堆输出插件最后卡在配置错误里出不来。我的建议是先搭一个最小链路——一块网卡、一个配置文件、一条规则。链路通了再往上面加东西。实验的目的不是把 Snort 配置成生产级设备而是亲眼看到“流量进、规则匹配、告警出”这个过程。2.1 选 2 系还是 3 系实验环境该做的第一个决定Snort 现在有两套常见分支2.9.x 和 3.x。2 系是传统稳定版配置用snort.conf规则语法沿用十几年绝大多数公开规则和教程都基于它资料最全。3 系是重构版配置改成snort.lua解析性能更好线程模型更现代但很多老规则的写法要微调。对于做实验我一般推荐先选 2 系原因是资料密度。你遇到“规则不生效”“告警没输出”这类问题搜出来的解决方案十有八九是 2 系的对照着排查效率高很多。3 系值得后面单独花时间但第一遍不要在它上面死磕。在 Debian/Ubuntu 上安装 2 系一步步来sudo apt update sudo apt install -y snort snort -V安装完成后第一件事不是急着跑而是确认版本和默认配置路径snort -V | grep -i Version sudo snort -c /etc/snort/snort.conf -T-T是测试配置模式只检查配置和规则有没有语法错误不抓包。这一步的作用是提前暴露问题——比如规则文件路径不存在、变量没定义、插件加载失败。如果输出里有Snort successfully validated the configuration之类的字样说明配置能过可以继续。注意如果报错提示找不到snort.conf先用dpkg -L snort看一下实际安装路径。配置验证通过后把监听网卡确认好。实验机上通常有多块网卡用ip addr找到要监听的那块记下名字ip -br addr这一步看起来不起眼但后面所有抓包和告警都依赖这个网卡名写错直接白跑一天。2.2 配置文件和规则集让 Snort 知道它要保护什么Snort 的配置核心是它的“视野范围”——它要知道你所在网络的结构、要监控哪些网段、只对哪些流量产生兴趣。打开/etc/snort/snort.conf有几项必改。sudo cp /etc/snort/snort.conf /etc/snort/snort.conf.bak sudo vim /etc/snort/snort.conf文件里先找到 IP 变量定义ipvar HOME_NET 192.168.1.0/24 ipvar EXTERNAL_NET !$HOME_NETHOME_NET定义内网网段实验机上改成你自己的网段EXTERNAL_NET用!$HOME_NET表示“除内网外的所有地址”。这里的语义是Snort 会把规则里$HOME_NET替换成你定义的网段如果配错规则匹配范围就不对可能该告警的不告警不该告警的刷屏。再看规则文件加载部分2 系的配置末尾通常有include语句默认会把/etc/snort/rules下所有规则文件加载进来include $RULE_PATH/snort.rules include $RULE_PATH/local.rules实验阶段我们只维护一个local.rules把自己写的规则放进去避免被默认规则集干扰。下一步确认规则目录存在ls -l /etc/snort/rules/ sudo touch /etc/snort/rules/local.rules2.3 首条规则与第一条告警跑通全链路现在写一条最简单的规则验证整个链路通不通。在local.rules里加一行echo alert icmp any any - $HOME_NET any (msg:ICMP Packet Detected; sid:20240001; rev:1;) | sudo tee -a /etc/snort/rules/local.rules这条规则的含义任何来源、任何端口发往$HOME_NET的 ICMP 包都触发告警。msg是告警显示的内容sid是规则唯一编号rev是版本号。sid很重要Snort 规定不能重复否则加载报错这也是新手最容易踩的坑之一。以后台模式启动 Snort把日志写到指定目录sudo mkdir -p /var/log/snort sudo snort -i eth0 -c /etc/snort/snort.conf -l /var/log/snort -A fast参数解释-i eth0指定监听网卡-c指定配置文件-l指定日志输出目录-A fast只记录告警摘要适合实验阶段阅读再开一个终端从另一台机器或者本机另一个网卡ping 这台实验机ping -c 5 192.168.1.100然后回头看/var/log/snort/alert文件sudo tail -f /var/log/snort/alert如果看到类似[**] [1:20240001:1] ICMP Packet Detected [**]的记录链路就通了。到这里你已经走完了“取流量→匹配规则→产出告警”的最小闭环。很多人卡在这一步之后不知道怎么往前深挖下一章把规则引擎拆开讲这是 Snort 实验真正有价值的部分。3. Snort 规则引擎拆开看规则头、规则体与一次扫描规则的落地从第一条 ICMP 告警开始实验就迈入真正的检测逻辑了。Snort 的规则体系说到底是“在一堆网络流量里声明一种特征符合特征就报警”的描述语言。要做到能把一条攻击特征准确翻译成规则而不只是抄别人的规则必须把规则头和规则体拆开理解。这一章也是整个实验的重心后面的模拟攻击、日志研判全部靠这个基础。3.1 规则头动作、协议、地址、端口与方向的决策一条 Snort 规则分两段规则头和规则体。规则头决定了“在什么条件下、以什么动作处理流量”语法上是这样一行alert tcp $EXTERNAL_NET any - $HOME_NET 80从左到右依次是动作、协议、源地址、源端口、方向、目标地址、目标端口。动作不只是alert常用的还有log、drop和reject。log只记录不告警drop是在 IPS 模式下直接丢包reject会发送 RST 主动断开连接。实验用 IDS 模式默认用alert就行。协议字段支持tcp、udp、icmp、ip也可以写tcp udp表示两类协议都匹配。地址和端口支持变量和取反!$HOME_NET表示“非内网”any表示任意地址或端口。方向箭头只有两个方向-表示从左到右表示双向没有-这种写法。我一般建议新手把规则头写“宽”一点。实验阶段先不管内网外网源和目的都用any写先把流量抓到、把告警跑出来再逐步缩窄范围。一上来就精确控制地址端口很容易因为方向写反导致十分钟查不出问题。方向写反是最常见的低级错误一条规则本该检测外部到内部的扫描结果写成内部到外部告警永远出不来的感觉就像见鬼了。3.2 规则体content、flags、threshold 怎么配合决定告警质量规则体是用分号分隔的选项列表真正决定一条规则检测什么。下面是几条高频选项(msg:...; content:GET /admin; nocase; flags:S; threshold:type both, track by_src, count 10, seconds 5; sid:20240002; rev:1;)content是核心它声明在包载荷中查找的字符串。默认是大小写敏感的加上nocase变成不区分大小写。Snort 对content的匹配性能比较敏感多个content之间默认是“与”的关系也就是说一条规则里写了两个content两个都得匹配才算命中。flags用来匹配 TCP 标志位。S表示 SYNA表示 ACKP表示 PSHF表示 FINR表示 RST。一个常见的端口扫描规则会写成flags:S意思就是只看 SYN 包。flags:SA则表示 SYNACK 包。threshold是告警阈值控制它的存在是为了防止告警刷屏。格式是threshold:type limit|threshold|both, track by_src|by_dst, count N, seconds Stype both表示同时应用limit和threshold同一个源在seconds秒内出现count次之前每个包都告警超过之后每个包只记录一次。这个参数在端口扫描检测里几乎是必须的否则一次全段扫描能把日志打成上千条重复记录。还有一个容易忽略的选项是offset和depth它们限制content在包里的搜索范围。content:GET /admin; offset:0; depth:16;表示从包起始位置开始、只在前 16 字节内找这个字符串。这个约束能把匹配范围缩小很多实验流量小看不出差别但规则多了跑在千兆链路上时没有这些约束的规则往往会成为性能黑洞。3.3 用一条端口扫描规则走通“写规则-加载-验证”闭环下面直接用一个端口扫描检测的规则把整条链路串起来。打开本地规则文件sudo vim /etc/snort/rules/local.rules写入以下规则然后保存退出alert tcp $EXTERNAL_NET any - $HOME_NET any (msg:Port Scan Detected; flags:S; threshold:type both, track by_src, count 10, seconds 5; sid:20240003; rev:1;)这条规则检测外部对内部任意端口的 SYN 扫描行为5 秒内同一个源产生超过 10 次 SYN 请求就触发告警。flags:S只匹配 SYN 包threshold做了频率约束。加载规则并验证语法sudo snort -i eth0 -c /etc/snort/snort.conf -l /var/log/snort -A fast --homenet 192.168.1.0/24这里用--homenet临时覆盖配置里的HOME_NET方便快速测试不同网段。不要小看这个参数后面做镜像流量、内网网段变动时它比反复改配置文件省事得多。验证完成后从一个外部地址执行针对目标机的扫描ping -c 3 192.168.1.100 nmap -sT 192.168.1.100 --top-ports 100再回头检查告警文件sudo grep Port Scan /var/log/snort/alert | tail -20如果看到Port Scan Detected的告警说明这条规则的整条链路已经生效。这里注意一个细节如果实验机上用的是物理服务器而不是虚拟机$EXTERNAL_NET可能匹配不到因为源地址在同网段。实验时可以把源地址改成any先验证规则逻辑再去控制方向。规则验证通过不代表规则写得好但规则写不好一定在验证阶段露馅这个闭环就是用来干这个的。4. 跑一次真正的入侵检测实验模拟攻击、告警研判与日志反查规则通了实验才刚开始。一条 ICMP 告警和一条端口扫描告警只能证明 Snort 在工作距离“检测到入侵”还很远。这一章要做的是用三种不同的攻击模拟方式让 Snort 产生三类风格完全不同的告警然后学会从日志反推攻击者的行为路径。对实验来说重要不是“它告警了”而是“它为什么告警、告警说明了什么”。4.1 用 hping3 模拟端口扫描看 Snort 的实时告警实验环境里没有真实攻击流量就得自己造。hping3 是常用的流量生成工具比 nmap 更有优势的地方在于它能把 TCP 标志位拆得很细方便验证 Snort 对单一标志位的检测逻辑。安装后执行sudo apt install -y hping3 sudo hping3 -S -p 80 -c 20 192.168.1.100这条命令的含义向目标主机 192.168.1.100 的 80 端口发送 20 个 SYN 包。-S指定 SYN 标志-p指定目标端口-c指定包数量。Snort 侧用前台模式看输出更直观sudo snort -i eth0 -c /etc/snort/snort.conf -A console-A console表示告警直接刷到终端。对比上一章的-A fastconsole 模式适合交互式验证。这时终端里应该能看到端口扫描规则触发的告警同时还能看到 ICMP 规则如果没注释掉也会刷出来。这里有个值得注意的现象20 个 SYN 包不一定只产生 20 条告警因为 TCP 重传、Snort 的流重组、阈值规则都会影响最终告警数。看日志时不要简单地把“告警条数”等同于“攻击包个数”这个误差本身也是实验的一部分。hping3 还可以用来验证不同标志位组合。比如发 SYN-ACK 包sudo hping3 -SA -p 443 -c 10 192.168.1.100如果 Snort 只做了flags:S的规则这类包不会触发。这个对比能让实验者直观理解“标志位是检测的最小颗粒度”这个结论。4.2 用 HTTP 探测触发 Web 攻击规则理解 signature 与 payload 的关系端口扫描属于“行为式检测”靠的是多个包的行为特征。Web 攻击检测则更依赖content——在 payload 里找特征字符串。这一步用一个模拟 SQL 注入的探测请求curl -v http://192.168.1.100/index.php?id1 OR 11在测试环境中目标端口可以指向任何服务Snort 不管目标上跑没跑 Web 服务它只做流量匹配。规则侧打开规则文件加一条针对 SQL 注入典型特征的规则alert tcp any 80 - $HOME_NET any (msg:SQL Injection probe; content:OR 11; nocase; sid:20240004; rev:1;)这条规则的含义检测目标端口 80 的入站流量里包含OR 11字符串的包。nocase让大小写不敏感探测里写11和规则里的11不完全一样所以这条规则能不能命中还取决于 URL 编码和实际载荷。如果告警没出来试试把探测改成直接匹配规则的版本或者用 Wireshark 先看实际发送的内容。这个“规则设想的特征和实际流量里的特征对不上”的问题是 Web 检测落地的常态也是 Snort 实验最有教学价值的一环——检测规则不是一厢情愿的文本匹配。再看一个更贴近实战的情况。真实的 SQL 注入 payload 常常被 URL 编码比如空格变成%20单引号变成%27。编码后content:OR 11就失效了。Snort 对 URL 编码有urilen和uricontent这两个选项它们只在 HTTP 请求的 URL 部分匹配alert tcp any 80 - $HOME_NET any (msg:SQL Injection via URI; uricontent:OR; uricontent:11; nocase; sid:20240005; rev:1;)uricontent比content更精准它限定在 URL 字段里查找能避开 body 区域的大段内容减少误报。Snort 里类似这样“限定匹配区域”的选项还有content配offset和depth使用场景都是让检测条件更明确、避免无效匹配拖慢性能。建议实验时把原始请求和编码后的请求各测一遍对比告警差异这是理解 payload 检测边界最快的路径。4.3 从日志反查原始流量统一日志格式与字段解读告警文件里只写了规则命中和基本信息要还原攻击者的完整意图必须回到原始流量。Snort 默认会把触发告警的包写进tcpdump格式的 pcap 文件里用 Wireshark 打开分析。先确认日志目录ls -l /var/log/snort/目录下除了alert还会有snort.log.xxxx文件。用tcpdump直接在命令行里解读sudo tcpdump -nn -r /var/log/snort/snort.log.1696924800 | head -30-nn不做域名和端口解析直接显示 IP 和端口速度快且结果一致。输出里能看到告警发生时前后一段时间的数据包按时间顺序排列攻击者的源 IP、目标端口、包大小一目了然。更推荐的做法是导出后导入 Wiresharksudo tcpdump -r /var/log/snort/snort.log.1696924800 -w /tmp/attack.pcap然后在 Wireshark 里打开/tmp/attack.pcap用Follow TCP Stream功能把攻击者本次连接的完整对话还原出来。端口扫描阶段你可以看到一串类似“同一个源 IP 轮询多个端口”的包SQL 注入阶段则能看到 HTTP 请求的行文并在里面精确找到触发规则的字符串。把 Snort 告警和原始流量对着看告警就不再是干巴巴的一行字而是一条可以被追溯、被验证的攻击过程证据链。5. Snort 实验最容易翻车的 5 个点现象、原因与解决做 Snort 实验很少有“一次全通”的。绝大多数时间花在排错上而且很多坑非常一致几乎每个做实验的人都会踩一遍。下面这几个是我自己在实验环境里反复遇到的按“现象→原因→解决”来写照着排查比翻文档快得多。5.1 规则明明加载了就是不出告警现象snort -T验证配置没有任何报错规则文件里能看到自己的规则但模拟攻击发出后alert文件里什么增量都没有。原因分三种第一种规则里的sid重复Snort 加载时为了不崩静默丢弃了后面的重复规则第二种规则被配置里的分类机制过滤掉了比如snort.conf里的classification或reference写错导致规则匹配后告警被丢弃第三种传入的参数把规则文件覆盖了比如手动指定-r读入 pcap 时忽略实时流量。解决先加一条最简单、最不可能出错的规则确认链路本身是通的比如 ICMP any 规则。确认链路通后再检查sid是否唯一。另外用sudo snort -c /etc/snort/snort.conf -T -v看详细加载输出Snort 会列出“规则加载总数、告警规则数”等统计如果统计里的告警规则数是 0说明规则确实没被加载回去看规则文件内容是不是全被注释掉了。过滤和丢弃类的问题在这种统计里不太容易暴露更快的办法是换成-A console跑一次看是不是有告警但是只写进了别的位置。5.2 监听网卡在混杂模式下流量仍然丢失现象实验时用笔记本跑 Snort连接的是无线网络抓到的只有自己的广播包本机访问外网的流量也看不到感觉像是“只看到别人的影子”。原因多数无线网卡根本不支持真正意义上的混杂模式驱动层面会把不属于本连接的流量丢掉。另外很多人忽略了交换机的端口隔离有线接入时交换机不会把其他端口的流量复制给你除非配置了 SPAN 端口镜像。解决实验一律用有线连接并把网卡设为混杂模式sudo ip link set eth0 promisc on ip -br link show eth0 | grep -o PROMISC如果在虚拟机里跑实验把虚拟交换机的“混杂模式”选项打开否则虚拟网卡收不到其他虚拟机的流量。这里再提醒一个容易忽略的点混杂模式在重启网络服务后会被重置每次启动实验前检查一下这个标志位别到测完才发现网卡根本没在监听。丢了半天流量找不到原因最后发现是网卡模式被重置这是典型的“玄学问题”实际上一点不玄。5.3 内网流量完全抓不到镜像口的方向问题现象公司内网部署了一台 Snort 旁路监听直连交换机镜像口理论上所有员工访问服务器的流量都会经过但alert文件几乎只出不入。原因交换机的 SPAN 端口镜像有方向性。常见的Rx、Tx、Both三种选项Rx只复制进入该端口方向的流量Tx只复制流出方向的流量。如果只配置了Rx那么从服务器返回的流量就不会到达 Snort。很多新手只看“镜像口连上了”就以为万事大吉结果告警数量比实际攻击少一个数量级。解决确认交换机镜像是Both方向配置示例Cisco 系交换机monitor session 1 source interface Gi1/0/5 both monitor session 1 destination interface Gi1/0/10如果交换机只能做单向镜像那就需要两条会话或者把服务器方向的流量也镜像一份。实验环境里更简单的验证办法是在被镜像的端口上打一个明显的 ping 流量然后在 Snort 端用tcpdump -i eth0 icmp看能不能抓到。抓不到就说明镜像方向或链路有问题不要急着调规则。这个方向性坑在所有旁路部署场景中都存在。5.4 Snort 3 与 Snort 2 规则混用的兼容性陷阱现象网上找了一条规则按照教程放进local.rules加载时直接报错比如unknown rule option之类或者干脆不加载。原因Snort 3 的规则语法和 2 系有不少差异最典型的是 3 系改用 Lua 配置后变量名、规则选项的写法都有变化。一些老教程里的规则在 3 系里就是不能直接用尤其是ipvar这类变量定义、flow选项的写法、以及部分content修饰符。解决做实验时先确认自己装的版本不要“按截图操作”。2 系规则在 3 系里需要做以下检查变量定义用ipvar的部分配置文件的变量替换写法不同content选项本身通用但nocase的位置和 3 系的风格不完全一致。更省心的方法是让实验环境“专一”一点——装 2 系就只用 2 系规则装 3 系就先找 3 系配套教程。不建议在同一台机器上同时跑两套也不建议把 2 系规则文件直接丢给 3 系强行加载。要看当前版本到底用的哪套一条命令就能确认snort --version | head -2如果你查到版本是 3.x去看配置文件的路径是不是/usr/local/etc/snort/snort.lua如果还在找snort.conf大概率装的是 2 系。版本不对会造成大量无意义排错浪费时间不说还会让人误以为是自己规则写错了。5.5 单条规则看似有效整批扫后性能崩掉现象实验时流量不大单条规则跑得很好。一旦加载完整规则集或者流量变大Snort 变得卡顿告警延迟明显甚至丢包。原因规则数量大之后Snort 的匹配开销显著上升。特别是规则里的content都是单字节或常见字符串时Snort 的 Aho-Corasick 匹配算法也扛不住海量短模式。还有另一层原因是在同一个包上连续匹配上百条规则CPU 吃满。实验环境忽略性能生产环境绝对躲不开。解决先量化再调优。跑实验时打开性能统计sudo snort -i eth0 -c /etc/snort/snort.conf -l /var/log/snort -A fast --perfmon-cpu --perfmon-pkts看两个指标CPU 占用和丢包率。Snort 启动时会打印drop rate如果丢包率超过 1%就得想办法。优先检查规则文件里是不是加载了用不上的规则按需 include把不用的规则文件注释掉。其次给经常命中的规则加上offset和depth限定搜索范围给既有content再加长字符串长度越长匹配开销越小比如content:GET /admin/login就比content:admin便宜得多。最后确认网卡驱动开的是AF_PACKET并调大环形缓冲区ethtool -G eth0 rx 4096 tx 4096注意ethtool改的是网卡驱动缓冲区Snort 侧用的还是内核套接字缓冲区可以在配置里调整pcap_ring_buffer三层配合才能把丢包压下去。性能问题说起来不复杂核心就是让 Snort 少干活、干快活但它永远是排错里最费时间的一环因为现象和原因通常隔着一层看不见的流量负载。6. 收尾给 Snort 实验加一个可复用的验证脚本实验做到这里规则能写、攻击能模拟、告警能看、问题能排剩下最后一件值得做的事把验证过程固化成脚本以后每次改规则、调参数跑一遍就知道有没有回归问题。我自己的习惯是准备一个快速回归脚本放在实验机/opt/snort-lab/下内容很简单但非常顶用#!/bin/bash # 快速回归验证检查 Snort 是否存活、规则是否加载、告警是否更新 SNORT_CONF/etc/snort/snort.conf ALERT_LOG/var/log/snort/alert TARGET192.168.1.100 echo [1/3] 检查 Snort 进程状态 pgrep -a snort || { echo Snort 未运行请先启动; exit 1; } echo [2/3] 验证配置与规则加载 sudo snort -c $SNORT_CONF -T 21 | tail -5 echo [3/3] 触发一条 ICMP 探测确认告警链路 sudo ping -c 1 $TARGET /dev/null 21 BEFORE$(wc -l $ALERT_LOG) sleep 2 AFTER$(wc -l $ALERT_LOG) if [ $AFTER -gt $BEFORE ]; then echo PASS: 告警链路正常告警总数 ${AFTER} else echo FAIL: 告警未增长检查网卡和规则配置 fi脚本逻辑是三段式先确认进程在不在再验证配置和规则加载有没有报错最后用一条 ICMP 流量探测告警链路是否仍然产出。改完规则后跑一遍比手动敲命令找问题快得多。这套思路同样适用于生产环境里的安全设备变更验证——无论改的是 Snort 还是其他检测引擎变更后跑一个最小回归集是最便宜、最靠谱的后悔药。在 Snort 上多花的时间从来不会白费。后面你去看 Suricata 的规则去研究各种商业 NDR 平台的告警语义都会发现底层逻辑跟 Snort 一脉相承。做实验的时候多看告警原文、多抓原始包对照、多改规则看变化比收藏一百篇教程管用。希望帮到你。本文还有配套的精品资源点击获取
返回列表