⭐ 推荐:社区规则条款 V1.0

Nginx 防爬虫时如何设置搜索引擎白名单?

周末
周末 萌新站长
发布于 2026-10-19 11:58 ·4 浏览 ·0 回复
内容摘要

Nginx 防爬虫应避免用 if 判断 UA,而用 map 按 User-Agent 生成标记并接入 limit_req_zone 的 key,使搜索引擎请求以空 key 跳过限流,同时配合 IP 反向解析防伪造,并建议对白名单分档限速而非

结论:Nginx 防爬虫时的搜索引擎白名单,正确做法是用 map 指令按 User-Agent 匹配蜘蛛标识生成一个标记变量,再把该变量接入 limit_req_zone 的 key——白名单请求的 key 置为空字符串,Nginx 对 key 为空的请求不计入限流;同时必须配合 IP 反向解析校验,因为 UA 可以随意伪造。

为什么不用 if 判断 User-Agent?

结论:在 location 里用 if ($http_user_agent ~* Baiduspider) 放行是错误姿势,if 在 Nginx 中属于“邪恶指令”(if is evil),在 location 上下文里会破坏配置继承顺序,且多个 UA 并列时性能差、难维护。

map 定义在 http 块,只在配置加载时编译一次,运行时是哈希查找,10 个 UA 关键词和 1 个的成本几乎相同。而且 map 产出的变量可以复用到限流、日志、缓存多个环节,比散落的 if 干净得多。

搜索引擎白名单的 Nginx 配置怎么写?

结论:核心是三段——map 匹配 UA、map 生成限流 key、limit_req_zone 引用这个 key。以下配置可直接抄改:

http {
    # 1. UA 白名单,命中置 1
    map $http_user_agent $engine_ua {
        default               0;
        "~*Baiduspider"       1;
        "~*Googlebot"         1;
        "~*bingbot"           1;
        "~*Sogou web spider"  1;
        "~*360Spider"         1;
        "~*YisouSpider"       1;
        "~*Bytespider"        1;
        "~*YandexBot"         1;
        "~*Applebot"          1;
        "~*DuckDuckBot"       1;
    }

    # 2. 生成限流 key:引擎留空,其余按 IP
    map $engine_ua $limit_key {
        1  "";
        0  $binary_remote_addr;
    }

    # 3. 声明限流区
    limit_req_zone $limit_key zone=crawler:10m rate=5r/s;

    server {
        location / {
            limit_req zone=crawler burst=20 nodelay;
            # 便于事后审计:日志里带上标记
            add_header X-Engine-Hit $engine_ua always;
        }
    }
}

要点:$binary_remote_addr 比 $remote_addr 省内存,IPv4 固定 4 字节;10m 约可存 16 万个 IP 状态;rate=5r/s 是普通访客基线,burst=20 nodelay 允许 20 个突发请求立即处理。Nginx 官方文档明确写着 “Requests with an empty key value are not accounted”,所以 key 为空的蜘蛛请求完全不进限流桶。

白名单只放宽、不全放,怎么设计?

结论:不建议给搜索引擎完全免限,推荐“分档限速”——普通用户 5r/s、白名单 20r/s 并单独给大 burst,既保证抓取效率,又能挡住伪装成百度蜘蛛的高频 CC。

做法是建两个 limit_req_zone,用 map 再分流出 $limit_key_normal 和 $limit_key_engine,在 location 里写两条 limit_req;Nginx 允许多条 limit_req 并存,任一超限即返回 503。另一个细节:map 里的正则必须加引号包住含空格的关键词(如 "~*Sogou web spider"),否则 Nginx 启动会报 invalid number of the map parameters。

怎么识别伪装成搜索引擎的爬虫?

结论:UA 白名单只是第一道门槛,真正的校验是“反向解析 + 正向解析”双重 DNS 验证,Nginx 自身做不到,需要用定时脚本生成 IP 清单后 include 进配置。

以百度为例,官方验证方法是:对来访 IP 执行 dig +short -x 220.181.108.75,若返回 baiduspider-220-181-108-75.crawl.baidu.com 这类 *.crawl.baidu.com 域名,再对该域名做 dig +short baiduspider-220-181-108-75.crawl.baidu.com,返回的 IP 必须与来访 IP 一致才算真蜘蛛。Googlebot 同理,反解应落在 *.googlebot.com 或 *.google.com。两个方向都对不上,就是伪造。

落地建议:写一个每小时跑的脚本,从 access.log 提取带 $engine_ua=1 的 IP,做双重解析,验证通过的写进 /etc/nginx/conf.d/engine_ips.conf 里的 geo $trusted_engine { default 0; 220.181.108.75 1; ... },然后 nginx -s reload。真实爬虫 IP 段很稳定,一天最多新增几十条,reload 开销可忽略。不要硬编码 Google 的 IP 段——官方 JSON 每季度会变,写死迟早失效。

常见坑有哪些?

结论:最容易踩的三个坑是大小写、编码和日志。

第一,UA 大小写不统一,必用 ~* 而非 ~,Baiduspider 和 baiduspider 都出现过。第二,部分爬虫会带 URL 编码或全角字符,日志里先抓原始 UA 再补关键词,别凭记忆写。第三,务必在 log_format 里加上 $engine_ua,否则被刷了流量你无法区分是白名单误放还是正常抓取。另外 limit_req 超限返回的是 503,如果站点前面还有 CDN,记得把 503 也纳入缓存穿透保护。

整体思路归结成一句:map 定白名单、空 key 免限流、DNS 反解析保真伪、日志留痕做审计。四步走完,搜索引擎抓取不受影响,伪装爬虫照样被限。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2289.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~