Nginx防御嗅探流量的核心是行为识别而非IP段封禁,需结合限流(limit_req_zone)、UA/Referer过滤(map+if)、独立日志审计及Redis动态黑名单(Lua脚本),并适配CDN回源与多server配置。

Nginx 拦截公有云和机房 IP 的自动化嗅探流量,核心不是“一刀切封禁所有云厂商IP”,而是识别并阻断具备扫描特征的行为模式——这类流量通常来自云主机、IDC服务器或代理池,具备高并发、路径遍历、User-Agent异常、无 Referer、短时高频等特点。单纯按 IP 段黑名单封禁既不可靠(如阿里云ECS与用户业务共用出口),也易误伤(CDN回源、合规爬虫、运维探测)。
以下是兼顾有效性与可用性的实操配置思路:
一、先识别典型嗅探行为特征,再针对性拦截
嗅探流量常见表现:
- 短时间内密集请求
/wp-admin/、/phpmyadmin/、/.git/config、/robots.txt、/api/user/login等敏感路径 - 请求 URI 含大量编码字符(如
%2e%2e%2f)、路径穿越(..%2f)、SQL注入/ XSS 特征串(union select、<script>) -
User-Agent为空、为python-requests、curl/7.x、Go-http-client、masscan、nmap等非浏览器标识 -
Referer缺失或为无效域名(如http://0.0.0.0、http://127.0.0.1) - 单 IP 在 1 分钟内发起 >30 次 GET/POST,且 80% 请求返回 404
✅ 建议:不直接封整个
118.193.0.0/16(某华东IDC段),而是对命中上述多条件的请求做限流+记录+临时封禁。
二、用 Nginx 原生模块组合实现轻量级防御
▪ 限制高危路径的访问频次(防爆破/目录扫描)
# 在 http 块中定义限流区域(按 IP + 路径维度)
limit_req_zone $binary_remote_addr$uri zone=scan_protect:10m rate=3r/m;
server {
location ~ ^/(wp-admin|phpmyadmin|\.git|\.env|config\.php|api/.*login) {
limit_req zone=scan_protect burst=5 nodelay;
# 返回 429 提示更友好,也可改 return 403;
}
}▪ 拦截可疑 User-Agent 和空 Referer(配合日志审计)
map $http_user_agent $is_suspicious_ua {
default 0;
"~*masscan" 1;
"~*nmap" 1;
"~*gobuster" 1;
"~*dirbuster" 1;
"~*sqlmap" 1;
"~*python-requests" 1;
"~*Go-http-client" 1;
"~*curl/" 1;
}
map $http_referer $no_referer {
"" 1;
default 0;
}
# 在 location 或 server 中使用
if ($is_suspicious_ua = 1) { return 403; }
if ($no_referer = 1) { set $blocked "1"; }
if ($blocked = "1") { return 403; }⚠️ 注意:if 在 location 外慎用;建议将以上逻辑放在 location / 或具体业务路径下,并确保 if 前无 proxy_pass(Nginx 不允许在 proxy 场景中嵌套 if)。
▪ 记录可疑请求到独立日志,便于后续提取黑名单
log_format blocked_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'ua="$is_suspicious_ua" ref="$no_referer"';
access_log /var/log/nginx/blocked.log blocked_log if=$is_suspicious_ua;
access_log /var/log/nginx/blocked.log blocked_log if=$no_referer;三、进阶:对接动态黑名单(推荐用于生产)
当发现某 IP 在 5 分钟内触发 10+ 次 403,可自动加入 Redis 黑名单,由 Lua 脚本实时校验:
- 配置
access_by_lua_file /etc/nginx/lua/block_scanner.lua; - 脚本中检查
$remote_addr是否在 Redis 的ip_blacklist中(TTL 设 1 小时) - 若命中,
ngx.exit(403);否则计数,超阈值则写入 Redis
该方案无需 reload,支持秒级封禁,适合应对突发扫描潮。
四、补充建议:避免踩坑
- ❌ 不要在 HTTPS server 块里漏配规则——HTTP 和 HTTPS 是两个独立 server,需分别加限流/拦截
- ❌ 不要用
deny all; allow xxx;白名单保护公网 API ——除非是纯内网调用,否则会拦掉所有合法客户端(含手机App、小程序) - ✅ 对 CDN 回源流量(如阿里云全站加速、腾讯云 CDN),可在
server块开头用set_real_ip_from+real_ip_header还原真实客户端 IP,再做判断 - ✅ 把
geo模块预加载常用 IDC 段(如112.90.0.0/16、121.40.0.0/16)作为辅助标记,不直接 deny,而是提升其限流等级(如rate=1r/m)
不复杂但容易忽略。


















