侧边栏壁纸
  • 累计撰写 181 篇文章
  • 累计收到 2 条评论

配置防盗链却把搜索引擎蜘蛛误杀了?我排查 Nginx valid_referers 与图片收录 403 的几个坑

2026-10-9 / 0 评论 / 15 阅读
AI 摘要由 AI 生成

因配置防盗链误杀搜索引擎蜘蛛,文章分析了Nginx valid_referers配置错误导致图片收录403 Forbidden的原因。首先,搜索引擎蜘蛛抓取图片时,空Referer未被考虑,其次,图片搜索展示页Referer跨域降级导致问题,最后,User-Agent伪造和蜘蛛白名单优先级导致误判。文章建议显式允许主流搜索引擎域名,解决相关问题。

前几天看百度资源平台和 Google Search Console 的抓取异常报告,猛地发现图片类资源的抓取失败率飙升,后台全是一溜的 403 Forbidden。看索引量曲线,图片收录直接从原本的几千张腰斩。

当时第一反应是不是服务器被限流了,但翻了 access.log 发现普通的 HTML 页面抓取很正常,200 状态码跑得很稳,偏偏只要后缀是 .jpg、.png、.webp 的静态图片,搜索引擎的抓取请求一律被 Nginx 丢了 403。

顺着 Nginx 提交记录往前查,两天前刚把一套防盗链配置推上了生产环境,起因是有几个采集站天天用爬虫把图片外链贴到他们站上,白白吃掉服务器几十个 G 的 CDN 流量。

当时在 nginx.conf 里顺手写了这段常见配置:

location ~* \.(jpg|jpeg|png|gif|webp)$ {
    valid_referers blocked server_names *.llbbs.cn;
    if ($invalid_referer) {
        return 403;
    }
}

配置语法挑不出毛病,测试外链直接打不开,盗链确实被挡住了,但搜索引擎蜘蛛的抓取也一并被掐死了。

根因一:搜索引擎蜘蛛抓取图片时,Referer 到底带不带?

很多人以为蜘蛛爬网页时会带上上一级页面的 URL 作为 Referer。

实际上,各大搜索引擎的图片爬虫(比如 Baiduspider-image、Googlebot-Image)在抓取原始图片文件时,行为逻辑和普通用户在浏览器里顺着网页点击完全不同。

搜索引擎建立的是图片索引库。当蜘蛛的调度队列拿到了图片的绝对 URL,它发起的是独立的单点资源请求,而不是像无头浏览器那样先加载完整 HTML 再解析图片。这种抓取请求在很多情况下根本不带 Referer 请求头(也就是所谓的空 Referer)。

回到刚才那条配置:

valid_referers blocked server_names *.llbbs.cn;

这里虽然加了 blocked,但没有加 none。

在 Nginx 的定义里:

  • none:匹配请求头中完全缺少 Referer 的情况(比如浏览器直接在地址栏打开图片,或者爬虫独立抓取)。
  • blocked:匹配请求头中有 Referer,但被防火墙或代理清空了(比如只传了空字符串或不合规字段)。

漏掉了 none,导致所有直接向图片 URL 发起的空 Referer 抓取请求全部被判定为 $invalid_referer = 1,搜索引擎蜘蛛抓一张死一张。

用 curl 模拟一下搜索引擎的行为就能清楚复现:

# 模拟没有 Referer 请求头的蜘蛛独立抓取
curl -I -A "Mozilla/5.0 (compatible; Baiduspider-image/2.0; +http://www.baidu.com/search/spider.html)" https://www.llbbs.cn/uploads/test.jpg

返回直截了当的 HTTP/1.1 403 Forbidden。

根因二:图片搜索展示页的 Referer 跨域降级

空 Referer 只是第一道坎。

当图片被收录进百度图片或者谷歌图片搜索结果页时,用户在搜索结果里点开预览,图片是从你的源站直接拉取展示的。

这时候浏览器会带上 Referer,但是 Referer 的域名是 https://www.baidu.com、https://image.baidu.com 或者 https://www.google.com。

更棘手的是现代浏览器的 Referrer-Policy 默认策略(通常是 strict-origin-when-cross-origin)。当搜索结果页发起跨域资源加载,有些环境送过来的 Referer 甚至只带来源协议和顶级域名,或者由于 HTTPS 到 HTTP 的跳转直接被浏览器剥离了。

如果你在 valid_referers 里面只写了自己站点的域名,那即便图片勉强进了索引,搜出来的缩略图在搜索结果页里也会全部变成破图,进而被搜索引擎判定为死链迅速剔除。

所以在配置合法域名白名单时,必须显式放行主流搜索引擎的域名:

valid_referers none blocked server_names *.llbbs.cn *.baidu.com *.google.com *.bing.com;

根因三:User-Agent 伪造与蜘蛛白名单的优先级

有人会想,既然搜索引擎蜘蛛那么特殊,能不能干脆写个针对 User-Agent 的例外规则?比如匹配到 Baiduspider 就直接放行?

早期我也见过有人这么写:

# 隐患写法:容易被采集站轻易穿透
if ($http_user_agent ~* (baiduspider|googlebot)) {
    # 直接跳过防盗链
}

这种写法很容易留下大漏洞。采集站只要在爬虫脚本里把 User-Agent 伪造成 Baiduspider,防盗链立刻形同虚设。

更稳妥的做法是分层处理:

  1. 先利用 Nginx 的 valid_referers 放行合法域名和空 Referer;
  2. 对普通外链严格拦截,对搜索引擎保持开放;
  3. 如果是高风险资产,在边缘网关层结合 IP 段或双向反查做二次鉴权。

一套兼顾防盗链与 SEO 友好的 Nginx 配置

把上面的坑踩了一圈之后,目前在用的配置改成了这套方案:

# 在 server 块的静态资源 location 中
location ~* \.(jpg|jpeg|png|gif|webp|svg)$ {
    # 1. 允许空 Referer、伪装 Referer、自身所有子域名,以及主流搜索引擎域名
    valid_referers none blocked server_names
        *.llbbs.cn
        llbbs.cn
        *.baidu.com
        *.google.com
        *.googleusercontent.com
        *.bing.com
        *.so.com
        *.sogou.com;

    # 2. 对非法 Referer 进行处理,但对已知正规蜘蛛 UA 保持兜底放行
    set $block_hotlink 0;

    if ($invalid_referer) {
        set $block_hotlink 1;
    }

    # 如果非法 referer 但携带了常见搜索引擎爬虫标识,降级放行避免误杀
    if ($http_user_agent ~* (Baiduspider|Googlebot|bingbot|Bytespider|360Spider|Sogou\ web\ spider)) {
        set $block_hotlink 0;
    }

    if ($block_hotlink = 1) {
        return 403;
    }

    # 静态资源缓存配置
    expires 30d;
    add_header Cache-Control "public, no-transform";
    access_log off;
}

这段配置的核心在于两处细节:

第一,valid_referers 必须带上 none。不能为了封杀外链把没有 Referer 的单请求一律截断。

第二,搜索引擎白名单涵盖了 *.googleusercontent.com(谷歌图片缓存拉取常用域名)和国内搜狗、360 等常见源。

CDN 边缘节点的防盗链与源站冲突

如果你的静态资源前面挂了 CDN,必须注意 CDN 与源站的协同。

有一次我们在源站配好了放行规则,测试发现依然偶发 403。排查后发现是 CDN 边缘节点也开启了防盗链功能,而 CDN 控制台里的规则没有勾选“允许空 Referer”。

CDN 节点挡在源站前面,直接在边缘服务器就把搜索引擎蜘蛛的请求用 403 掐断了,请求根本没有到达源站 Nginx。

排查时别只盯着本机配置:

  • 用 curl -I -H "Referer:" https://cdn.llbbs.cn/image.jpg 模拟空 Referer 直接测 CDN 域名;
  • 检查 CDN 控制台的防盗链规则中,“允许空 Referer”和“放行爬虫”选项是否同时开启;
  • 源站和 CDN 只保留一层主防盗链逻辑,避免两边规则互斥导致调试困难。

改完这套配置之后,观察了两周的站长后台日志,抓取错误率降到了个位数,百度和谷歌的图片收录曲线也逐步回升。防盗链防的是恶意采集,把搜索引擎爬虫放进来才能守住搜索流量。

评论一下?

OωO
取消