对高误报规则实施阈值与抑制调优

约 30 分钟

能针对高误报规则配置 threshold 与 suppress,使告警数量显著下降且真实攻击仍可检出。

上一课你已经会用 threshold 按次数与时间窗口聚合高频告警,用 suppress 按 sid 与地址静音已知噪声,也在自定义规则上用 -T 校验、-r 回放验证过压噪效果。当时特别强调:抑制只是让告警队列安静下来,并不等于修复误报的根因。这一课就把这两件工具放进一个完整流程——从量化噪声开始,到选择工具、落地配置,最后回放对比收尾。

先把问题量化,别凭感觉改规则。先用 Wireshark 看懂 PCAP 里有什么——官方论坛与社区教程都是这个流程。然后回放同一份授权测试 PCAP,检查 fast.log,统计每条规则的告警数量,找出 top 几条。分析告警时可以用 jq 阅读 EVE JSON 输出(Quickstart 推荐用 jq)。离线回放用 -r path-to-pcap 选项,再检查 fast.log 是否命中规则。

拿到统计结果后做两个判断:噪声来自“同一来源反复触发”,用 threshold 聚合;噪声来自“已确认无害的固定来源”,用 suppress 屏蔽。两者都是上一课掌握的关键字,这一课只做选择与落地。

最后回放同一份 PCAP,对比调优前后。边界不变:只针对本地授权测试 PCAP 与你自己管理的规则文件,不对任何未授权目标做探测。

怎么选 threshold 还是 suppress?先做类比。threshold 像地铁闸机:同一张卡短时间内反复刷,只在真正通过时计一次,陌生人的通行不受影响。suppress 像免打扰名单:某个确定的人被直接请出去,他的行为不再打扰你,其他人的提醒照常。

对应到技术判断:告警来自少数源 IP 的高频重复,用 threshold 限制时间窗口内的告警数;告警来自你确认无害的固定来源,用 suppress 屏蔽该来源。真实攻击多为单次或低频,两类手段都不会把它吞掉。

threshold 与 suppress 属于 Suricata 官方文档的 Thresholding Keywords 章节(rules/thresholding.html),完整语法以该章节与上一课内容为准。

对高误报规则实施阈值与抑制调优

  1. 1

    准备授权测试 PCAP 与规则文件。规则文件默认位于 /var/lib/suricata/rules 下的 suricata.rules(Quickstart 说明)。放两条规则:噪声规则 sid:2024001 匹配带 curl 用户代理的入站 HTTP 请求;攻击规则 sid:2024002 匹配入站 HTTP URI 中的命令注入载荷。

    text
    alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"使用 curl 的入站 HTTP 请求"; content:"curl"; http_user_agent; nocase; sid:2024001; rev:1;)
    alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"命令注入尝试"; content:"/bin/sh"; http_uri; nocase; sid:2024002; rev:1;)
  2. 2

    建立基线。用 -r path-to-pcap 离线回放 PCAP,查看 fast.log,按 gid:sid:rev 统计各规则出现次数,找出 top 误报规则。

    bash
    suricata -r /data/lab.pcap
    grep -oE '\[[0-9]+:[0-9]+:[0-9]+\]' /var/log/suricata/fast.log | sort | uniq -c | sort -rn
  3. 3

    判断噪声来源。假设结果:198.51.100.23 的 curl 请求每小时触发数百条 sid:2024001,你已确认它是授权测试源(无害);攻击源 203.0.113.5 的单次命令注入同时触发 sid:2024001 与 sid:2024002。

  4. 4

    给高频规则加 threshold:沿用上一课语法,按源 IP 限制时间窗口内告警数,rev 升到 2。

    text
    alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"使用 curl 的入站 HTTP 请求"; content:"curl"; http_user_agent; nocase; threshold: type limit, track by_src, count 5, seconds 60; sid:2024001; rev:2;)
  5. 5

    给已知噪声源加 suppress:把确认无害的 198.51.100.23 加入该规则抑制名单,其余来源不受影响。gen_id 按 fast.log 中 gid:sid:rev 的 gid 填写。

    text
    alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"使用 curl 的入站 HTTP 请求"; content:"curl"; http_user_agent; nocase; threshold: type limit, track by_src, count 5, seconds 60; suppress: gen_id 1, sig_id 2024001, track by_src, ip 198.51.100.23; sid:2024001; rev:2;)
  6. 6

    校验并回放。先用上一课掌握的测试模式校验规则文件,通过后对同一份 PCAP 再次离线回放。

  7. 7

    对比前后。统计两次回放中 sid:2024001 的告警数,确认显著下降;再确认 sid:2024002 的攻击告警仍出现在 fast.log。

你应该看到

调优后回放同一份 PCAP:sid:2024001 的告警数量较基线显著下降,sid:2024002 的攻击告警仍保留在 fast.log。若攻击告警消失,说明 threshold 或 suppress 参数过严,按 troubleshoot 调整后重跑。

遇到问题:修改规则后回放,告警数量与调优前完全一样。

可能原因

  • 改写的是 Suricata 实际加载的规则文件之外的副本。
  • suricata.yaml 中 fast.log 输出未启用。
  • threshold 或 suppress 加在了错误的 sid 上。

排查步骤

  1. 确认写入 Suricata 实际加载的规则文件(默认 /var/lib/suricata/rules 下的 suricata.rules)。
  2. 确认 suricata.yaml 中 fast.log 输出已启用(官方论坛明确提醒过这一点)。
  3. 用 fast.log 的 gid:sid:rev 核对 sid 与 gen_id。

遇到问题:规则解析报错,Suricata 拒绝加载规则文件。

可能原因

  • threshold 或 suppress 语法错误:缺少结尾分号、track 取值拼写错误、数字位置错误。
  • 一次改了多条规则,报错规则难以定位。

排查步骤

  1. 用测试模式定位报错规则。
  2. 一次只改一条,改完立即校验。
  3. 对照上一课语法与官方 Thresholding Keywords 章节核对。

遇到问题:噪声降下来了,攻击告警也消失。

可能原因

  • threshold 过严:count 太小或 seconds 太大,单次攻击事件被聚合掉。
  • suppress 的 ip 或 track 范围覆盖了攻击源。

排查步骤

  1. 把 suppress 收紧到确切的噪声源 IP,不要用大网段。
  2. 优先用 type limit(保留窗口内告警)而不是 type threshold(凑够次数才告警)。
  3. 回放后同时核对噪声规则与攻击规则的 sid,确认攻击告警仍在。
自检:调优后回放同一份 PCAP,你如何证明“噪声下降”且“真实攻击仍可检出”?请给出具体核对对象。

先统计基线回放中噪声规则(sid:2024001)的告警数,再统计调优后回放的告警数,确认显著下降;然后单独在 fast.log 中查找攻击规则(sid:2024002)与攻击源 IP(203.0.113.5)的告警,确认调优后仍然出现。若攻击告警缺失,说明参数过严,收紧 suppress 范围或放宽 threshold 后重新回放验证。