nginx集群全局封禁恶意请求需依赖共享状态机制,主流方案是redis+lua(openresty),辅以fail2ban配置分发或geoip/请求特征前置过滤,并注意if位置、封禁粒度与白名单等避坑点。

在 Nginx 集群环境下实现恶意请求的全局封禁,关键在于让所有节点实时、一致地识别并拒绝黑名单中的请求,而不是各自维护独立规则。静态配置(如直接写 deny)无法同步,也不支持自动更新,因此必须引入共享状态机制。
用 Redis + Lua 实现分布式实时封禁
这是目前最主流、高性能且可扩展的方案,依赖 OpenResty(Nginx + Lua),所有节点共用一个 Redis 黑名单库,每次请求时动态查表拦截。
- 安装 OpenResty 并启用
ngx_http_lua_module - 在
http块中初始化 Redis 连接池:
lua_shared_dict ip_blacklist 10m;
init_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("10.0.1.100", 6379)
if not ok then ngx.log(ngx.ERR, "Redis connect error: ", err) end
ngx.ctx.redis = red
} - 在
server或location中插入拦截逻辑:
access_by_lua_block {
local ip = ngx.var.remote_addr
local red = ngx.ctx.redis
local exists, err = red:exists("blacklist:" .. ip)
if exists == 1 then ngx.exit(403) end
} - 通过脚本或管理接口向 Redis 写入封禁项(带过期时间):
redis-cli SETEX "blacklist:192.168.2.55" 3600 "blocked"(封禁 1 小时)
结合 Fail2ban + 配置分发实现准实时封禁
适合暂未上 OpenResty 的集群,利用日志分析触发统一配置更新,再推送到所有节点。
- 所有 Nginx 节点将访问日志(如含 404/403/高频 POST)统一写入中央日志服务器(如 ELK 或 rsyslog)
- Fail2ban 在中心节点监听日志流,识别攻击 IP 后生成封禁列表(如
/etc/nginx/conf.d/blacklist.conf) - 通过 Ansible / SaltStack / rsync 等工具将黑名单配置原子化推送到全部 Nginx 节点,并执行
nginx -t && nginx -s reload - 为避免 reload 风险,建议将封禁指令集中放在单独文件中,主配置用
include引入:
http {
include /etc/nginx/conf.d/blacklist.conf; # 动态覆盖部分
# 其他配置…
}
基于 GeoIP 或请求特征的前置过滤
对已知高危来源(如特定国家、扫描器 UA、SQL 注入参数)做无状态拦截,不依赖后端存储,天然适用于集群各节点独立生效。
- 使用
map提前归类风险等级,避免在每个 location 里重复写if:
map $http_user_agent $is_malicious_ua {
default 0;
~*sqlmap|nikto|dirbuster|Scrapy 1;
}
map $args $has_inject {
default 0;
~*(union\s+select|sleep\() 1;
} - 在
server块顶层统一拦截:
if ($is_malicious_ua = 1) { return 403; }
if ($has_inject = 1) { return 403; } - 配合
limit_req控制异常行为频率(如每秒超 5 次即限流):
limit_req_zone $binary_remote_addr zone=attack:10m rate=5r/s;
limit_req zone=attack burst=10 nodelay;
注意事项与避坑点
集群环境下的封禁容易因架构差异导致失效,需特别注意:
-
不要在 location 内写 if + return:Nginx 中
if在 location 块内行为不可靠,应始终放在server块顶层 -
避免滥用 rewrite 拦截:rewrite 只重写 URI,不能终止请求;真正拦截请用
return 403、deny或 Lua exit - 封禁粒度要合理:单纯按 IP 封禁可能误伤 CDN 或 NAT 用户,建议叠加 User-Agent、Referer、请求路径等多维判断
- 预留白名单机制:在 Lua 或 map 中显式放行运维 IP、搜索引擎爬虫(如 Googlebot)、健康检查地址,防止自锁











