nginx中单纯用if($http_user_agent ~* "scrapy")拦截爬虫90%会失效,因if在location内是伪指令、易被覆盖,必须置于server块顶层;需配合map预定义变量、limit_req限流、白名单兜底及空ua单独处理才能可靠生效。

单纯用 if ($http_user_agent ~* "scrapy") 拦截恶意爬虫,90% 的配置会失效或误杀——它必须放在 server 块顶层,且得配合限流、白名单和日志才能真正起效。
为什么 if 在 location 里基本不生效
Nginx 的 if 指令在 location 内部不是“条件判断”,而是“伪指令”:它可能被后续的 proxy_pass、try_files 或 fastcgi_pass 覆盖或跳过;多个 if 嵌套时逻辑不可预测,官方文档明确标注“avoid”。
- 错误写法:
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: /admin\nDisallow: /wp-login.php\n"; } - 换行必须用 LF(
\n),Windows 的\r\n会让部分爬虫解析失败 - 如果只屏蔽百度、搜狗等个别爬虫,
User-Agent规则必须按“具体→泛化”顺序写,User-Agent: *放最后,否则提前终止匹配
最易被忽略的是白名单兜底:盲目封禁含 bot、spider 的 UA,会直接阻断 Googlebot、Applebot、Zabbix、Prometheus 等合法流量,后果比爬虫还严重。先建白名单变量,再拦黑,不是“非白即黑”。











