Nginx恶意IP拦截需构建“日志采集→分析识别→动态封禁→生效验证”闭环,主流方案有三:脚本定时解析日志+重载配置(分钟级)、Fail2ban调用防火墙(30秒级)、OpenResty+Redis实时查库(亚秒级)。

要在 Nginx 中实现针对恶意 IP 的实时日志分析与拦截,关键不是靠“单次配置一劳永逸”,而是构建一个“日志采集 → 分析识别 → 动态封禁 → 生效验证”的闭环流程。Nginx 本身不带实时分析能力,但可借助外部脚本 + 内置模块协同完成,且全程无需中断服务。
用日志统计+自动写入黑名单(最常用、零依赖)
这是中小规模站点最稳妥的方案:定时解析 access.log,筛选高频恶意 IP,生成 deny 指令写入独立配置文件,再重载 Nginx。
- 确保 access.log 格式含 $remote_addr(客户端真实 IP),若经代理需配合 $http_x_forwarded_for 并启用 real_ip_module
- 编写分析脚本(如每 5 分钟执行一次):
提取近 5 分钟内对敏感路径(如/login、/api/auth)请求 ≥ 50 次的 IP;
过滤掉已返回 403 的记录(加grep -v " 403 ")避免重复封禁;
输出格式为deny 192.168.1.100;到/etc/nginx/conf.d/auto-deny.conf - 在
nginx.conf的 http 块中加入:include /etc/nginx/conf.d/auto-deny.conf; - 脚本末尾执行
nginx -s reload—— 轻量重载,毫秒级生效,不影响已有连接
用 Fail2ban 实现日志驱动的自动防火墙封禁
适合需要更强隔离(网络层拦截)或无法频繁重载 Nginx 的环境。Fail2ban 不改 Nginx 配置,而是调用系统防火墙直接丢包。
- 安装 Fail2ban 后,定义 filter 规则(例如匹配连续出现 10 次 401/403 或特定 UA 的 IP)
- 配置 jail,指定 action:
对 CentOS/RHEL 用iptables或firewalld;
对 Ubuntu/Debian 推荐ufw - 封禁动作立即生效,且可设自动解封时间(如 1 小时后释放),避免误伤
- 注意:需确保 Nginx 日志时间戳准确(
log_format中使用$time_local或$msec),否则 Fail2ban 可能漏判
用 OpenResty + Redis 实现毫秒级动态决策
适用于高并发、多节点集群场景。所有 Nginx 实例共享同一个 Redis 黑名单,请求到达时实时查库,无需 reload。
- 部署 OpenResty(含 ngx_lua 模块),在
location或access_by_lua_block中写 Lua 逻辑 - 示例逻辑:
local ip = ngx.var.remote_addrlocal is_blocked = redis:exists("blacklist:" .. ip)if is_blocked == 1 then ngx.exit(403) end - 封禁操作由外部程序(Python/Shell)写入 Redis,例如:
redis-cli SETEX "blacklist:203.0.113.5" 3600 1(封 1 小时) - 优势是真正实时、无 reload 开销;缺点是需维护额外组件,调试门槛略高
三种方式本质是不同粒度的“实时”:脚本方案延迟在分钟级,Fail2ban 通常 30 秒内响应,Lua+Redis 可做到亚秒级。选哪一种,取决于你的流量规模、运维能力与可用基础设施。


















