最稳妥的UA拦截方案是在Nginx server块顶层用map定义$blocked_ua变量并匹配可疑UA,再通过if($blocked_ua)返回403,配合日志记录、限流及针对性location强化规则。

直接在 Nginx 的 server 块顶层 添加 UA 拦截逻辑最稳妥,既避免 location 内部重写导致失效,也防止 if 误用引发 502 错误。核心是用正则匹配可疑标识,返回 403 并留痕便于追踪。
用 map 定义黑名单变量(推荐)
在 http 块中统一声明映射,提升性能与可维护性:
- 添加如下配置(注意空格和分号位置,Nginx 对语法敏感):
default 0;
~* (sqlmap|nikto|gobuster|nuclei|acunetix|whatweb|zmap|masscan) 1;
~* (python-requests|curl|wget|httpie|Go-http-client) 1;
~* (scanner|crawler|exploit|pentest|vuln|hack) 1;
~* (^$|^\s*$|^-$) 1;
}
- 该方式支持大小写不敏感匹配,且能覆盖空 UA、短横线、纯空白等边缘情况;
- 白名单可显式设为 0(如允许
Sogou web spider),但需放在黑名单规则之后,因 map 匹配按顺序生效。
在 server 中拦截并返回 403
进入对应站点的 server 块,在 location / 之前插入判断:
- 写法简洁明确:
return 403 "Access denied.";
}
- 不建议把 if 放进 location 块内——某些 fastcgi_pass 或 try_files 规则可能绕过它;
- 返回带提示信息的 403(如上例)比纯空响应更利于日志识别,又不会暴露过多服务细节。
增强可观测性与防御纵深
单纯拦截不够,还需记录、限流与行为识别:
- 在
log_format中加入 UA 和拦截标记,例如:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $blocked_ua'; - 对高频触发拦截的 IP,加一层限流:
limit_req zone=ua_block burst=5 nodelay;(需提前定义 limit_req_zone) - 若发现某 UA 集中扫目录(如 /admin、/wp-login.php),可结合
location ^~ /admin单独强化规则,不依赖全局 UA 判断。
验证与上线要点
- 每次改完配置,必须执行
nginx -t校验语法,再nginx -s reload热加载; - 测试时用 curl 模拟目标 UA:
curl -H "User-Agent: sqlmap/1.7" https://yoursite.com/ 应返回 403; - Windows 下 phpEnv 用户注意:配置文件路径多为
C:\phpEnv\nginx\conf\vhost\*.conf,勿改错文件; - macOS 或 Linux 用户若用 Homebrew 安装,确保 Nginx 版本 ≥ 1.19(if 指令行为更稳定)。











