limit_req是Nginx实时限速的第一道防线,Fail2ban是基于error.log事后封禁的守门人;二者分工明确、不可替代,需独立配置并互补覆盖,而非串联联动。

Nginx 的 limit_req 和 Fail2ban 不是“配合使用”的关系,而是分工明确、各司其职:limit_req 负责实时拦截超速请求(第一道防线),
Fail2ban 负责事后识别恶意行为并封 IP(最后一道守门人)。
两者不能串联成“limit_req 触发后自动通知 Fail2ban”,因为 Nginx 本身不向 Fail2ban 发送事件;Fail2ban 只能被动读日志——而且必须是它能“看懂”的错误信号。
所以真正可行的组合方式,是让两者独立生效、互补覆盖:
✅ 正确理解二者角色
-
limit_req是 Nginx 内置模块,工作在请求处理早期,基于内存状态做毫秒级限速(如每秒最多 10 次),超限直接返回503,不消耗后端资源。 - Fail2ban 是外部守护进程,依赖日志分析,延迟几十秒到几分钟才封 IP,适合识别反复触发特定错误的行为(如多次 upstream timeout、SSL handshake 失败、非法请求头),而非单纯高频访问。
⚠️ 注意:Fail2ban 默认规则(如
nginx-http-auth)匹配 access.log 中的 401/403,但真实 CC 攻击常返回 200,这类流量根本不会被传统 filter 捕获。靠它防 CC 效果极差。
✅ Nginx 配置 limit_req(必须做)
在 http {} 块中定义限流区域,在 location 中启用:
http {
# 按二进制 IP 地址限流,10MB 内存约存 16 万个 IP
limit_req_zone $binary_remote_addr zone=cc_limit:10m rate=15r/s;
server {
location / {
# 允许突发 30 个请求,不排队,超了立刻 503
limit_req zone=cc_limit burst=30 nodelay;
proxy_pass http://backend;
}
# 登录接口更严格(防爆破)
location /api/login {
limit_req zone=cc_limit burst=5 nodelay;
limit_req_status 429; # 返回 429 Too Many Requests
}
}
}-
rate=15r/s:平均速率,建议 API 接口设为30r/s,静态站设为10r/s -
burst=30:漏桶容量,避免用户刷新误杀 -
nodelay:关键!不加会导致请求排队,反而压垮后端
? 如果用了 CDN(如 Cloudflare),务必先在宝塔或 Nginx 中配置
real_ip,否则$binary_remote_addr拿到的是 CDN 节点 IP,全站限流就失效了。
✅ Fail2ban 配置 error.log 封禁(精准补位)
只对 Nginx error.log 中高攻击指向性错误建 filter,例如:
upstream timed outconnect() failed (111: Connection refused)client sent invalid requestSSL_do_handshake() failed
步骤如下:
-
确保 error.log 记录足够详细
在nginx.conf的http块中设置:error_log /var/log/nginx/error.log warn;
-
新建 filter 文件
/etc/fail2ban/filter.d/nginx-upstream-timeout.conf:[Definition] failregex = ^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\].*upstream timed out.*<HOST> ignoreregex = -
添加 jail 规则(在
/etc/fail2ban/jail.local中):[nginx-upstream-timeout] enabled = true filter = nginx-upstream-timeout logpath = /var/log/nginx/error.log maxretry = 5 findtime = 60 bantime = 7200 action = iptables[name=NGINX_TIMEOUT, port=http,https, protocol=tcp]
? 这样配置后,一个 IP 若 1 分钟内触发 5 次 upstream timeout,就会被 iptables 封禁 2 小时——这比单纯限流更能揪出慢速攻击、代理探测等隐蔽行为。
❌ 不要做的误区
- 不要用 Fail2ban 匹配 access.log 中的请求频次来“替代”
limit_req:日志写入有延迟,等它数完 100 行,服务器可能已 OOM。 - 不要在同一个
limit_req_zone下混用多个location:登录页和首页共用一个 zone,会导致用户登不上也刷不了首页。 - 不要忽略 CDN 场景下的真实 IP 获取:没配
set_real_ip_from和real_ip_header,所有限流和封禁都作用于错误 IP。
Fail2ban 不是限流开关,它是从 error.log 里翻出“已经动手的人”再关门。真正的防护节奏是:
Nginx 用 limit_req 把流量压下来 → 后端稳住 → Fail2ban 从 error.log 找出捣乱者拉黑。


















