一、环境和背景
1.1 环境
OS: Ubuntu 22.04.5 LTS
IDE: vscode
suricata: suricata 7.0.5
1.2 背景
在添加规则时,为了给规则分类,将不同类别的规则写入不同的文件。
在规则加载时两条不同的规则却被认为是重复的,因此记录一下去重逻辑。
a.rule
alert ip any any -> any any (msg:"SURICATA Applayer Mismatch protocol both directions"; flow:established; app-layer-event:applayer_mismatch_protocol_both_directions; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260000; rev:1;)
b.rule
alert http any any -> any any (msg:"SURICATA HTTP unknown error"; flow:established; app-layer-event:http.unknown_error; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260000; rev:1;)
suricata.yaml
rule-files:
- a.rule
- b.rule
二、 Suricata 规则去重
suricata 规则通过一个hashtable进行去重。
2.1 hashtable 建立
// src/suricata.c
PostConfLoadedDetectSetup
// src/detect-engine.c
-> DetectEngineCtxInit
// src/detect-engine.c
-> DetectEngineCtxInitReal
// src/detect-parse.c
-> DetectParseDupSigHashInit
// src/suricata.c
-> LoadSignatures
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
{
de_ctx->dup_sig_hash_table = HashListTableInit(15000,
DetectParseDupSigHashFunc,
DetectParseDupSigCompareFunc,
DetectParseDupSigFreeFunc);
if (de_ctx->dup_sig_hash_table == NULL)
return -1;
return 0;
}
2.2 检测重复
// src/detect-parse.c
Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, const ch
{
// 1. 解析规则
Signature *sig = SigInit(de_ctx, sigstr);
if (sig == NULL) {
return NULL;
}
// 2. 检测重复
/* checking for the status of duplicate signature */
int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
...
}
static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx
Signature *sig)
{
/* we won't do any NULL checks on the args */
/* return value */
int ret = 0;
SigDuplWrapper *sw_dup = NULL;
SigDuplWrapper *sw = NULL;
/* used for making a duplicate_sig_hash_table entry */
sw = SCMalloc(sizeof(SigDuplWrapper));
if (unlikely(sw == NULL)) {
exit(EXIT_FAILURE);
}
memset(sw, 0, sizeof(SigDuplWrapper));
sw->s = sig;
/* check if we have a duplicate entry for this signature */
sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
/* we don't have a duplicate entry for this sig */
if (sw_dup == NULL) {
...
}
...
}
2.3 重复条件
static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
uint16_t len2)
{
SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
if (sw1 == NULL || sw2 == NULL ||
sw1->s == NULL || sw2->s == NULL)
return 0;
/* sid and gid match required */
if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
return 0;
}
以sid
和gid
作为重复条件,全部相等时则认为重复,不看具体的规则内容。
三、总结
- suricata规则通过
sid
和gid
进行去重,并不关注规则中的具体内容 - 通过
sid
和gid
唯一区分规则,整个工程里对规则的处理相较于字符串,整数值处理更简单高效 - 如果需要将规则拆分成多个文件时,需要注意sid的值