Snort源码分析

时间:2024-04-06 21:04:09

       Snort由几大软件模块组成,这些软件模块采用插件方式与Snort结合,扩展起来非常方便,例如有预处理器和检测插件,报警输出插件等,开发人员也可以加入自己编写的模块来扩展Snort功能。所有这些子模块都建立在数据包截获库函数接口Libpcap的基础上,Libpcap为他们提供了一个可移植的数据包截获和过滤机制。

snort源代码主要由以下几个主要部分构成:

snort.c   snort主代码

decode.c   包解码器

rules.c  规则引擎

detect.c  检测引擎

log.c  记录引擎

以 spp_开头     预处理器插件

以 sp_开头       处理插件

以sop_开头       输出插件

(1)主程序流程

处理流程图如下:

                                                                                       Snort源码分析

        在 snort.c中 , SnorMain函数才是程序真正的入口和出口 ,它被 main函数调用 。 在 SnorMain中首先初始化设定一些缺省值 , 然后调用 ParseCmdLine函数解析命令行参数 , 根据命令行参数 , 填充结构变量 pv;pv数据结构用于存储程序所用到的各种变量以及命令行参数的解析结果 。 根据 pv的值 (也就是解析命令行的结果 )确定工作方式 , 需要注意 :如果是运行在 D aemon 方式 , 通过 GoDaemon函数 , 创建守护进程 , 重定向标准输入输出 , 实现 Daemon 状态 , 并结束父进程 。随后调用 OpenPcap函数打开 L ibpcap包捕获接口 。Snort可以实时采集网络数据 , 也可以从文件读取数据进行分析 。 如果是读取文件进行分析 (并非直
接从网卡 实时采集来 的 ), 以该文件名 作为 libpcap 的 函数OpenPcap的参数 , 打开采集过程 ;如果是从网卡实时采集 , 就把
网卡接口作为 O penPcap的参数 , 利用 libpcap的函数打开该网卡接口 。

        接着 , 指定数据包的解析处理函数。不同的数据链路网络 ,解析的函数也不同 。利用函数 SetProcessor, 根据全局变量
data link的值 , 来设定不同的解析函数 , 并将其保存在全局定义的函数指针 grinder中 。 例如 , 以太网 , 解析函数为 DecodeE thPkt;令牌环网 , 解析函数为 D ecodeTRPkt, 等等 。 这些 Decode*函数 , 在 decode. c中实现 。
        然后初始化各种预处理器插件 ( InitP reprocessor函数 ), 初始化各种处理插件 (InitPlugins函数 ), 初始化各种输出插件
(InitOutputPlugins函数 ), 并解析规则文件 , 转化成规则链表 。再根据报警模式 , 设定报警函数 ;根据日志模式 , 设定日志函数 ;
如果指定了能够进行响应 , 就打开 raw socket, 准备用于响应 。最后 , 调用 InterfaceThread 函 数循环抓包检测 , 在Interfa
ceThread函数中调用了 libpcap 的库函数 pcap_ loop, 它实质上循环调用了pcap_ read函数 , 直至所需数目的数据包全部处理完
毕 。pcap_ loop 对每个采集来的数据包都用 ProcessPacke t函数进行处理 , ProcessPacke t函数的功能是启动对每一个数据包的处理过程 , 如果出现错误或者到达指定的处理包数 (pv. pkt_ cnt定义 ), 就退出该函数 。
(2)数据包处理流程

数据包处理流程图如下:

                                                           Snort源码分析

        数据包处理流程被主程序在 InterfaceThread函数中循环调用 。对数据包进行处理时 , 首先调用各种网络协议解析程序 , 对当前数据包进行分层协议格式字段的分析 ,并将分析结果存入到重要的数据结构packet中。ProcessPacket函数调用DecodeEthPkt函数 (在 decode. c中 ), 该函数对以太帧进行解码 , 另外还有 DecodeIP对 IP协议进行解码 ,DecodeTCP对 TCP协议进行解码 , 等等 。然后 , 系统依次调用预处理程序 Preprocess函数 (在 detect.c中 )和检测主引擎 Detect函数 , 该函数对当前数据包按照一定的顺序 , 分别应用规则列表 , 根据给定的各种规则和当时所截获的数据包分析结果 , 作出是否发生入侵行为的判断 。如果当前数据包符合某条检测规则所指定的情况 , 则系统可以根据这条规则所定义的响应方式以及输出模块的初始化定义情况 , 选择进行各种方式的日志记录和报警操作 。
(3)Snort规则建立及检测引擎

         在启动时 , Snort读取所有的规则文件 , 并且建立一个三维的链表 , Snort使用规则匹配包和检测 , 输入和读取规则文件都
在 parser. c中的ParseRulesFile()函数中实现 。链表的建立在snor.t c中进行初始化 , 当 Snort以 IDS模式运行时 , 在对网络数
据包进行检测前 , Snort首先读取 Snort.conf配置文件 , 在Snort.conf文件的 “ Step4— Custom ize you r ru le set”中链接特定的规则文件 , 包含在每个规则文件中的规则被解析并且链表建立 。建立链表时 , 首先按规则类型 (Log、 Pass、Alert、 Dynamic、Activation)分类 , 分成了五个单独的规则链 ;然后针对这五个规则链的每一个按协议类型 (TCP、UDP、 ICMP、 IP)分成相应的节点链表 ;最后又按照源 IP、目的 IP、源端口号及目的端口号分为多个规则树节点 (RTN);每个规则树节点下又有规则选项 , 称
为选项树节点 (OTN);这样每个OTN节点就对应了一条规则 。
                                 Snort源码分析

        当数据包到达检测引擎时 , Snort将首先匹配规则链 , 然后根据数据包协议匹配相应 的节点链表 , 于是从左至右遍 历RTN, 参看源 、目的 IP及端口号是否匹配 , 找到一个匹配后 , 算法向下进行 , 在每个 OTN 中寻找匹配 ;当找到一个匹配后 , 退出树结构返回相应规则链的头部 , 通过指定格式输出 。
 

附录:插件分析

Snort系统中插件模块共分为三种类型:预处理器插件模块、输出插件模块和处理插件模块。

        预处理器插件模块———在数据包进入检测引擎之前, 它们首先被送入预处理器 , 主要是在数据包送入 Snort主检测引擎前提供一个报警、丢弃数据包、修改数据包的地方。预处理器完成的功能主要有:①包重组, 完成将多个包中的数据进行合并的工作, 如 TCP流重组插件 (stream4)、 IP 碎片重组插件 (frag2);②协议解码和规范化, Snort中有三个协议解码及规范化插件, 分别对 Telne t、HTTP和 RPC 协议进行处理;③异常检测, 对无法用一般的规则发现的攻击进行检测, 或者进行协议异常检测, 如端口扫描插件、Back Orifice检测插件等;在 Snort.conf文件中加入preprocessor <name> <options>就可以启动所需的预处理器。
         处理插件模块———处理插件在规则匹配阶段的 ParseRleOptions函数(在 rule. c中)中被调用, 辅助完成基于规则的匹配过程。 每个规则处理函数通常对应规则选项中的一个关键字, 实现对这个关键字的解释, 主要功能为:①检查协议各字段,如TCPF lag、 ICMPType、 IPId 等;②辅助功能, 如会话记录、攻击响应、关闭连接等。
         输出插件模块———输出插件允许把报警和日志以更加灵活的格式和表现形式呈现给管理员, 这些输出插件在预处理器和抓包引擎执行完后调用 Snort报警和日志子系统时执行。他们在配置文件中定义, 在触发规则时被调用, 如将数据写入数据库或者以TCPDump 格式输出日志文件, 或者向NMS发送SNMPtrap等。