Linux Nginx拦截恶意爬虫配置方法

作者:技术拾光

时间:2026-06-29

浏览:325

Nginx拦截恶意爬虫时,需将if指令放在server块顶层,利用map模块预编译用户代理黑名单,配合limit_req限流,同时设置白名单做兜底,并单独处理空用户代理。要避免在location块内使用if,否则配置失效。正确配置能提升服务器性能,防止误封合法流量。

文章目录

在Nginx中,通过一条if语句拦截恶意爬虫,往往难以奏效。例如,if ($http_user_agent ~* "scrapy")这类配置,大多数情况下并不能真正生效。问题在于if指令在location块中的行为与常规条件判断不同,它更接近“伪指令”,容易被后续的proxy_pass、try_files等指令覆盖或跳过。正确的做法是将if放在server块的顶层,并配合map预编译、limit_req限流、白名单兜底,同时单独处理空User-Agent,才能有效拦截恶意爬虫。

Linux Nginx拦截恶意爬虫配置方法

因此,单纯使用if ($http_user_agent ~* "scrapy")来拦截恶意爬虫,90%的配置要么失效,要么误杀。正确做法是放在server块顶层,同时配上限流和白名单,并持续监控日志。

为什么if在location里基本不生效

Nginx的if指令在location内部并非简单的条件判断,它本质上是一个“伪指令”,很容易被后续的proxy_pass、try_files或fastcgi_pass覆盖或跳过。更麻烦的是,多个if嵌套时,逻辑会变得不可预测,官方文档也明确标注了“a void”。

  • 错误写法:location /api { if ($http_user_agent ~* "curl") { return 403; } } —— 这条规则大概率被忽略,等于白写。
  • 正确位置:紧贴server {下方,在listen和server_name之后、所有location之前。
  • 空UA必须单独处理:if ($http_user_agent = "") { return 403; },不能用正则匹配。
  • 大小写敏感问题:~*才能匹配Python-urllib和python-requests,如果用了~,会漏掉一半。

用map定义$blocked_ua更可靠

将UA黑名单从if搬到http块里的map,是更明智的做法。性能更高、顺序可控、语法更安全。Nginx启动时就编译好映射表,不依赖运行时判断。

  • 在http块中添加(注意分号和空格):
    map $http_user_agent $blocked_ua {
      default 0;
      ~* (sqlmap|nikto|gobuster|nuclei) 1;
      ~* (python-requests|curl|wget|httpie) 1;
      ~* (scanner|crawler|exploit|pentest) 1;
      ~* (^$|^s*$|^-$) 1;
    }
  • 在server块中启用:if ($blocked_ua) { return 403 "Access denied."; }
  • 白名单必须后置:若要放行Bingbot,需在map中写成~* Bingbot 0;,且放在黑名单规则之后。
  • 别匹配泛化词:~* python会误伤CPython或内部监控脚本,应该写具体工具名。

limit_req才是防高频爬虫的核心

封UA只能拦住“懒爬虫”。真正让服务器吃紧的,是那些每秒发几十次请求的自动化脚本。此时,limit_req才是主力。它基于IP地址做漏桶限速,硬性掐断流量。

  • 定义区(http块):limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s; (注意$binary_remote_addr比$remote_addr更节省内存)
  • 启用位置(推荐放在敏感location中):limit_req zone=ip_limit burst=10 nodelay;
  • burst=10表示允许瞬时最多15次请求(基础5 + 缓冲10),nodelay让这10次立刻处理,不排队。
  • 登录接口建议:rate=1r/s burst=0,彻底禁止连试;静态资源可设rate=100r/s,防止页面卡顿。
  • 必须显式声明拒绝码:limit_req_status 429; (Nginx ≥1.23可用reject=429)

robots.txt必须用location = /robots.txt精确匹配

直接返回内容比读磁盘文件快。但写错匹配方式,可能泄露路径或返回错误内容。

  • 错误写法:location /robots.txt { ... } —— 会意外匹配/robots.txt.bak或/robots.txt/xxx
  • 正确写法:location = /robots.txt { default_type text/plain; add_header Content-Type "text/plain; charset=UTF-8"; return 200 "User-agent: *nDisallow: /adminnDisallow: /wp-login.phpn"; }
  • 换行必须用LF(n),Windows的rn会让部分爬虫解析失败。
  • 如果只屏蔽百度、搜狗等个别爬虫,User-Agent规则必须按“具体→泛化”顺序写,User-Agent: *放最后,否则会提前终止匹配。

最后想说:最容易被忽略的其实是白名单兜底。盲目封禁含bot、spider的UA,会直接阻断Googlebot、Applebot、Zabbix、Prometheus这些合法流量——后果比爬虫本身还严重。所以,得先建白名单变量,再拦黑名单,而不是简单粗暴地“非白即黑”。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章