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

网站上了 CDN 反而收录腰斩、爬虫频报超时?排查源站误封节点、动态页面被缓与真实 IP 穿透我踩过的几个坑

2026-10-5 / 0 评论 / 3 阅读
AI 摘要由 AI 生成

文章探讨了网站接入CDN后出现收录减少、爬虫抓取超时的问题。主要分析了源站误封节点、动态页面缓存和真实IP穿透问题,并提供了解决方案,如将CDN回源IP加入白名单,以及配置Nginx的real_ip模块,确保爬虫能够正确抓取数据。

前阵子把一个内容站接入了 CDN。原本的打算很直接:静态资源交给边缘节点分发,回源压力减下去,全国各地的访问速度提上来。接入第一周,看监控仪表盘一切正常,静态文件命中率跑到了 92% 以上,各省 ping 延迟从过去的 80ms 降到了 20ms 以内。

结果到了第二周周一拉搜索引擎数据,问题来了。百度搜索资源平台的抓取频次曲线直接掉了一个陡峭的悬崖,从每天一万多次抓取骤降到几百次。点进“抓取诊断”看报错,列表里密密麻麻全是“抓取超时”和“连接被拒绝”。更糟的是,新发布的十几篇文章完全没有收录,已收录的核心关键词排名也出现滑坡。

明明网页秒开,为什么搜索引擎爬虫抓不到?这几天我把 CDN、源站 Nginx、系统防火墙和 DNS 解析从头到尾扒了一遍,理出来几个隐蔽性极高的问题。把这些具体故障点和对应的配置方案整理出来,给遇到类似情况的朋友参考。

坑一:源站防火墙与 Fail2ban 误把 CDN 回源节点当成肉鸡封禁

这是导致爬虫大面积超时的最主要元凶。

站点刚上 CDN 时,由于大部分静态资源被边缘缓存,普通访客只访问缓存节点。但搜索引擎爬虫的行为模式不同:蜘蛛会顺着内部链接密集抓取深度长尾页面,这些冷门页面大概率不在 CDN 边缘节点的缓存中,每一次抓取都会触发 CDN 节点向源站发起回源请求。

CDN 的回源架构是汇聚型的。全国几十个边缘节点采集到的未命中请求,往往会汇聚到几台固定的二级回源节点,再由这几个固定 IP 向你的源站发起 HTTP 请求。

如果源站装了 Fail2ban、iptables 防御规则或者应用层的频率限制,问题就炸了。

# 截取源站 /var/log/fail2ban.log
2026-09-18 14:22:01,842 fail2ban.filter [18421]: INFO [nginx-req-limit] Found 119.29.29.35 - 2026-09-18 14:22:01
2026-09-18 14:22:03,115 fail2ban.actions [18421]: NOTICE [nginx-req-limit] Ban 119.29.29.35

源站看到的请求来源全是这几个回源节点的 IP。在 Fail2ban 眼里,某个 IP 在 10 秒内连续请求了上百次不同的页面路径,立刻触发高频刷接口规则,直接调用 iptables 把这个回源 IP DROP 掉。

这导致的结果极其诡异:你自己在本地浏览器打开网页非常快,因为你的请求走的是没被封的节点或者命中了缓存;但爬虫分配到的回源节点刚好被源站屏蔽,爬虫抓取直接挂起等待 30 秒超时。

排查与解决办法

第一步是在源站检查 iptables 封禁记录:

iptables -L -n --line-numbers | grep DROP

如果看到列表中有腾讯云、阿里云或 Cloudflare 的回源 IP 段,基本就能确诊。

解决办法有两个层面。首先,把 CDN 厂商官方公布的全量回源 IP 段加入 Fail2ban 的白名单。打开 /etc/fail2ban/jail.local:

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 119.29.29.0/24

其次,也是更根本的做法:源站应用层与 Nginx 的限流不能基于连接层 IP($remote_addr),必须基于穿透后的真实客户端 IP。

在 Nginx 主配置文件 nginx.conf 的 http 块中配置 real_ip 模块:

# 填写 CDN 服务商的回源 IP 段,告诉 Nginx 这些 IP 是合法的代理反代
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 119.29.29.0/24;

# 指定从哪个 Header 头提取原始访客 IP
real_ip_header X-Forwarded-For;

# 开启递归解析,排除受信任的代理 IP,获取真实的终端客户 IP
real_ip_recursive on;

配好之后重载 Nginx:

nginx -t && nginx -s reload

此时 Nginx 的 $remote_addr 就会被还原为终端访客或搜索引擎蜘蛛的真实 IP,后续限流配置 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; 针对的就是单独的访客,而不是误伤整个 CDN 回源网关。

坑二:CDN 边缘错误缓存了动态页面与 Set-Cookie 头

很多站长为了追求极致的加载速度,在 CDN 控制台偷懒配置了“全站缓存”或者 /*.html 强行缓存 30 天。这一步如果没有处理好响应头,会给 SEO 带来致命打击。

搜索引擎爬虫抓取页面时,如果拿到的是带有登录态、私有用户数据、或者带错随机 token 的缓存静态版本,轻则收录混乱,重则判定页面内容低质被降权。

更隐蔽的一个问题是:如果某个爬虫抓取时服务器返回了临时 500 报错或者 404 页面,而 CDN 恰好配置了“错误码缓存”,那么这个 404 错误就会被 CDN 边缘节点缓存几天。后续所有访问该 URL 的爬虫都会直接拿到 404,搜索引擎很快就会从索引库剔除这个 URL。

排查与解决办法

通过 curl 模拟爬虫抓取,观察响应头中的 Cache-Control 和 CDN 命中状态:

curl -I -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" https://www.yourdomain.com/article/218.html

重点关注以下几项 Header:

HTTP/2 200
server: nginx
content-type: text/html; charset=UTF-8
cache-control: private, no-cache, no-store, must-revalidate
set-cookie: PHPSESSID=...; path=/
x-cache-lookup: Hit From MemCache

如果内容是动态生成(例如根据用户状态展示不同内容),绝不能让 CDN 缓存整个 HTML。在源站 Nginx 对应的 PHP 或反代 location 中明确声明私有属性:

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    # 动态页面明确告知代理和浏览器不可共享缓存
    add_header Cache-Control "private, no-cache, no-store, must-revalidate";
    add_header Pragma "no-cache";
}

针对纯静态资源,才配置较长的公共缓存周期:

location ~* \.(jpg|jpeg|png|gif|webp|avif|css|js|ico|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, no-transform, max-age=2592000";
    access_log off;
}

同时在 CDN 控制台的缓存规则里检查:

  1. 错误页面缓存时间:404 和 500 状态码必须设置为 0 秒,禁止边缘节点沉淀故障响应。
  2. 忽略 URL 参数开关:文章列表往往包含分页参数 ?page=2,如果开启了“忽略 URL 参数缓存”,爬虫访问第二页、第三页看到的都会是第一页的缓存数据,所有翻页文章全都不会被抓取。

坑三:CDN WAF 人机验证误伤蜘蛛,返回 403 或 JS 质询

如今几乎所有 CDN 都集成了基础 WAF 和 Bot 防护功能。有些平台默认开启了“智能防爬”或者“全站 JS 质询挑战”。

普通人类用户用 Chrome 或 Edge 访问,浏览器毫秒级执行一段挑战 JS 后自动跳转,用户几乎无感知。但搜索引擎蜘蛛完全是另一回事。无论是百度蜘蛛还是搜狗蜘蛛,底层的爬虫程序大多数不运行复杂的 JavaScript 质询逻辑。

当爬虫带着 Baiduspider 的 User-Agent 过来时,CDN 的 WAF 如果判定该 IP 行为可疑或者直接下发验证码页面,返回 HTTP 403 或 200 加一段 JS,爬虫解析不到正文,直接打上“无法抓取”标记。

验证是不是 WAF 拦截了爬虫

在终端执行以下命令伪造百度爬虫请求:

curl -i -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" https://www.yourdomain.com/

查看返回状态码和 HTML 正文:
如果返回的是 403 Forbidden,或者页面正文里充斥着 Checking your browser before accessing...、waf-verify-token 之类的内容,说明 WAF 把蜘蛛当恶意脚本干掉了。

正确的配置策略

在 CDN 控制台的 WAF / Bot 规则中:

  1. 开启“已知搜索引擎白名单”放行。主流服务商(如阿里云、腾讯云、Cloudflare、华为云)都有官方维护的合规搜索引擎 IP 库。
  2. 切勿仅靠 User-Agent 放行。如果单纯写规则 if ($http_user_agent ~* "Baiduspider") allow;,恶意采集者只要改一下 UA 就能绕过你的全部防护。必须结合反向 DNS 解析(rdns)或者厂商内置的“合法蜘蛛校验机制”,确认请求来自百度或谷歌的官方机房网段。

在本地日志分析中,可以通过 host 命令验证爬虫 IP 的真实性:

host 220.181.108.118
# 返回类似 220.181.108.118.in-addr.arpa domain name pointer baiduspider-220-181-108-118.crawl.baidu.com.

只有 PTR 反查域名后缀为 .baidu.com 或 .googlebot.com 的,才是真蜘蛛。

坑四:DNS 线路分配不当,把爬虫甩给高延迟冷门节点

很多站长为了兼顾海内外访问,在域名解析平台(如 DNSPod、阿里云云解析)配了精细的分线路解析:

  • 默认线路:解析到 CDN CNAME
  • 境外线路:解析到海外节点
  • 联通 / 电信 / 移动:各走对应机房

这里容易忽略的是“搜索引擎线路”。

国内主流解析服务商通常提供单独的“百度”“谷歌”“必应”线路选择。如果你没有单独为搜索引擎线路配记录,默认它会继承全局默认线路。如果默认线路被指向了配置较低的高防 IP 或者需要多次跨网路由的境外 CDN,搜索引擎爬虫的连接建立时间(TLS 握手 + 首次字节到达)就会飙升到 800ms 以上。

百度官方明确建议首字节响应时间(TTFB)控制在 200ms 以内。一旦爬虫在 DNS 寻址上花掉大量时间,它给站点的单日抓取配额就会直接腰斩。

解决配置

登录 DNS 管理后台:

  1. 检查是否存在“搜索引擎”独立线路。如果源站具备足够的带宽和基本防御能力,且源站是双线或三线 BGP 机房,建议把“搜索引擎”线路直接指向源站 IP,绕过 CDN 节点的多层转发。
  2. 如果源站防御较弱必须全走 CDN,确保搜索引擎线路分配到国内响应最快的边缘加速节点,而不是被负载均衡甩到海外节点。
  3. 调低 DNS 记录的 TTL。在排查阶段把 TTL 改成 60 秒或 300 秒,方便调整线路后快速生效,避免各地 LocalDNS 长期缓存错误路由。

排查之后的验证清单

改完上面的配置后,别干等收录恢复。通过以下几个步骤验证爬虫抓取是否通畅:

第一步,在百度搜索资源平台的“抓取诊断”工具里提交 5 到 10 个不同层级的页面 URL(首页、分类页、最新文章页、老文章页),观察返回状态。必须全部显示为“抓取成功”,HTTP 状态码严格为 200,抓取耗时稳定在 100ms 左右。

第二步,在源站实时监控 Nginx 真实爬虫日志:

tail -f /var/log/nginx/access.log | grep -E "Baiduspider|Googlebot"

检查日志输出格式中的 IP 是否已经还原为真爬虫 IP,响应状态码是否全为 200,传输字节数是否与实际页面大小匹配。

第三步,在 CDN 控制台查看回源带宽与回源错误率统计。回源 5xx 错误率应该趋近于 0。

把这四个暗坑逐一排查闭合之后,一般在一到两周内,搜索引擎对站点的抓取频次就会逐步回升,新页面的抓取延时也会恢复到正常水准。

评论一下?

OωO
取消