suricata的模块和插槽

参考资料

suricata官方文档https://suricata.readthedocs.io/en/latest/performance/runmodes.html#different-runmodes

suricata的源代码https://blog.csdn.net/shenwansangz/article/details/37900875?utm_medium=distribute.pc_relevant.none-task-blog-utm_term-3&spm=1001.2101.3001.4242

suricata的总体架构https://www.cnblogs.com/zlslch/p/7382176.html

suricata数据结构https://blog.csdn.net/gengzhikui1992/article/details/103031874?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param

原理

suricata是基于模块(TMmoudle)的,所谓模块是suricata中的数据结构:

typedef struct TmModule_ {
    char *name;          // 模块名称
    TmEcode (*ThreadInit)(ThreadVars *, void *, void **);
    void (*ThreadExitPrintStats)(ThreadVars *, void *);
    TmEcode (*ThreadDeinit)(ThreadVars *, void *);
    TmEcode (*Func)(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
    TmEcode (*PktAcqLoop)(ThreadVars *, void *, void *);
    TmEcode (*Init)(void);
    TmEcode (*DeInit)(void);
    void (*RegisterTests)(void);
    uint8_t cap_flags;  
    uint8_t flags;
} TmModule;

每个模块代表一个特定的功能。
例如获取报文、解码报文、检测报文、记录日志这四个模块。
前一个模块的输出是后一个模块的输入,它们各自拥有一个线程。多线程是suricata具有较高性能的保证。
在这里插入图片描述
模块和模块之间的联系通过suricata中的插槽(slot)这一数据结构相连。

typedef struct TmSlot_ {

    ThreadVars *tv;                       // 拥有该slot的线程
    SC_ATOMIC_DECLARE(TmSlotFunc, SlotFunc);// 函数指针
    TmEcode (*PktAcqLoop)(ThreadVars *, void *, void *);      // 模块数据包获取函数
    TmEcode (*SlotThreadInit)(ThreadVars *, void *, void **); // 模块初始化执行函数
    void (*SlotThreadExitPrintStats)(ThreadVars *, void *);   // 模块退出打印函数
    TmEcode (*SlotThreadDeinit)(ThreadVars *, void *);        // 模块清理执行函数
    void *slot_initdata;  // 数据存储
    SC_ATOMIC_DECLARE(void *, slot_data);
    PacketQueue slot_pre_pq;
    PacketQueue slot_post_pq;
    int tm_id;  // tm ID
    int id;     // slot ID
    struct TmSlot_ *slot_next;
} TmSlot;

每个线程运行一个slot对象,slot负责管理其上的模块。包括该模块的初始化,以及对模块数据包的获取和模块的退出和清理。
数据从一个模块到另一个模块是通过slot结构体中的 struct TmSlot_* 指针指向下一个slot,并将数据包输入至下一个slot管理的TmModule上。
在这里插入图片描述
图中有3个插槽,每个插槽各有一个模块,3个插槽各自启动了一个线程。类似生产者和消费者原理,模块i是模块i-1的消费者,模块i-1是模块i的生产者。使用模块-插槽结构的好处是便于添加中间组件对数据包进行处理。同时模块化也便于利用多线程。

suricata的模块需要被注册,注册函数名为 TmModuleXXXRegister(void),模块被注册后便被存入全局数组 TmModule tmm_modules[TMM_SIZE]中。该数组使用了枚举-索引方式。用枚举的方式对数组每个位命名。

typedef enum{
TMM_DECODEDFQ,
TMM_XXXX
};

枚举数正好对应TMM数组的index。

运行模式(run-mode)

在suricata中,线程,模块和队列排列在一起的方式称作运行方式。

suricata如何封包捕获?

suricata中的AF_PACKET和PF_RING方法可以捕获数据包。

原文地址:https://www.cnblogs.com/goto2091/p/13705685.html