Nginx屏蔽User-Agent
网站跑了一段时间后,日志里经常出现大量陌生User-Agent的请求,有的是采集爬虫,有的是漏洞扫描器。
这些请求不仅消耗带宽和CPU,还可能探测后台路径。
本文用Nginx的map和if指令,教你从零配置User-Agent黑名单,拦截常见恶意程序,并验证拦截是否生效。
先搞清楚要拦谁
动手之前先看日志,确认哪些User-Agent值得拦截。
执行下面的命令统计最近访问量最高的User-Agent:
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
输出结果里,如果出现python-requests、curl、Wget、Scrapy、masscan、ZmEu、morfeus这类明显不是正常浏览器的标识,就可以加入黑名单。
注意:curl和Wget也可能是你自己的监控脚本在用,确认后再决定是否拦截。
用map指令配置黑名单
推荐在nginx.conf的http块中使用map指令,比在每个server块里写if更清晰、性能更好。
打开Nginx主配置文件,路径通常是/etc/nginx/nginx.conf,在http {}块内添加:
map $http_user_agent $bad_agent {
default 0;
~*python-requests 1;
~*scrapy 1;
~*masscan 1;
~*zmeu 1;
~*morfeus 1;
~*nikto 1;
~*sqlmap 1;
~*"curl/" 1;
~*"wget/" 1;
}
这段配置的含义是:默认$bad_agent为0,如果User-Agent匹配到任意一条正则,就设为1。~*表示不区分大小写匹配。
然后在需要拦截的server块中引用这个变量:
server {
listen 80;
server_name yourdomain.com;
if ($bad_agent) {
return 403;
}
# 其他正常配置...
}
返回403比返回444更友好,方便你在日志中确认拦截记录。
如果不想让对方看到任何响应,可以用return 444;直接断开连接。
单独拦截空User-Agent
有些扫描器会发送空User-Agent,可以在map中增加一条:
map $http_user_agent $bad_agent {
default 0;
"" 1;
~*python-requests 1;
# ...其他规则
}
但要注意,部分正常客户端(如某些API调用)也可能不带User-Agent,启用前先评估业务影响。
重载配置并验证
修改完成后,先测试配置语法:
nginx -t
看到syntax is ok和test is successful后,平滑重载:
nginx -s reload
验证拦截效果,用被屏蔽的User-Agent发请求:
curl -A "python-requests/2.28" -I http://yourdomain.com
预期返回HTTP/1.1 403 Forbidden。
再用正常浏览器User-Agent测试:
curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" -I http://yourdomain.com
预期返回200 OK。
两个结果都符合,说明配置生效。
容易踩的坑
误拦截正常用户。 某些老旧浏览器或合规爬虫(如百度蜘蛛)的User-Agent可能包含你屏蔽的关键词。
建议先观察日志,确认后再添加规则。
百度蜘蛛的User-Agent包含Baiduspider,不要误伤。
正则写得太宽。 比如只写~*curl会匹配到curl出现在任何位置的User-Agent,可能误伤。
建议写成~*"curl/",加上斜杠和引号更精确。
map指令位置放错。 map必须写在http块内、server块外,写在server里会报错。
忘记重载。 改完配置必须执行nginx -s reload,否则不生效。
怎么确认拦截真的在起作用
重载后观察Nginx错误日志和访问日志:
tail -f /var/log/nginx/access.log | grep 403
如果看到被拦截的请求返回403,说明规则在工作。
也可以统计拦截数量:
awk '$9==403' /var/log/nginx/access.log | wc -l
这个数字会随着时间增长,能直观反映拦截效果。
常见疑问
屏蔽User-Agent能完全阻止爬虫吗? 不能。
对方可以伪造User-Agent绕过。
这只是基础防护,配合频率限制、IP黑名单和验证码效果更好。
会不会影响搜索引擎收录? 只要不误伤百度、Google等正常蜘蛛的User-Agent,就不会影响。
建议先放行主流搜索引擎,只拦截明显恶意的标识。
规则多了会不会拖慢Nginx? map指令在Nginx启动时编译为正则匹配表,运行时开销很小。
几十条规则对性能几乎没有影响。
宝塔面板怎么操作? 在宝塔的网站设置中找到配置文件,
在server块内添加if ($bad_agent) { return 403; },
然后在nginx.conf的http块添加map配置,
保存后重载Nginx即可。
完成以上步骤后,你的Nginx就能拦截大部分常见爬虫和扫描程序。
建议先在小范围测试,确认不影响正常业务后再全量启用。