前言

我的站点架在 Cloudflare Pages 上,想着国内访问慢,就套了一层腾讯 EdgeOne 做加速。结果一通操作下来,先后遇到了 Error 1001、525 SSL 握手失败、以及最离谱的「访问自己的域名却跳转到 xxx.pages.dev」。三次翻车其实是同一个根因的三个侧面,记录下来给后来者省点时间。

起因

站点是 Next.js,部署在 Cloudflare Pages,源站域名是 uptime-status-9iv.pages.dev,对外用 status.suis.ren 访问。

Cloudflare 在国内的访问质量不用多说,所以想用 EdgeOne 套一层:访客就近接入 EdgeOne 国内节点,EdgeOne 回源到 Cloudflare Pages。架构看起来很直白:

1
访客 → EdgeOne 边缘节点 → Cloudflare Pages

接入过程按控制台提示走:添加加速域名 status.suis.ren,源站填 uptime-status-9iv.pages.dev,把 DNS 记录 CNAME 到 EdgeOne 分配的 xxx.eo.dnse1.com。一切看起来都很标准。

然后就炸了。

第一次翻车:Error 1001 DNS resolution error

1
2
Error 1001 Ray ID: a3a6c9c7bd18f5dc
DNS resolution error

Cloudflare 的提示页写得很含糊,大意是「我们解析不了你请求的域名」。第一反应是 DNS 没生效、等一会儿就好——等了半天还是这样。

这里是我犯的第一个错误:凭感觉猜,而不是先确认流量到底走到哪了。

先别急着改配置:搞清楚请求在哪一步断的

两个命令就能定位清楚。

第一步,确认 DNS 有没有切到 EdgeOne:

1
2
nslookup -type=CNAME status.suis.ren
# status.suis.ren canonical name = status.suis.ren.eo.dnse1.com

CNAME 已经指向 eo.dnse1.com(EdgeOne 的调度域名),说明 DNS 侧没问题,流量确实进了 EdgeOne。

第二步,看真实响应头:

1
2
3
curl --noproxy '*' -s -D - -o /dev/null https://status.suis.ren/
# HTTP/1.1 525 SSL Handshake Failed with Origin Server
# Server: TencentEdgeOne

注意两点:

  • Server: TencentEdgeOne —— 响应是 EdgeOne 返回的,不是 Cloudflare 直接返回的。所以「DNS 没生效」的猜想当场排除,问题发生在 EdgeOne 回源那一步。
  • --noproxy '*' 很关键。我本机开了 HTTP 代理,不加这个参数拿到的是代理的响应(我第一次就拿到了一个误导性的 127.0.0.1 的假结果)。

于是第一个结论出来了:加速已经生效,是回源失败了。

根因:Cloudflare Pages 是按 hostname 认人的

要理解后面两个坑,得先明白 Cloudflare Pages 的路由机制。

Pages 不是「你把 DNS 指过来我就给你服务」。它维护的是一张 hostname → 项目 的绑定表:

  • xxx.pages.dev 是项目创建时自动生成的,永远有效;
  • 自定义域必须在 Pages 项目的 Custom domains 里显式添加,Cloudflare 才会为它签发证书、创建边缘路由。

当一个请求带着某个 hostname 打到 Cloudflare 边缘,而这张表里查不到它时,Cloudflare 不知道该交给谁,就返回 Error 1001。

所以 1001 的本质不是「DNS 解析失败」,而是「这个 hostname 我没登记过」。

第二次翻车:525 SSL Handshake Failed

顺着这个思路,问题就清楚了:EdgeOne 回源时,默认把 Host(以及 TLS 的 SNI)填成了加速域名本身,也就是 status.suis.ren。

Cloudflare 收到 SNI = status.suis.ren 的 TLS 握手请求,而这个 hostname 在它那儿没有证书(Pages 里没绑定,或者绑定已失效),TLS 层直接就把连接断了。EdgeOne 收不到有效响应,于是报 525。

1001 和 525 是同一个根因的两种表现:TLS 握手前失败 → 525;握手过了但 hostname 查不到路由 → 1001。

修复

EdgeOne 控制台 → 站点 → 域名服务 → 加速域名 → 源站配置:

配置项 值
源站类型 域名(自有源)
源站地址 uptime-status-9iv.pages.dev
回源协议 HTTPS
回源端口 443
回源 HOST 头 使用源站域名(或自定义填 uptime-status-9iv.pages.dev)

最后一行是整个问题的核心。「回源 HOST 头」有三个选项,绝对不能选「使用加速域名」——那就是 525 的来源。改成源站域名后,SNI 会跟随回源 Host,正好命中 Cloudflare 给 *.pages.dev 签的通配证书。

改完保存,再测:

1
2
3
4
curl --noproxy '*' -s -D - -o /dev/null https://status.suis.ren/
# HTTP/1.1 200 OK
# Server: cloudflare
# CF-RAY: a3a6dd0ebaff885c-LAX

200 了,CF-RAY 说明确实回源到了 Cloudflare 的洛杉矶节点。

一个必须提前做的动作:删掉 Pages 里的自定义域

在改回源配置之前,还有一步必须做:进 Pages 项目 → Custom domains,把 status.suis.ren 删掉。

原因有两个:

  1. Pages 会周期性校验自定义域的 DNS 是否指向它。现在 DNS 指向 EdgeOne,校验必然失败,绑定失效后 Cloudflare 就不认这个 hostname 了。
  2. 更要命的是——只要自定义域还挂着,访问 xxx.pages.dev 会被 Cloudflare 301 跳回自定义域。这样 EdgeOne 回源拿到 301,跳回 status.suis.ren,又回到 EdgeOne,形成死循环。

所以「加速域名」和「Pages 自定义域」这两个身份只能选一个,不能两头都占。既然要用 EdgeOne 加速,Pages 侧就只保留 pages.dev。

顺带确认一下项目设置里没有开启 “Disable pages.dev”。

第三次翻车:访问自己的域名,却跳到了 pages.dev

200 之后我以为完事了,结果浏览器一访问 status.suis.ren,地址栏变成了 uptime-status-9iv.pages.dev。

又是 curl 出马:

1
2
3
curl --noproxy '*' -s -D - -o /dev/null http://status.suis.ren/
# HTTP/1.1 301 Moved Permanently
# Location: https://uptime-status-9iv.pages.dev/

注意这个 Location —— 它是按回源 Host 拼出来的绝对 URL。

链路是这样的:我在浏览器地址栏输入 status.suis.ren,浏览器默认走 HTTP → EdgeOne 用「协议跟随」也走 80 端口回源 → Cloudflare 收到 HTTP 请求,返回 301 跳 HTTPS,Location 基于它看到的 Host(uptime-status-9iv.pages.dev)拼成绝对地址 → EdgeOne 原样透传给浏览器 → 浏览器老老实实跳到 pages.dev。

修复

两处一起改:

  1. 回源协议固定为 HTTPS,不要选「协议跟随」。回源直接走 443,Cloudflare 就不会返回 HTTP→HTTPS 的 301。
  2. EdgeOne 开启「强制跳转 HTTPS」(HTTPS 配置里)。这样 HTTP 访客在 EdgeOne 边缘就被 301 到 https://status.suis.ren/,压根不用回源,省一个来回。

还有个坑中坑:浏览器会强缓存 301

301 是永久重定向,浏览器会缓存很久。所以即使服务端改好了,你本地打开可能还是在跳。

验证时务必用无痕窗口,或者清一下该站点的缓存,否则会误判成「改了没用」。我在这上面多花了十分钟。

最终配置清单

一份能跑通的配置:

DNS

1
status.suis.ren  CNAME  status.suis.ren.eo.dnse1.com

EdgeOne 源站配置

项 值
源站地址 uptime-status-9iv.pages.dev
回源协议 HTTPS
回源端口 443
回源 HOST 头 使用源站域名
强制跳转 HTTPS 开启

Cloudflare Pages

  • Custom domains 里删除 status.suis.ren
  • pages.dev 保持启用

几个收尾

1. 别把源站暴露出去

现在响应头里 Server: cloudflare 和 CF-RAY 直接透传给访客,等于告诉所有人源站是谁。在 EdgeOne 规则引擎加一条「修改 HTTP 响应头」,删掉 Server、CF-RAY、Report-To、Nel 即可。

2. 记得刷新缓存

改完配置要点「保存并发布」,再去缓存刷新里提交一次 URL 刷新,否则旧的 525 / 1001 错误页可能还被 EdgeOne 缓存着。

3. 备案

如果 EdgeOne 用的是中国大陆加速区域,域名需要完成 ICP 备案,否则节点会被拦截。

反思:这套架构真的划算吗

踩完坑能用是一回事,值不值得是另一回事。

从 CF-RAY: ...-LAX 能看出来,EdgeOne 的节点回源到的是 Cloudflare 洛杉矶。也就是说:访客到 EdgeOne 这一段确实快了,但 EdgeOne 到 Cloudflare 这一段仍然要走一次跨境,回源延迟该高还是高。只有静态资源被 EdgeOne 缓存命中后,才有明显收益。

所以:

  • 如果站点以静态内容为主、缓存命中率高 —— 这套方案有效;
  • 如果大量动态请求、缓存命中率低 —— 加速效果有限,反而多了一层复杂度和出错面;
  • 如果主要服务国内访客,长期更划算的做法是把构建产物直接搬到 EdgeOne Pages 或 COS + EdgeOne,把 Cloudflare 从链路里彻底拿掉,上面这些坑一个都不会有。

小结:一份排查清单

下次遇到类似问题,按这个顺序来:

  1. nslookup -type=CNAME <域名> —— 确认 DNS 是否已切到 CDN;
  2. curl --noproxy '*' -sD - -o /dev/null https://<域名> —— 看 Server 头判断流量在哪一层;
  3. Server 是 CDN 但 5xx/1001 —— 查回源 HOST 头用的是不是源站域名;
  4. 出现 301 跳到源站域名 —— 查回源协议是不是 HTTPS,以及 CDN 有没有开强制跳转 HTTPS;
  5. 排除服务端问题后本地仍异常 —— 无痕窗口再测一次,301 会被浏览器强缓存。

核心心法只有一句:CDN 回源时的 Host 决定了源站怎么看待这个请求,而大多数诡异问题都出在这里。