Fail2ban 封禁404攻击IP需同时满足:Nginx日志记录真实客户端IP、含404状态码、failregex正则精准匹配;否则将误封CDN或代理节点。

Fail2ban 能封 404 攻击 IP,但必须满足三个硬条件:Nginx 日志里有真实客户端 IP、含 404 状态码、且 failregex 正则能准确提取 <host></host> —— 缺一不可,否则封的全是 CDN 或代理节点。
确保 Nginx access.log 记录的是真实 IP 和 404 状态码
如果服务器前有 Cloudflare、Nginx 反向代理或宝塔面板,$remote_addr 默认是上游地址(比如 10.10.0.5),不是攻击者真实 IP。封错 IP 比不封更危险。
- 在
/etc/nginx/nginx.conf的http块中添加:set_real_ip_from 10.10.0.0/16;(替换成你实际的可信代理网段)real_ip_header X-Forwarded-For; - 日志格式必须用
$remote_addr(不是$http_x_forwarded_for)并包含$status:log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent'; - 验证方法:curl -I http://yourdomain.com/xxx(一个不存在路径),然后检查
/var/log/nginx/access.log是否出现你的公网 IP +"GET /xxx HTTP/1.1" 404
写一个只匹配 404 扫描行为的 filter
默认的 nginx-http-auth 不管 404,必须自己建规则。重点是「只抓扫描,不误伤健康检查或前端路由」。
- 新建文件:
/etc/fail2ban/filter.d/nginx-404.conf - 内容严格按以下写(注意空格和引号):
[Definition]failregex = ^<host> -.*"(GET|HEAD|POST) .+ HTTP/1\.[01]" 404 </host>ignoreregex = ^<host> -.*"(GET|HEAD) /(health|ping|metrics|robots\.txt) HTTP/.*" 404 </host> -
<host></host>是 Fail2ban 内置变量,自动提取 IP;ignoreregex必须写,否则/health返回 404 也会被封 - 测试是否生效:
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-404.conf,看输出里Lines: 12345 Matched: 89是否合理
配置 jail 并绑定 iptables 封禁动作
maxretry 和 findtime 不是越大越好。设成 30 次/10 分钟,对真实用户几乎无感,但能卡住目录爆破脚本;设成 5 次/60 秒,则可能误封刷新快的前端用户。
- 在
/etc/fail2ban/jail.local中追加:[nginx-404]enabled = truefilter = nginx-404logpath = /var/log/nginx/access.logmaxretry = 30findtime = 600bantime = 86400action = iptables-multiport[name=nginx-404, port="http,https", protocol=tcp] - 别用
jail.conf—— 升级会覆盖;jail.local才是安全修改位置 - 重启后用
fail2ban-client status nginx-404查看是否 running,并确认Journal entries数值在增长
封禁后怎么验证真生效了?
很多人配完以为 OK,其实 iptables 规则根本没加载,或者封的是 INPUT 链而非 fail2ban-nginx-404 自定义链。
- 手动触发一次:用 curl 多次请求不存在路径(如
for i in {1..35}; do curl -sI http://localhost/xxx$i; done) - 查封禁记录:
fail2ban-client status nginx-404,看Banned IPs是否出现你的测试 IP - 查 iptables 是否插入规则:
iptables -L fail2ban-nginx-404 -n,应看到类似REJECT all -- 1.2.3.4 0.0.0.0/0 reject-with icmp-port-unreachable - 最关键一步:换台机器 curl 测试 IP,应直接超时或被拒,而不是返回 404 —— 如果还返回 404,说明封禁没走通,大概率是 action 配错或防火墙服务冲突
最常被忽略的点:日志路径写错(比如写了 error.log 却在配 access.log 规则)、real_ip 没生效导致封的全是内网地址、以及 ignoreregex 漏掉内部监控路径造成误封。配完别急着上线,先拿自己 IP 测三遍。


















