最稳妥的做法是用 map 指令在 http 块中统一定义 UA 匹配规则,再在 server 块顶层用 if 判断并返回 403;需注意 map 必须置于 http 顶层、大小写不敏感匹配、默认 0 黑名单 1、白名单显式置 0 且后置,并配合日志增强、IP 限流与路径加固。
最稳妥的做法是用 map 指令在 http 块中统一定义匹配逻辑,再在 server 块顶层用 if 判断并返回 403。这种方式性能好、可维护性强,还能覆盖空 UA、大小写混用等边缘情况。
把以下配置加到 nginx.conf 的 http { ... } 区域内(注意缩进和分号):
map 必须放在 http 块顶层,不能嵌套在 server 或 location 里~* 实现大小写不敏感正则匹配0,黑名单匹配设为 1,白名单(如搜狗爬虫)需显式写成 0 并放在黑名单之后示例配置:
map $http_user_agent $blocked_ua {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;~* Sogou web spider 0;}进入你要保护的站点对应的 server { ... } 块,在所有 location 之前添加:
if ($blocked_ua) { return 403 "Access denied."; }if 放进 location 内——某些 fastcgi_pass 或 try_files 可能绕过它单靠 UA 拦截容易被绕过,建议同步做三件事:
log_format 中加入 $http_user_agent $blocked_ua,便于排查误拦或漏拦limit_req zone=ua_block burst=5 nodelay;(需提前定义 limit_req_zone)/admin 或 /wp-login.php),可用 location ^~ /admin 单独加严规则改完配置后必须执行两步:
nginx -t 检查语法是否正确curl 模拟目标 UA 测试,例如:curl -H "User-Agent: sqlmap/1.7" https://yoursite.com/ 应返回 403Sogou web spider)仍可正常访问