suricata 4.0.3 配置模块
配置部分主要涉及两个变量:
- main函数中的局部变量
SCInstance suri
- conf.c中的静态全局变量
static ConfNode *root
SCInstance suri
1 | typedef struct SCInstance_ { |
1 | /* Run mode */ |
在ConfInit()
初始化root变量后,开始解析命令行参数,会填充suri变量和root变量所链接的表结构。
main函数中定义了SCInstance suri;
,其中成员如下:
- run_mode
- 枚举类型,依据命令行参数中指定的抓包引擎而设定,比如
--pcap
参数会设定run_mode为RUNMODE_PCAP_DEV
。命令行参数解析完成后会写入全局变量run_mode
。
- 枚举类型,依据命令行参数中指定的抓包引擎而设定,比如
- pcap_dev
- 命令行参数提供的抓包设备的名字,超长会截断至128字节限制。比如
--pcap
参数如果有值,则会存储该值或该IP所对应的设备名,同时会被传入函数int LiveRegisterDevice(const char *dev)
,用以将需要抓包的设备连接到一个链表中。命令行参数多次传入设备名时,该字段每次会被清空再使用,这个字段看起来更像是一个缓冲区的作用。在后续的配置文件加载完成后,会再次检查该字段,用以确定是否需要使用配置文件中的设备列表,如果使用配置文件中的列表同样需要注册到前文提到的链表中。
- 命令行参数提供的抓包设备的名字,超长会截断至128字节限制。比如
- sig_file
- 填充为命令行参数
-s/-S
的值,用于记录需要包含或排除的特征文件。
- 填充为命令行参数
- sig_file_exclusive
- 用于标识sig_file是需要包含的特征文件还是需要排除的特征文件。
- pid_filename
- 填充为命令行参数
--pidfile
的值。
- 填充为命令行参数
- regex_arg
- 填充为命令行参数
-U
的值,unittest使用的过滤器。
- 填充为命令行参数
- keyword_info
- 填充为命令行参数
--list-keywords
的值(如果提供的话),这里的keyword是检测引擎使用的特征关键字。
- 填充为命令行参数
- runmode_custom_mode
- 填充为命令行参数中的
--runmode
值。
- 填充为命令行参数中的
- delayed_detect
- 由配置文件中的
detect.delayed-detect
项设定。设定为真的话,将在抓包启动开始加载特征文件,这将有助于降低IPS模式下的宕机时间。
- 由配置文件中的
- disabled_detect
- 由编译参数决定初始值,同时命令行参数
--disable-detection
也会将该值设定为真。
- 由编译参数决定初始值,同时命令行参数
- daemon
- 命令行参数出现
-D
则置1,用于标识是否以守护进程运行。
- 命令行参数出现
- offline
- 命令行参数解析完成后,以
runmode
项值确定,以下值将使offline
为真。RUNMODE_CONF_TEST
RUNMODE_PCAP_FILE
RUNMODE_ERF_FILE
RUNMODE_ENGINE_ANALYSIS
RUNMODE_UNIX_SOCKET
- 命令行参数解析完成后,以
- verbose
- 由命令行参数
-v
设定,影响日志模块,使日志等级提升一个值。
- 由命令行参数
- checksum_validation
- 默认值为unknown。若命令行提供了
-k
参数,则设置为all(1)或none(0)。若加载配置文件后该值依然为unknown,则会读取配置文件项capture.checksum-validation
,若为all或none则设置该值。进一步影响配置文件项stream.checksum-validation
,也就是说命令行参数的有效值是会覆盖配置文件项的。配置文件项stream.checksum-validation
在使用时值为”1”为检查checksum,其他值皆不检查。
- 默认值为unknown。若命令行提供了
- start_time
- 记录启动时间,进程结束后会计算运行时间。
- log_dir
- 记录日志文件所在目录。该值的配置优先级为:
- 命令行参数
-l
- 配置文件项
default-log-dir
- 宏定义
#define DEFAULT_LOG_DIR "/var/log/suricata"
- 命令行参数
- 记录日志文件所在目录。该值的配置优先级为:
- progname
- 顾名思义,存储
argv[0]
。
- 顾名思义,存储
- conf_filename
- 配置文件路径。该值的配置优先级为:
- 命令行参数
-c
- 宏定义
#define DEFAULT_CONF_FILE CONFIG_DIR "/suricata.yaml"
- 命令行参数
- 配置文件路径。该值的配置优先级为:
设定的抓包设备会注册在一个链表中1
int LiveRegisterDevice(const char *dev)
链表结构为1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** storage for live device names */
typedef struct LiveDevice_ {
char *dev; /**< the device (e.g. "eth0") */
char dev_short[MAX_DEVNAME + 1];
int ignore_checksum;
SC_ATOMIC_DECLARE(uint64_t, pkts);
SC_ATOMIC_DECLARE(uint64_t, drop);
SC_ATOMIC_DECLARE(uint64_t, invalid_checksums);
TAILQ_ENTRY(LiveDevice_) next;
uint32_t offload_orig; /**< original offload settings to restore @exit */
} LiveDevice;
static ConfNode *root
加载配置文件晚于命令行参数解析,配置文件路径取suri->conf_filename。若命令行参数未提供路径,则填充为默认路径DEFAULT_CONF_FILE
。
1 | /** |
1 | vars: |
这个假设的配置段包含了几种结构,足够体现suricata配置文件需要的几种结构,更深的结构可以多次组合
- mapping内嵌套mapping
- mapping内嵌套sequence,sequence内包含scalar
- mapping内嵌套sequence,sequence内嵌套mapping
下图显示了几种结构在内存中的关系,其中的链表结构参考Tail queue。ConfNode结构体成员部分理解如下:
- is_seq,两种情况下被置为1
- 图2的rule-files节点和图3的outputs节点,用以标明这个mapping节点的值是一个sequence,但是这个标记并没有什么实际用处,只在获取rule-files节点用以加载特征文件时检查了一下。
- 图3的0节点和1节点,当sequence内嵌套mapping时,在outputs和fast/eve-log节点间生成了一个中间节点,这个中间节点的is_seq被置为1,这里的标记更没有用处。
- val,值存在几种情况
- sequence内scalar节点的值,这时其name为sequence内索引序号。
- mapping节点value是scalar类型时,val为其value的值,这时其name为key的值。
- 上文提到的中间节点后所连接的mapping结构的第一个key,配置文件中sequence内mapping结构全部是只有一对key-value的,且value是又一个mapping结构。在这种情况下,这个val的作用是用于查找中间节点后连接的节点。这种情况下val并没有什么作用,完全可以顺序获取。
- final,命令行参数所生成的节点的final值被置1。当加载配置文件遇到配置需要覆盖时,final为1的节点不被覆盖,只是会被移除并重新加入链表用以保证链表顺序与配置文件写作顺序一致。
- parent, 看起来也没什么用。
下面以配置节点查找操作举例使用方式
1 | /** |
1 | /** |
配置部分的代码没有对YAML的所有结构完成有效的支持,比如多层sequence嵌套在suricata配置解析中就会出现问题。但由于suricata配置文件中没有出现这种结构,所以配置部分的代码对此特定应用的配置文件解析足够用了。