fail2ban可通过自定义filter从nginx error.log中提取含client ip的恶意错误行(如connect() failed 111),匹配后按jail规则封禁ip。需精准正则提取ip+行为特征,排除纯服务错误,并绑定iptables动作。
![怎么利用错误日志中的 [error] 级别指纹通过 fail2ban 自动触发系统防火墙封禁恶意 ip](https://img.php.cn/upload/article/001/242/473/178203272722365.jpg?x-oss-process=image/resize,p_40)
Fail2ban 本身不直接分析 [error] 级别的日志行(比如 Nginx 的 error.log 中的 *12345 connect() failed (111: Connection refused)),它依赖的是可匹配的失败行为模式——而 [error] 是日志级别标签,不是攻击特征。真正起作用的是错误背后所反映的恶意行为指纹,比如反复请求不存在的路径、伪造 UA、触发 401/403/502、连接上游失败等。关键在于:你得从 [error] 行里提取出能唯一标识“恶意意图”的字段(尤其是 IP + 行为组合),再用正则把它定义成 Fail2ban 的 filter。
下面分三步说清楚怎么做:
明确哪些 [error] 日志能当封禁依据
不是所有带 [error] 的行都该封,要挑有攻击指向性的。常见有效指纹包括:
- Nginx
error.log中反复出现的no live upstreams while connecting to upstream(说明在扫后端服务) -
connect() failed (111: Connection refused)+ 同一 IP 在短时间内高频出现 -
client sent invalid request或upstream timed out配合非常规请求头(如空 Host、异常 UA) - Apache 或自定义应用日志中
Invalid URI in request+clientIP 字段
⚠️ 注意:纯服务内部错误(如 open() "/tmp/xxx" failed (13: Permission denied))不能封,那是配置问题,不是攻击。
写一个专用 filter 匹配 [error] 中的恶意 IP
以 Nginx error.log 为例,先确认典型错误行格式(用 sudo tail -20 /var/log/nginx/error.log 查看):
2026/06/19 08:42:11 [error] 12345#12345: *6789 connect() failed (111: Connection refused) while connecting to upstream, client: 192.0.2.100, server: example.com, request: "GET /wp-admin/ HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "example.com"
→ 关键提取点是 client: XXX.XXX.XXX.XXX 和 [error] 标签共存,且行为具备扫描特征(如 /wp-admin/、/phpmyadmin/)。
新建 filter 文件 /etc/fail2ban/filter.d/nginx-upstream-scan.conf:
[Definition]
failregex = ^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\].*connect\(\) failed \(111: Connection refused\) while connecting to upstream.*client: <host>,.*
ignoreregex =</host>
-
<host></host>是 Fail2ban 内置宏,自动识别 IPv4/IPv6 - 正则必须严格锚定时间+
[error]+关键词+client:,避免误匹配 warn 或 info 行
测试是否生效:
sudo fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/nginx-upstream-scan.conf
绑定 jail 并联动防火墙动作
在 /etc/fail2ban/jail.local 中添加:
[nginx-upstream-scan] enabled = true filter = nginx-upstream-scan logpath = /var/log/nginx/error.log port = http,https action = iptables-multiport[name=nginx-scan, port="http,https", protocol=tcp] maxretry = 5 findtime = 600 bantime = 3600 ignoreip = 127.0.0.1/8 192.168.0.0/16 203.0.113.0/24 # 填你自己的运维网段
-
maxretry = 5+findtime = 600表示:10 分钟内同一 IP 触发 5 次 upstream 连接拒绝,就封 1 小时 -
action明确调用 iptables,只封 HTTP/HTTPS 端口,不影响 SSH 或其他管理端口
生效配置:
sudo systemctl restart fail2ban sudo fail2ban-client status nginx-upstream-scan
看到 Number of jail's bannings 上升,且 iptables -L INPUT -n | grep f2b-nginx-scan 能查到规则,说明已联动成功。
不复杂但容易忽略











