纯靠Nginx配置无法自动封禁恶意IP,需外部脚本分析日志生成黑名单并重载;推荐geo+map实现内存级静态封禁,配合limit_req限流与日志分离提升精准性与可审计性。

纯靠 Nginx 配置无法自动识别并封禁恶意 IP——它不解析日志,也不运行逻辑判断。真正可行的自动化方案,是“外部脚本分析日志 + 生成黑名单文件 + Nginx 平滑重载”,整个过程轻量、稳定、无需额外服务或编译模块。
用 geo + map 实现高性能静态封禁
这是最推荐的基础架构:把黑名单提前加载进内存,避免每次请求都做字符串匹配,性能几乎无损耗。
- 在 http 块中定义 geo 变量,将黑名单 IP 映射为 1,其余为 0:
geo $bad_ip {
default 0;
include /usr/local/nginx/conf/blacklist.conf;
} - 再用 map 转成易读的布尔标记:
map $bad_ip $blocked {
1 "1";
default "";
} - 在具体 location 中拦截(如登录页、管理后台):
if ($blocked) { return 403; } - 白名单优先级更高,可在 geo 块顶部直接写:
192.168.0.0/16 0;
10.0.0.0/8 0;
定时脚本提取高频恶意行为
脚本每 2–5 分钟执行一次,聚焦真实攻击特征,而非泛泛统计总请求数。
- 识别短时间大量访问敏感路径(如
/wp-login.php、/admin/):
awk -v d="$(date -d '2 minutes ago' '+%d/%b/%Y:%H:%M')" '$0 ~ d && $7 ~ /\/(wp-login|admin|phpmyadmin)\.php?/ && $9 == 200 {print $1}' /var/log/nginx/access.log | sort | uniq -c | awk '$1 > 15 {print $2}' | sort -u > /usr/local/nginx/conf/blacklist.conf - 补充识别异常模式:单位时间 404 超 50 次、User-Agent 含
sqlmap或nmap、无 Referer 却高频 POST 等 - 执行前务必校验语法:
nginx -t && nginx -s reload,否则 reload 失败会中断服务
叠加限流降低误伤与攻击冲击
单纯封禁有滞后性,容易被绕过或误封。配合 limit_req 提前压制,更稳妥。
- 对登录接口设速率限制:
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=3r/m; - 在对应 location 中启用:
location = /wp-login.php {
limit_req zone=login_limit burst=5 nodelay;
if ($blocked) { return 403; }
} - 触发限流后,IP 进入冷却期,此时脚本再将其写入黑名单,比直接封更精准
可选增强:分离恶意 IP 日志便于审计
不想让黑名单 IP 的请求污染主日志?可用 map 控制日志输出目标。
- 定义日志开关变量:
map $bad_ip $loggable {
1 0;
default 1;
} - 在 server 或 location 中指定:
access_log /var/log/nginx/access.log main if=$loggable;
access_log /var/log/nginx/blocked.log main if=$bad_ip; - 这样既保留审计线索,又保持主日志干净


















