当前位置:   article > 正文

入侵检测引擎之 Suricata 源码剖析_suricata 源码解析

suricata 源码解析

引言

从上一篇 “浅谈 Suricata”我们可以了解 Suricata 的安装部署大致框架、以及从配置方面谈及的性能优化。这篇文章则从代码角度带您剖析 Suricata。

通过本篇文章,您将了解以下知识点:

  • 收包和解包线程。
  • Flow-Worker 线程角色。
  • 队列负载均衡。
  • Detect 线程。
  • 应用协议解析层。
  • Output 输出层。
  • 代码框架优化。

Suricata

提到Suricata源码分析,我们首先需要了解suricata整体框架设计,只有你了解了整体框架,他才能对阅读源码有更好的促进作用。而提到框架则需要了解它的运行模式,在上一篇文章中说,suricata相对于传统snort引擎,它是由很多单独的线程模块所组成,使用者可以自行配置组合所需要的线程模块既可进行优化、自定义需求。默认的运行模式主要分为workers模式、autofp模式以及单线程模式single。workers模式主要是采用串行流水线的模式,针对单独数据流采取唯一线程 从头至尾处理,而autofp则是将收包和解包放在一个单独线程,而剩下的工作线程则通过队列传递数据包进行处理。 显然workers模式更适用于高效率处理数据包。

其次suricata支持多种抓包引擎,如:pcap、netmap、pfring、socket等。本文就pfring抓包引擎来谈一下数据包的流转以及部分解析引擎。 ##运行模式 涉及文件:runmodes.c 、util-runmodes.c、tm-thread.c、tm-queue ...... ###1. 注册运行模式

  1. void RunModeIdsPfringRegister(void)
  2. {
  3.   default_mode_autofp = "autofp";
  4.   RunModeRegisterNewRunMode(RUNMODE_PFRING, "autofp",
  5.                             "Multi threaded pfring mode. Packets from "
  6.                             "each flow are assigned to a single detect "
  7.                             "thread, unlike \\"pfring_auto\\" where packets "
  8.                             "from the same flow can be processed by any "
  9.                             "detect thread",
  10.                             RunModeIdsPfringAutoFp);
  11.   RunModeRegisterNewRunMode(RUNMODE_PFRING, "single",
  12.                             "Single threaded pfring mode",
  13.                             RunModeIdsPfringSingle);
  14.   RunModeRegisterNewRunMode(RUNMODE_PFRING, "workers",
  15.                             "Workers pfring mode, each thread does all"
  16.                             " tasks from acquisition to logging",
  17.                             RunModeIdsPfringWorkers);
  18.   return;
  19. }

主要数据结构

模块结构

  1. typedef struct TmModule_ {
  2. const char *name;
  3. TmEcode (*ThreadInit)(ThreadVars *, const void *, void **);
  4. ......
  5. } TmModule;
  6. TmModule tmm_modules[TMM_SIZE];

模块注册结构体,主要用于注册各个线程模块,提供全局变量tmm_modules, 便于组装回调。 如pfring模块注册:

  1. void TmModuleReceivePfringRegister (void)
  2. {
  3.   tmm_modules[TMM_RECEIVEPFRING].name = "ReceivePfring";
  4.   tmm_modules[TMM_RECEIVEPFRING].ThreadInit = ReceivePfringThreadInit;
  5.   tmm_modules[TMM_RECEIVEPFRING].Func = NULL;
  6.   tmm_modules[TMM_RECEIVEPFRING].PktAcqLoop = ReceivePfringLoop;
  7.   tmm_modules[TMM_RECEIVEPFRING].PktAcqBreakLoop = PfringBreakLoop;
  8.   tmm_modules[TMM_RECEIVEPFRING].RegisterTests = NULL;
  9.   tmm_modules[TMM_RECEIVEPFRING].flags = TM_FLAG_RECEIVE_TM;
  10. }

线程结构

  1. typedef struct ThreadVars_ {
  2.   pthread_t t;
  3.   char name[16];
  4.   char *printable_name;
  5.   char *thread_group_name;
  6.   SC_ATOMIC_DECLARE(unsigned int, flags);
  7.   uint8_t tmm_flags;
  8.   Tmq *inq;
  9.   Tmq *outq;
  10.   void *outctx;
  11.   const char *outqh_name;
  12.   struct Packet_ * (*tmqh_in)(struct ThreadVars_ *);
  13.   void (*InShutdownHandler)(struct ThreadVars_ *);
  14.   void (*tmqh_out)(struct ThreadVars_ *, struct Packet_ *);
  15.   void *(*tm_func)(void *);
  16.   struct TmSlot_ *tm_slots;
  17. ......
  18.   struct ThreadVars_ *next;
  19.   struct ThreadVars_ *prev;
  20. } ThreadVars;

线程结构,主要用于自由组装模块之后,提供线程队列绑定、线程句柄等。

队列结构

  1. typedef struct Tmqh_ {
  2. const char *name;
  3. Packet *(*InHandler)(ThreadVars *);
  4. void (*InShutdownHandler)(ThreadVars *);
  5. void (*OutHandler)(ThreadVars *, Packet *);
  6. void *(*OutHandlerCtxSetup)(const char *);
  7. void (*OutHandlerCtxFree)(void *);
  8. void (*RegisterTests)(void);
  9. } Tmqh;
  10. Tmqh tmqh_table[TMQH_SIZE];

队列数据结构,提供队列的注册回调、并提供全局句柄tmqh_table供线程绑定队列用。而队列主要包含 这几种: TMQH_SIMPLE, TMQH_NFQ, TMQH_PACKETPOOL, TMQH_FLOW, 这边我们主要关心TMQH_PACKETPO

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号