从 fail2ban 到协同防御——WardenNet 检测架构解析
前言
自己维护的博客服务器每天被自动化扫描器骚扰上万次。传统防护手段遇到的问题:
- fail2ban 正则匹配容易误封搜索引擎爬虫
- Nginx rate_limit 被扫描器压 QPS 绕过
- 手动 ipset add 每周花 20 分钟
最终选择了 WardenNet——一个 Go 写的基线自学习协同防御 Agent。本文解析它的检测架构设计。
架构总览

核心思想:每台 Web 服务器旁放一个轻量级 Go Agent(约 5.8MB),组成协同防御网络。
Agent 职责:
- 实时解析 Nginx/Apache/Tomcat 访问日志
- 三档滑动窗口统计每个 IP 的行为特征
- 6 层防御 + 5 维评分判断威胁
- 内核级 ipset/iptables DROP 封禁
单机可用,协同更强。
基线自学习:不预设阈值
传统防护脚本统计"过去 N 秒请求总数",超过阈值就拉黑。扫描器把 QPS 压到阈值以下就能绕过。
WardenNet 用三档独立滑动窗口解决:
detector:
windows:
- size: 10 # 捕捉突发扫描
- size: 30 # 捕捉持续扫描
- size: 60 # 捕捉慢速扫描
评分不是看绝对值,而是看偏离 P95 基线的倍数:
deviation_score = 当前值 / P95基线值
同样是 QPS 500,对小博客是攻击,对电商首页刷新可能只是常态。这就是基线自学习的精妙之处。
6 层防御体系
| 层级 | 机制 | 作用 |
|---|---|---|
| L1 | 流量异常检测 | QPS 突增、404 比例 |
| L2 | 攻击特征匹配 | Bot UA、敏感路径、危险方法 |
| L3 | 协同信号分析 | 多特征关联 |
| L4 | 防误报 | 空 Referer 硬封顶 |
| L5 | 防投毒 | 智能去重、QPS 限流 |
| L6 | 快速响应 | 白名单优先、ForceBlock |
关键设计:空 Referer 硬封顶
恶意扫描器几乎都是空 Referer,但正常 curl/Postman 也是空 Referer。WardenNet 把空 Referer 分数硬封顶在 score_high/4,纯空 Referer 扫描器难以单独触发封禁,但如果同时命中 /.env 等敏感路径,绝对权重叠加。
5 维一致性评分

核心问题:高 QPS 的 IP,到底是 bot 还是勤奋的真实用户?
WardenNet 的答案是 5 维一致性评分。不依赖任何 header,只看 access log 必有字段:
| 维度 | 检测什么 | 权重 |
|---|---|---|
| 前缀连贯度 | 请求路径第一段是否集中 | +2 |
| 新颖度饱和 | 前 30% 请求是否覆盖大部分路径 | +2 |
| 路径集中度 | Top 5 路径访问占比 | +2 |
| 状态同质性 | 同一路径状态码变异系数 | +1 |
| 方法语义符合度 | GET/POST/PUT/DELETE 比例 | +1 |
总分 >= 4 判为良性。反信号扣分:反复撞墙 -5,发散扫描 -3。
协同防御:打散型扫描
扫描器把 QPS 分散到 N 台服务器,单机看每台只是"轻微偏离"。
| 场景 | 评分 | 决策 |
|---|---|---|
| 单机 | Local=45, Detector=40 | < 50,放过 |
| 协同 | Cloud=72 + Local + Detector -> 58 | >= 50,拉黑 |
云端聚合后,每台单机的轻微偏离变成全网威胁。
决策引擎
三路信号加权:Cloud + Local + Detector。
| 综合评分 | 动作 |
|---|---|
| >= 80 | 拉黑 |
| >= 50 | 告警 |
| < 50 | 忽略 |
云端只下发评分,不下发封禁指令——最终决策权在 Agent。
总结
- 基线自学习消除预设阈值
- 5 维评分过滤误报
- 6 层防御 + 防投毒机制
- 单机可用、协同更强
- 零外部依赖,Go 单二进制约 5.8MB
GitHub:github.com/wardennet/wardennet
许可:AGPLv3

浙公网安备 33010602011771号