在Nginx中实现黑名单自动封禁高频恶意IP,关键在于“日志分析+外部脚本+geo/map预加载+reload”闭环机制;需用geo定义$bad_ip变量并include黑名单文件,map转为$blocked标记,再通过if($blocked){return 403}拦截,配合定时脚本提取恶意IP、nginx-t校验后reload,并建议CIDR合并与日志审计。

在 Nginx 中实现黑名单自动封禁高频恶意 IP,关键不是靠 Nginx 自身“实时读文件”,而是用“日志分析 + 外部脚本 + geo/map 预加载 + reload”这一闭环机制。它轻量、稳定、不依赖额外模块,适合大多数生产环境。
用 geo + map 实现高性能 IP 标记
直接写 deny 语句在大量 IP 下性能会下降,推荐用 geo 定义变量、map 转为拦截标记:
- 在
http块中定义地理变量:geo $bad_ip {<br> default 0;<br> include /usr/local/nginx/conf/blacklist.conf;<br>} - 再用
map把数值转为可用标识:map $bad_ip $blocked {<br> 1 "1";<br> default "";<br>} - 在
server或location中拦截:if ($blocked) { return 403; }
注意:geo 支持 include,外部脚本只需更新 blacklist.conf 再 reload,无需改主配置。
定时分析日志提取恶意 IP
高频恶意行为通常表现为:短时间大量 404、反复请求登录接口、异常 User-Agent 扫描等。可用 shell 脚本快速提取:
- 统计 5 分钟内访问
/wp-login.php超过 20 次的 IP:awk '$9 == 200 && $7 ~ //wp-login.php/ {print $1}' /var/log/nginx/access.log \<br>| sort | uniq -c | awk '$1 > 20 {print $2}' > /usr/local/nginx/conf/blacklist.conf - 也可扩展识别:单位时间内 404 超 50 次、UA 含
sqlmap/nmap、无 Referer 却高频 POST 等 - 建议每 2–5 分钟执行一次 cron 任务,避免延迟过高
安全重载:校验 + 权限 + 审计
自动 reload 不能跳过验证,否则配置错误会导致服务中断:
- 每次更新后必须先运行
nginx -t,仅当返回 success 才执行nginx -s reload - 确保脚本以 nginx 配置文件所属用户(如
www-data或nginx)权限写入blacklist.conf,防止 reload 失败 - 记录操作日志:把每次封禁的 IP、触发规则、时间写入
/var/log/nginx/block-audit.log,便于回溯 - 超量 IP 建议合并为 CIDR 段(如将
192.168.1.100–192.168.1.103合并为192.168.1.100/30),减少 geo 查表开销
进阶可选:OpenResty + Redis 动态查表
若需毫秒级生效、不 reload、多节点共享黑名单,可升级为 OpenResty:
- 用 Lua 脚本在
access_by_lua_block中查询 Redis:redis:get("block:" .. ngx.var.remote_addr) - 命中则
ngx.exit(403),未命中继续转发 - 配合 Java/Python 服务提供 HTTP 接口添加封禁,或由风控系统自动写入 Redis
- 优势是零 reload、支持 TTL 过期、可与限流/人机识别联动,但引入了 Redis 依赖和 Lua 维护成本


















