suricata源码分析
文章平均质量分 92
基于suricata3.1的源码分析。
高晓伟_Steven
wx_cangying1988的博客
展开
-
配置篇-suricata.yaml-1
suricata版本为4.0.3user and group用于设置启动suricata的用户及其分组。# Run suricata as user and group.# run-as:# user: suri# group: surimax-pending-packets该选项设置了suricata能够同时处理的数据包的数量,最少为1,最大值取决于内存的大小,...转载 2019-10-18 10:06:57 · 2261 阅读 · 1 评论 -
suricata 架构图------持续更新
suricata架构,红色文字为待分析部分原创 2017-01-31 19:16:34 · 7629 阅读 · 6 评论 -
suricata 3.1 源码分析36 (dns解析获取相关内容)
在app-layer-dns-udp.c文件的DNSUDPRequestParse函数中调用DNSStoreQueryInState函数,该函数在app-layer-dns-common.c文件中。DNSStoreQueryInState中会取dns信息,包括type, class, name(可以是要查询的host)fqdn指向dns中的name,fqdn_len为name的长度。附dns正文结...原创 2018-03-02 17:37:56 · 1573 阅读 · 2 评论 -
suricata在netmap模式用autofp方式抓包有内存泄漏的相关信息
说个小的发现。 suricata在运行netmap模式进行抓包的时候默认使用的是”workers”的工作方式。 由于其它的都是“autofp”的方式,所以就带着疑问上google上查了一下。没想到还真查到点东西。 https://redmine.openinfosecfoundation.org/issues/1717 这是论坛里找到的,大体意思是说在suricata 3的版本使用netma原创 2016-08-26 16:11:56 · 2211 阅读 · 0 评论 -
suricata 3.2 源码分析(IP数据包分片重组流程)
在网络通信中如果发送的IP包超过MTU值就会将IP包拆分成多个包发送。那么在suricata中对于这种拆分开得IP包又是如何处理的呢?下面我们一步一步来分析。判断数据包是不是分片包是在DecedeIPV4这个函数中做的,具体位置是在 数据包解析模块->DecodeEthernet->DecedeIPV4在DecedeIPV4这个函数中有如下一段代码: /* If a fragment, pa原创 2017-07-11 17:24:17 · 3411 阅读 · 10 评论 -
suricata在netmap模式无法抓包的原因
问题描述suricata在很早就支持了netmap,但最近在用的时候却发现开启netmap抓包后总是获取不到数据包。 使用netmap自带的pke-gen工具测试,结果证明不是netmap的问题。 只能去suricata源码里查原因了。问题定位问题出在source-netmap.c文件的NetmapOpen函数中,具体位置如下: if (ioctl(pring->fd, NIOCR原创 2017-03-22 15:05:18 · 2238 阅读 · 2 评论 -
suricata 3.1 源码分析35 (FlowWorker处理流程4 - 流重用函数)
static Flow *TcpReuseReplace(ThreadVars *tv, DecodeThreadVars *dtv, FlowBucket *fb, Flow *old_f, const uint32_t hash, const Packet *p){ /*原创 2016-12-30 16:33:20 · 1504 阅读 · 1 评论 -
suricata 3.1 源码分析34 (FlowWorker处理流程3 - 流重用)
上一章提到了一个流重用的概念,这里主要说一下。根据code,所谓流重用仅仅重用了流的thread_id。其他内容都是新建流得来的,具体threa_id有什么作用以后看到了再分析,今天就说一下什么样的流可以被重用。//这就是判断包所属的流是否能重用的函数int TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *t原创 2016-12-30 16:08:59 · 1933 阅读 · 1 评论 -
suricata 3.1 源码分析33 (FlowWorker处理流程2 - FlowHandlePacket)
void FlowHandlePacket(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p){ /* Get this packet's flow from the hash. FlowHandlePacket() will setup * a new flow if nescesary. If we get NULL, we'r原创 2016-12-27 13:59:48 · 2447 阅读 · 2 评论 -
suricata 3.1 源码分析32 (FlowWorker处理流程1)
TmEcode FlowWorker(ThreadVars *tv, Packet *p, void *data, PacketQueue *preq, PacketQueue *unused){ FlowWorkerThreadData *fw = data;/*FlowWorkerThreadInit中初始化,包含大量stats统计指标,decode指标在DecodeThreadV原创 2016-10-18 17:54:14 · 3265 阅读 · 2 评论 -
suricata 3.1 源码分析31 (RespondReject)
简介 RespondReject工作在worker线程,在FlowWorker模块之后对数据包进行处理。此处主要的作用是直接对符合过滤规则的数据包进行阻断并回复,从而使得数据包不会流入后续的操作模块。个人理解这点在IPS模式时会十分有用,可以阻断网络攻击、爬虫等。原码分析 函数RespondRejectFunc只支持IPv4和IPv6的数据包回复,因此其中只调用了4个函数:RejectSendI原创 2016-10-14 16:09:09 · 1992 阅读 · 0 评论 -
suricata 3.1 源码分析30 (packet_pool处理流程)
简介suricata中的packet_poo是专门用于存放receive线程抓到的数据包的。 receive线程初始化时在TmThreadsSlotPktAcqLoop中调用PacketPoolInit来初始化它的packet_pool,并为packet_pool划分内存空间。默认是申请1024个packet结构大小的空间,以链表的开示存储。这里的packet_pool被记为“my_pool”,也原创 2016-10-13 18:07:08 · 3686 阅读 · 1 评论 -
suricata 3.1 源码分析29 (数据包队列)
这块的东西我现在还没有用到,所以很不厚道的抄了背着笔记本流浪的原文下来。简介Suricata中使用队列来缓存数据包,包括缓存线程模块内部新产生数据包的线程内队列,以及线程之间用来传递数据包的线程间队列。 用于表示数据包队列的结构体为PacketQueue,其定义如下(省略了调试相关字段): typedef struct PacketQueue_ { Packet top; / 头指针原创 2016-10-12 13:21:33 · 3056 阅读 · 0 评论 -
suricata 3.1 源码分析28 (数据包TCP解码)
int DecodeTCP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq){ StatsIncr(tv, dtv->counter_tcp); if (unlikely(DecodeTCPPacket(tv, p,pkt,len) < 0))原创 2016-10-11 09:47:12 · 2874 阅读 · 0 评论 -
suricata 3.1 源码分析27 (数据包IPv4解码)
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq){ StatsIncr(tv, dtv->counter_ipv4); SCLogDebug("pkt %p len %"PRIu16"", pkt, len);原创 2016-10-10 13:26:55 · 2073 阅读 · 0 评论 -
suricata 3.1 源码分析26 (数据包VLAN解码)
由于VLAN可能嵌套,因此Packet结构体中使用以下相应字段进行记录: 字段含义vlan_idx当前的vlan层数,初始为0,最多为2,即最多只能嵌套一层VLAN,否则会报错。vlan_id[2]记录每一层的VLAN ID(共12位,可表示4096个VLAN),通过GET_VLAN_ID获得。vlanh[2]记录每一层的VLAN头指针(VLANHdr *类型)。/** * \internal原创 2016-10-09 14:34:16 · 1867 阅读 · 0 评论 -
suricata 3.1 源码分析25 (数据包以太层解码)
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq){ StatsIncr(tv, dtv->counter_eth); if (unlikely(len < ETHERNE原创 2016-09-30 13:55:48 · 1929 阅读 · 0 评论 -
suricata 3.1 源码分析24 (数据包解码模块执行)
/** * \brief This function passes off to link type decoders. * * DecodePcap reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to Threa原创 2016-09-29 10:40:14 · 1986 阅读 · 0 评论 -
suricata 3.1 源码分析23 (数据包解码模块注册及初始化)
简介 Suricata的解码模块与数据包获取模块是一一对应的,例如DecodePcap对应ReceivePcap,DecodeAFP对应ReceiveAFP。 然而,我们知道数据包格式都是协议规定的,因此核心的数据包解码流程一定会是固定的。例如,对于常规的以太网包IPV4包TCP包,无非是DecodeEthernet->DecodeIPV4->DecodeTCP->… 那么,这里为什么需要设置原创 2016-09-28 09:37:16 · 1892 阅读 · 2 评论 -
suricata 3.1 源码分析22 (数据包处理2)
对数据包进行进一步处理的TmThreadsSlotVarRun函数原型如下: TmEcode TmThreadsSlotVarRun(ThreadVars *tv, Packet *p,TmSlot *slot) 按照函数头的注释说明,这个函数被从母函数中拉出来独立存在的原因是,为了能够对其进行递归调用。函数主流程是一个遍历所有slot的for循环,/** * \brief S原创 2016-09-27 09:22:20 · 2058 阅读 · 0 评论 -
suricata 3.1 源码分析21 (数据包处理1)
进一步的数据包处理是在TmThreadsSlotProcessPkt中完成,其原型为: static inline TmEcode TmThreadsSlotProcessPkt(ThreadVars *tv, TmSlot *s, Packet *p) 其中,s就是前面一路传下来的slot,而p为当前要处理的Packet。/** * \brief Process the r原创 2016-09-26 17:20:32 · 2073 阅读 · 0 评论 -
suricata 3.1 源码分析20 (数据包封装)
在Suricata中,用来封装数据包的结构体为Packet,核心字段如下: 字段 含义 src/dst、sp/dp、proto 五元组信息:源/目的地址,源/目的端口号,传输层协议(TCP/UDP/…)。 flow 数据包所属的流指针(类型为Flow_ *)。 ip4h、ip6h 网络层数据指针。 tcph、udph、sctph、icmpv4/6h 传输层数据指原创 2016-09-23 09:47:51 · 3197 阅读 · 0 评论 -
suricata 3.1 源码分析19 (数据包获取)
初始化完成后,TmThreadsSlotPktAcqLoop函数将进入一个while循环,调用slot的PktAcqLoop函数获取并处理数据包。对应的模块函数原型为: TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot) 其中,data即为初始化阶段生成的PcapThreadVars结构体,而slot就是原创 2016-09-22 09:02:56 · 2817 阅读 · 0 评论 -
suricata 3.1 源码分析18 (模块注册及初始化)
Suricata支持多种数据包源:pcap(实时/文件)、nfq、ipfw、mpipe、af-packet、pfring、dag(实时/文件)、napatech。 每种数据包源的支持都对应于一个线程模块(Thread Module),得益于这种其模块化的架构,增加一个新的数据源支持只需要添加一个新的线程模块即可。 这里,我将主要记录最常见的pcap实时数据源的实现细节,包括相关数据结构、运行流程原创 2016-09-21 09:16:37 · 2381 阅读 · 0 评论 -
suricata 3.1 源码分析17 (流管理2)
TmThreadsManagementstatic void *TmThreadsManagement(void *td){ /* block usr2. usr2 to be handled by the main thread only */ UtilSignalBlock(SIGUSR2); ThreadVars *tv = (ThreadVars *)td;//流原创 2016-09-20 10:50:10 · 1666 阅读 · 0 评论 -
suricata 3.1 源码分析16 (流管理1)
在suricata.c的main函数执行完RunModeDispatch之后会在判断是否使用UNIX_SOCKET中调用FlowManagerThreadSpawn创建流管理线程。/** \brief spawn the flow manager thread */void FlowManagerThreadSpawn(){#ifdef AFLFUZZ_DISABLE_MGTTHREADS原创 2016-09-19 14:38:42 · 2079 阅读 · 0 评论 -
suricata 3.1 源码分析15 (流更新)
流更新通过FlowWorker线程函数中调用FlowUpdate,FlowUpdate中又调用了FlowHandlePacketUpdate来更新流。 在获取到包所属的流后,接下来将根据这个包对流进行更新。/** \brief Update Packet and Flow * * Updates packet and flow based on the new packet. * *原创 2016-09-18 11:36:26 · 1653 阅读 · 2 评论 -
suricata 3.1 源码分析14 (流查找分配)
流查找/分配通过FlowWorker线程函数中调用FlowHandlePacket来找到流。 下面将按照FlowHandlePacket的流程,分析flow engine对于新送入的解码后的数据包是如何处理的。 对于一个Packet,首先在流表中查找其所属的流是否已经存在,若存在,则直接返回该流的引用即可,否则就需要分配一个新流。 该过程的实现由FlowGetFlowFromHash完成,函数原创 2016-09-14 10:47:53 · 1870 阅读 · 0 评论 -
suricata 3.1 源码分析13 (流初始化)
简介Suricata中用于管理和维护流的模块称为Flow Engine,主要由两部分实现,第一部分的入口点是FlowHandlePacket函数,用于为新数据包进行流查找/分配,另一部分是FlowManagerThread线程,用于对超时的流进行删除。初始化 初始化在FlowInitConfig中完成,与之相关的配置结构体为FlowConfig,其字段含义如下: 字段含义hash_rand用于随原创 2016-09-13 14:08:43 · 2327 阅读 · 0 评论 -
suricata 3.1 源码分析12
int engine_retval = EXIT_SUCCESS; while(1) { if (sigterm_count) { suricata_ctl_flags |= SURICATA_KILL; } else if (sigint_count) { suricat原创 2016-09-12 15:03:49 · 1963 阅读 · 0 评论 -
suricata 3.1 源码分析11
/* Wait till all the threads have been initialized */ if (TmThreadWaitOnThreadInit() == TM_ECODE_FAILED) { SCLogError(SC_ERR_INITIALIZATION, "Engine initialization failed, "原创 2016-09-09 08:58:04 · 1512 阅读 · 0 评论 -
suricata 3.1 源码分析10
/* In Unix socket runmode, Flow manager is started on demand */ if (suri.run_mode != RUNMODE_UNIX_SOCKET) { /* Spawn the unix socket manager thread */ int unix_socket =原创 2016-09-08 17:21:36 · 2144 阅读 · 0 评论 -
suricata 3.1 源码分析9
RunModeDispatch(suri.run_mode, suri.runmode_custom_mode)初始化运行模式。首先,根据配置文件和程序中的默认值来配置运行模式(single、auto这些),而运行模式类 型(PCAP_DEV、PCAPFILE这些)也在之前已经确定了,因此运行模式已经固定下来,可以从runmodes表中获取到特定的RunMode 了,接着就调用RunMode中的Ru原创 2016-09-07 08:52:12 · 1879 阅读 · 0 评论 -
suricata 3.1 源码分析8
CSetStartTime(&suri);设置记录开始时间 SCDropMainThreadCaps(suri.userid, suri.groupid);去除主线程的权限。这个是通过libcap-ng实现的,首先调用capng_clear清空所有权限,然后根据运行模式添加一些必要权限(主要是为了抓包),最后调用capng_change_id设置新的uid和gid。主线程的权限应该会被新建原创 2016-09-06 13:24:15 · 1557 阅读 · 0 评论 -
suricata 3.1 源码分析7
DetectEngineCtx *de_ctx = NULL; if (!suri.disabled_detect) { //detect设为启用 SCClassConfInit();解析Class相关正则 SCReferenceConfInit();解析Refference相关正则 SetupDelayedDetect(&suri);原创 2016-09-05 14:17:28 · 2253 阅读 · 0 评论 -
suricata 3.1 源码分析6
if (suri.run_mode != RUNMODE_UNIX_SOCKET) { FlowInitConfig(FLOW_VERBOSE);初始化Flow engine。用来表示一条TCP/UDP/ICMP/SCTP流的,程序当前所记录的所有流便组成了流表,在flow引擎中,流表为flow_hash这个全局变量,其类型为FlowBucket *,而FlowBucket原创 2016-09-02 08:45:04 · 1782 阅读 · 0 评论 -
suricata 3.1 源码分析5
if (PostConfLoadedSetup(&suri) != TM_ECODE_OK) { exit(EXIT_FAILURE);}执行PostConfLoadedSetup,即运行那些需要在配置载入完成后就立马执行的函数。这里面涉及的流程和函数非常多 /** * This function is meant to contain code that原创 2016-09-01 08:57:07 · 4122 阅读 · 0 评论 -
suricata 3.1 源码分析4
GlobalInits();初始化全局变量。包括:数据包队列trans_q、数据队列data_queues(干嘛的?)、对应的mutex和cond、建立小写字母表。TimeInit();初始化时间。包括:获取当前时间所用的spin lock,以及设置时区(调用tzset()即可)。SupportFastPatternForSigMatchTypes();为快速模式匹配注册关键字。调用Suppor原创 2016-08-31 09:31:03 · 2736 阅读 · 0 评论 -
suricata 3.1 源码分析3
继续main函数下面的内容。/* By default use IDS mode, but if nfq or ipfw * are specified, IPS mode will overwrite this */EngineModeSetIDS();初始化引擎模式为IDS模式,字面上是这么理解。反正这个模式只有IPS和IDS两种,如果不清楚可以上网查。我这里就说一下主要区原创 2016-08-30 09:23:13 · 2849 阅读 · 0 评论 -
suricata 3.1 源码分析2
这次要说的是一个十分重要的函数RunModeRegisterRunModes();主要是完成运行模式的注册,我们添加的所有运行模式都要通过这个函数注册。下面是它的内部实现。 void RunModeRegisterRunModes(void) { memset(runmodes, 0, sizeof(runmodes));RunModeIdsPcapRegister();原创 2016-08-29 16:53:01 · 2882 阅读 · 0 评论