最可靠方式是在 nginx server 块顶层用 map 预定义 ua 拦截规则并配合 if 返回 403,map 需置于 http 块中支持大小写不敏感正则匹配,覆盖空 ua 等边缘情况,白名单须后置;server 中 if($blocked_ua) { return 403 "access denied."; },避免嵌套 location;需配合日志记录、限流及路径级强化,并通过 nginx -t 和 curl 验证。

直接在 Nginx 的 server 块顶层配置 UA 拦截最可靠,避免嵌套在 location 里导致失效或引发 502;核心是用 map 预定义匹配逻辑,再通过 if 统一拦截并返回 403。
用 map 在 http 块统一定义可疑 UA 标识
把规则集中写在 http 块里,提升性能和可维护性。注意语法严格(空格、分号不能错):
- 添加如下配置(复制时保留缩进与换行):
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;
}
- 支持大小写不敏感、正则匹配,覆盖空 UA、纯空白、短横线等边缘情况
- 白名单(如允许 Sogou web spider)需显式设为
0,且放在黑名单之后(map 按顺序匹配)
在 server 块中触发拦截并返回明确响应
进入具体站点的 server 块,在 location / 之前插入判断:
- 写法简洁有效:
if ($blocked_ua) {
return 403 "Access denied.";
}
- 不建议把
if放进location内——fastcgi 或 try_files 可能绕过它 - 返回带提示的 403 比空响应更利于日志识别,又不暴露后端细节
增强防御纵深:记录、限流与路径强化
单靠 UA 拦截不够,需配合可观测性和行为控制:
- 在
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),可用location ^~ /admin单独加严规则,不依赖全局 UA 判断
验证与上线必须做的三件事
- 每次改完配置,先运行
nginx -t校验语法是否正确 - 确认无误后执行
nginx -s reload热加载,不中断服务 - 用 curl 模拟测试:
curl -H "User-Agent: sqlmap/1.7" https://yoursite.com/ 应返回 403











