使用 Cloudflare SaaS + 优选 IP 为 Pages 网站加速

实战笔记:使用 Cloudflare SaaS + 优选 IP 为 Pages 网站加速

场景描述:我部署了一个 Cloudflare Pages 静态网站,希望通过 Cloudflare for SaaS 功能,让自定义域名(如 www.domain2.org)能够通过 优选域名/IP(如 cdn.domain1.xyz)接入,从而实现国内访问加速。

在这个过程中,我遇到了回源 Cloudflare Pages 时的 522 超时403 禁止访问 错误,本文记录了排查思路及终极解决方案。


一、 核心架构与组件解析

为了实现“优选 IP 加速 + 静态网站托管”,我们运用了 Cloudflare 的三个核心组件,它们各司其职:

1. Cloudflare for SaaS (Custom Hostnames)

  • 角色逻辑路由器
  • 作用:它将“物理接入”和“逻辑归属”解耦。
    • 用户可以通过任意优选 IP(物理接入)连入 Cloudflare。
    • SaaS 功能根据请求的 Host 头,识别出流量属于我的平台,并将其导向我设定的 回退源(Fallback Origin)
    • 核心价值:它自动处理了 SSL 证书的分发,并允许通过 CNAME 接入优选线路。

2. Cloudflare Pages

  • 角色:源站 (Origin)。
  • 作用:存储和托管静态网页内容。
  • 特性:Pages 有严格的“白名单机制”。如果请求的 Host 头(如 www.domain2.org)没有在 Pages 后台绑定,它会直接拒绝连接(导致 522 或 404)。

3. Cloudflare Workers

  • 角色中间件 (Middleware) / 翻译官
  • 作用:解决 SaaS 回源与 Pages 之间的协议冲突
    • SaaS 回源时保留了用户的 Host 头(www.domain2.org)。
    • Pages 只能识别自己的原始域名(project.pages.dev)。
    • Worker 在中间拦截流量,修改 Host 头,骗过 Pages,使其正常响应。

二、 流量流向图解

最终成功的流量路径如下:

  1. 用户请求https://www.domain2.org
  2. DNS 解析:CNAME -> cdn.domain1.xyz (优选域名) -> Cloudflare 优选 IP
  3. SaaS 路由:CF 边缘节点识别 Host,转发给回退源 www.domain1.xyz
  4. Worker 拦截:检测到访问 www.domain1.xyz,触发 Worker 脚本。
  5. 修改头部:Worker 将 Host 头从 www.domain2.org 重写为 project.pages.dev
  6. 最终回源:请求到达 Pages,Pages 校验 Host 头通过,返回内容。

三、 踩坑与排查过程

在配置过程中,遇到的两个“拦路虎”:

⚠️ 问题一:Error 522 Connection Timed Out

  • 操作:在 SaaS 回退源中,直接配置 DNS CNAME 指向 Pages 域名,或使用 Worker 的“自定义域 (Custom Domain)”功能。
  • 原因
    1. 直接 CNAME:Pages 收到 www.domain2.org 的 Host 头,但 Pages 后台未绑定该域名,直接丢弃连接。
    2. Worker 自定义域:SaaS 的回退源机制需要一个实体的 DNS 记录(A/AAAA/CNAME)作为锚点。Worker 的“自定义域”生成的是一种特殊的虚拟记录,SaaS 引擎无法将其作为回退源目标,导致内部路由死循环或超时。

⚠️ 问题二:Error 403 Forbidden

  • 操作:使用 Worker 成功拦截,代码中只修改了 url.hostname,未修改 Host 头部。
  • 原因域名欺诈 (Domain Fronting) 保护
    • 请求的 SNI(TLS 握手域名)变成了 project.pages.dev
    • 但 HTTP 请求头里的 Host 依然是 www.domain2.org
    • Cloudflare 发现 SNI 和 Host 不一致,判定为非法请求,拦截并返回 403。

四、 终极解决方案 (配置指南)

步骤 1:DNS 配置 (骗过 SaaS 引擎)

在 SaaS 平台域名(domain1.xyz)下添加回退源记录。我们需要一个“实体”记录来让 SaaS 引擎能够“落地”。

  • 名称: www (作为回退源的子域名)
  • 类型: A
  • 内容: 192.0.2.1 (或者 1.1.1.1,只要是合法的 IP 即可)
  • 代理状态: 必须开启小黄云 (Proxied)

步骤 2:部署 Worker (核心代码)

创建一个 Worker,将以下代码部署上去。这段代码完美解决了 403 问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);

// 你的 Cloudflare Pages 原始地址
const TARGET_HOST = 'project.pages.dev';

// 1. 修改 URL 的 hostname (确保请求发往正确的 IP 和 SNI)
url.hostname = TARGET_HOST;

// 2. 创建新请求
const newRequest = new Request(url, request);

// 3. 【关键修复】显式重写 Host 头
// 必须确保 HTTP Host 头与 URL 主机名一致,否则会被 Cloudflare 判定为域名欺诈 (403)
newRequest.headers.set('Host', TARGET_HOST);

// 4. 发起请求
return fetch(newRequest);
},
};

步骤 3:绑定 Worker 路由 (Route)

不要使用 Custom Domain,而是使用 Triggers -> Routes

步骤 4:SaaS 回退源设置

  • 在 Cloudflare 后台 -> SSL/TLS -> Custom Hostnames。
  • Fallback Origin: 填写 www.domain1.xyz。
  • 等待状态变为 Active。

五、 总结

通过这套方案,我成功实现了:

  1. 由 Cloudflare Pages 托管内容:享受免费、快速的静态部署。
  2. 由 Cloudflare SaaS 管理域名:自动为所有域名签发证书。
  3. 由 Worker 解决兼容性:在免费版 Cloudflare 不支持 Origin Rules 修改 Host 头的情况下,用 Worker 以极低的延迟完成了“中间人”重写工作。
  4. 支持优选 IP 接入:客户域名可以通过 CNAME 解析到优选线路,显著提升国内访问速度。

技术启示:在 Cloudflare 的生态中,DNS 是入口,Worker 是胶水,SaaS 是大脑。理解它们之间如何传递 Host 头是解决连接问题的关键。