Suricata 快速模式匹配机制详解 ============================================= 若规则中显式设置了 'fast_pattern' 关键字,Suricata 将直接采用该内容作为快速模式匹配项。每条规则中 'fast_pattern' 关键字仅能设置一次。若未设置,Suricata 会自动选择最合适的内容作为快速模式匹配项。 下文将阐述 Suricata 自动确定快速模式匹配项的逻辑规则。 需注意:当规则中存在正向(非否定)内容匹配项时,否定型内容匹配项在快速模式选择过程中会被忽略。反之,则会纳入考量范围。 快速模式选择标准如下: #. Suricata 首先识别规则中具有最高"优先级"的所有内容匹配项。优先级基于匹配的缓冲区类型,通常应用层缓冲区具有更高优先级(数值越小优先级越高)。但 `http_method` 缓冲区例外,其优先级低于常规的 `content` 缓冲区。 #. 在步骤1筛选出的最高优先级内容匹配项中,选择字符/字节长度最长的作为快速模式匹配项。 #. 若多个内容匹配项具有相同最高优先级且长度相同,则选择字符/字节多样性得分("模式强度")最高者作为快速模式匹配项。具体算法详见 :ref:`附录A `。 #. 若多个内容匹配项具有相同最高优先级、相同长度及相同模式强度,则选择缓冲区("list_id")注册时间最晚者作为快速模式匹配项。 #. 若多个内容匹配项具有相同最高优先级、相同长度、相同模式强度且属于同一缓冲区(即list_id相同),则选择规则中从左到右最先出现的匹配项作为快速模式匹配项。 值得注意的是,对于具有相同优先级、长度和模式强度的内容匹配项,'http_stat_msg'、'http_stat_code' 和 'http_method' 会优先于常规 'content' 匹配项被选中。 附录 ---------- .. _fast-pattern-explained-appendix-a: 附录A - 模式强度算法 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 算法实现位于 detect-engine-mpm.c。模式强度"得分"初始为零,从左至右扫描字节数组中的每个字符/字节:若该字符/字节首次出现,字母字符加3分;可打印字符或0x00/0x01/0xFF加4分;其他字符加6分。若字符/字节重复出现则加1分。最终返回总分。 .. code-block:: c /** \brief 计算模式强度值 * * 字符多样性高的模式得分更高 * 字母字符得分较低 * 其他可打印字符及特定控制码得分中等 * 其余字符得分最高 * 长模式优于短模式 * * \param pat 模式字节数组 * \param patlen 模式长度 * * \retval s 模式强度得分 */ uint32_t PatternStrength(uint8_t *pat, uint16_t patlen) { uint8_t a[256]; memset(&a, 0 ,sizeof(a)); uint32_t s = 0; uint16_t u = 0; for (u = 0; u < patlen; u++) { if (a[pat[u]] == 0) { if (isalpha(pat[u])) s += 3; else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF) s += 4; else s += 6; a[pat[u]] = 1; } else { s++; } } return s; }