关键在于区分人与机器访问行为,通过nginx日志识别高频head+404、敏感路径集中访问、error.log反复报错三类特征,结合awk筛查或fail2ban自动封禁异常ip。

识别并封禁异常高频访问源,关键是把“人正常访问”和“机器高频试探”区分开——不是看单次请求是否可疑,而是看同一 IP 在短时间内的行为密度、路径规律与响应特征。Nginx 本身不主动封 IP,但能提供精准日志信号;真正实现动态封禁,需配合命令行筛查或 fail2ban 等工具快速联动防火墙。
盯紧三类高频行为特征
高频不等于恶意,但以下组合出现时,误报率极低:
- 短时密集 HEAD + 404:扫描器常用 HEAD 加速探测,真实用户几乎不用。1 分钟内同一 IP 出现 15 条以上 HEAD 请求且全返回 404,基本可判定为目录爆破
-
敏感路径集中访问:如
/wp-login.php、/.env、/api/login、/phpmyadmin/等,在 2 分钟内被同一 IP 访问超 5 次,尤其伴随 200/400/404 混合状态 -
error.log 中反复报错:比如
open() failed (2: No such file or directory)或upstream timed out,10 分钟内同一客户端 IP 触发 3 次以上,多为工具化扫描或慢速攻击
用命令行快速定位异常 IP
无需安装额外工具,直接在终端运行即可实时筛查(假设日志路径为 /var/log/nginx/access.log):
- 查最近 1 分钟内请求超 100 次的 IP:
awk -v d="$(date -d '1 minute ago' '+%d/%b/%Y:%H:%M')" '$4 ~ d {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10 - 筛出扫
.git或.env的 IP(从 error.log):awk '/No such file/ && /(\.git|\.env)/ {print $12}' /var/log/nginx/error.log | sort | uniq -c | sort -nr | head -5(注意:$12 是 client 字段位置,按你实际日志格式调整) - 提取高频访问登录接口的 IP:
awk '$7 ~ /\/wp-login\.php|\/admin\/login|\/api\/auth/ {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -5
用 fail2ban 实现自动封禁
手动筛查只能应急,fail2ban 才是可持续方案。它监听日志、匹配规则、调用 iptables/nftables 封禁,全过程可配置、可验证:
- 确保 Nginx 日志含真实 IP:使用
$binary_remote_addr并配好set_real_ip_from和real_ip_header X-Forwarded-For,否则封的是 CDN 节点 - 自定义 filter(例如
/etc/fail2ban/filter.d/nginx-scan.conf):failregex = ^<host> -.*"(GET|HEAD) /(\.env|\.git/config|backup\.zip) HTTP.*" 404</host> - 配置 jail(
/etc/fail2ban/jail.d/custom.conf):[nginx-scan]<br>enabled = true<br>filter = nginx-scan<br>logpath = /var/log/nginx/access.log<br>maxretry = 5<br>findtime = 60<br>bantime = 3600
- 验证规则是否生效:
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-scan.conf
临时封禁与验证方式
确认某 IP 异常后,可立即干预:
- 用 iptables 封禁:
iptables -I INPUT -s 192.168.1.100 -j DROP(记得保存:iptables-save > /etc/sysconfig/iptables) - 或在 Nginx 配置中加:
deny 192.168.1.100;(需 reload:nginx -s reload) - 验证是否生效:从该 IP 发起请求(如
curl -I http://yoursite.com),应返回超时或 403;同时观察tail -f /var/log/nginx/access.log是否不再记录其请求











