nginx屏蔽恶意请求需分层识别、精准拦截、可维护更新,核心是结合user-agent、uri、参数、频次、ip、cookie、referer等特征,在早期终止响应;推荐用map+if高效匹配工具指纹,配合动态限流、cookie/referer校验及外部黑名单热更新。

Nginx 屏蔽特定来源的自动化恶意请求,关键不是“一刀切封IP”,而是分层识别、精准拦截、可维护更新。真正有效的做法是结合请求特征(如 User-Agent、URI、参数)、行为模式(如频次、方法)和来源标识(IP、Cookie、Referer),在请求处理早期就终止响应。
用 map + if 高效拦截已知工具指纹
map 指令在配置加载时预编译正则,性能远高于运行时 if 判断,适合管理大量规则。
# 在 http 块中定义
map $http_user_agent $is_bad_bot {
default 0;
~*(sqlmap|nikto|dirb|wvs|acunetix) 1;
~*(curl|wget)\s+.*\-\-user\-agent 1; # 模拟爬虫的 curl/wget
}
map $request_uri $is_suspicious_path {
default 0;
~*\.php\?.*cmd= 1;
~*/wp-content/plugins/.*\.php 1;
~*/admin/.*login.* 1;
}
然后在 server 或 location 中拦截:
if ($is_bad_bot) { return 444; } # 444 表示直接断连,不发响应
if ($is_suspicious_path) { return 403; }
✅ 优势:规则集中、热加载友好、支持大小写不敏感匹配;避免
if嵌套带来的不可预测行为。
基于 IP 行为动态限流 + 封禁
单纯封 IP 容易误伤或失效(如代理池、CDN),更稳妥的是先限流,再根据日志触发封禁。
-
第一步:定义每 IP 请求速率限制
limit_req_zone $binary_remote_addr zone=attack:10m rate=3r/s;
-
第二步:在敏感路径启用并设置封禁窗口
location /login { limit_req zone=attack burst=5 nodelay; limit_req_status 429; # 后续正常逻辑 }
⚠️ 注意:
burst=5允许短时突发,nodelay避免排队延迟;多次超限后,该 IP 会在fail_timeout=60s(默认)内被拒绝——这是 Nginx 内置的“软封禁”。
按 Cookie 或 Referer 精准阻断共享 IP 场景
当攻击者通过 CDN、代理或 NAT 大量复用同一出口 IP 时,IP 封禁失效,此时可转向应用层标识:
-
拦截固定恶意 Cookie 值(例如攻击脚本硬编码的会话 ID):
if ($cookie_PHPSESSID = "a1b2c3d4e5f67890") { return 403; } if ($cookie_tracking_id ~* "^mal-[0-9a-f]{8}$") { return 444; } -
拦截伪造或缺失的 Referer(针对盗链或 API 滥用):
if ($http_referer = "") { return 403; } if ($http_referer !~* ^(https?://(www\.)?yourdomain\.com|https?://api\.yourdomain\.com)) { return 403; }
对接外部黑名单实现热更新
硬写 deny 1.2.3.4; 不可维护。推荐用 geo + include 加载外部 IP 库:
-
创建
/etc/nginx/ip_blacklist.map:"192.168.10.5" 1; "203.0.113.0/24" 1; "2001:db8::1" 1;
-
在
http块中引入:geo $is_blocked { default 0; include /etc/nginx/ip_blacklist.map; } -
在 location 中使用:
location / { if ($is_blocked) { return 403; } # 正常转发 }
✅ 更新方式:脚本定时拉取 AbuseIPDB 或 Emerging Threats 黑名单 → 生成
.map文件 →nginx -t && nginx -s reload,全程无连接中断。
不复杂但容易忽略。











