1. 为什么需要屏蔽特定User-Agent
在Web服务器管理中,User-Agent字符串就像每个访客的身份证。当爬虫程序、恶意扫描工具或自动化攻击脚本访问网站时,它们往往携带特定的User-Agent特征。这些异常流量会消耗服务器资源,影响正常用户访问体验,甚至可能被用来探测网站漏洞。
我管理的几个电商站点就曾遭遇过这样的问题:凌晨2-3点突然出现大量来自相同IP段的请求,User-Agent清一色显示"ScannerBot/1.0",导致服务器负载飙升。通过分析Nginx日志发现,这些请求都在试探性地访问/wp-admin等敏感路径。这就是典型的恶意扫描行为。
2. User-Agent拦截原理剖析
Nginx的if指令配合$http_user_agent变量可以实现精准拦截。当客户端发起请求时,其User-Agent信息会被包含在HTTP头中传输。Nginx在location或server块中通过正则表达式匹配这些特征值,对符合规则的请求返回403状态码。
这里有个技术细节需要注意:现代恶意程序常会伪造User-Agent,比如在合法浏览器标识后附加扫描器特征。因此我们的正则表达式要能匹配片段特征,例如".Scanner."这样的模式会更有效。
3. 实战配置步骤详解
3.1 基础拦截配置
在Nginx配置文件的server块中添加以下内容:
nginx复制server {
...
if ($http_user_agent ~* (ScannerBot|恶意爬虫|Havij)) {
return 403;
}
...
}
这里的~*表示不区分大小写的正则匹配。建议将这些规则放在location /块之前,确保全局生效。
3.2 高级模式匹配
对于更复杂的场景,可以使用map指令建立User-Agent黑名单:
nginx复制map $http_user_agent $bad_agent {
default 0;
"~*扫描器" 1;
"~*SQL注入" 1;
"~*BruteForce" 1;
}
server {
if ($bad_agent) {
return 403;
}
}
这种方式的优势是黑名单可以单独维护,且匹配效率更高。
4. 性能优化与注意事项
4.1 正则表达式优化
避免使用过于宽泛的.*匹配,这会导致性能下降。例如:
nginx复制# 不推荐
if ($http_user_agent ~* .*bot.*)
# 推荐
if ($http_user_agent ~* (Googlebot|Bingbot|YandexBot))
4.2 日志记录策略
建议将拦截记录单独输出到日志文件:
nginx复制server {
...
error_log /var/log/nginx/blocked_agents.log;
if ($http_user_agent ~* (恶意特征)) {
access_log /var/log/nginx/blocked_access.log;
return 403;
}
...
}
5. 常见问题解决方案
5.1 误拦截合法爬虫
如果发现搜索引擎爬虫被误拦,可以添加白名单机制:
nginx复制map $http_user_agent $is_allowed {
default $bad_agent;
"~*Googlebot" 0;
"~*Bingbot" 0;
}
5.2 动态更新黑名单
使用include指令实现动态加载:
nginx复制include /etc/nginx/user_agent_blacklist.conf;
然后定期更新这个conf文件即可,无需重启Nginx。
6. 实战案例分享
某金融网站部署后拦截了以下User-Agent:
- "Mozilla/5.0 (compatible; 恶意扫描器/1.0)"
- "Java/1.8.0_221 (探测攻击)"
- "python-requests/2.22.0 (用于撞库)"
配置一周后,服务器CPU使用率从平均70%降至35%,有效拦截了98%的恶意请求。关键配置如下:
nginx复制map $http_user_agent $block_ua {
default 0;
"~*(扫描器|暴力破解|sqlmap)" 1;
"~*(python-requests|Java/1.8)" 1;
"~*Mozilla.*恶意" 1;
}
server {
if ($block_ua) {
access_log /var/log/nginx/blocked.log;
return 444; # 特殊状态码直接关闭连接
}
}
7. 进阶防护建议
结合GeoIP模块可以增强防护效果:
nginx复制geo $block_country {
default 0;
CN 1; # 示例:屏蔽特定国家
}
server {
if ($block_country && $block_ua) {
return 403;
}
}
对于高频攻击IP,建议配合fail2ban工具实现自动封禁。将Nginx日志作为输入源,设置当某IP在1小时内触发超过50次403错误时,自动加入防火墙黑名单。
