CNAME 接入:把第三方服务挂到自己的子域
把 blog.example.com 指到 Pages、把 shop.example.com 指到 SaaS、把 img.example.com 指到对象存储,用的都是 CNAME。它比 A 记录省心的地方在于对方换 IP 你不用改,麻烦的地方在于它有一堆互斥规则,撞上就是解析失败。读完这篇,你能独立完成一次 CNAME 接入,也能判断验证卡住时是代理的问题还是记录的问题。
记录类型的基础见 50-dns-records-tutorial.md;Pages 侧的自定义域流程见 69-pages-custom-domain-preview.md。
1. CNAME 是别名,不是转发
CNAME 记录的语义是"这个名字等同于另一个名字"。查询 www.github.com 时,权威服务器不返回 IP,而是返回"去看 github.com",解析器再查一次目标拿到 A 记录。本机实查:
www.github.com CNAME -> github.com
这条链的长度算一跳。每多一跳,解析就多一次查询,链太长会拖慢首包,也会放大故障面。两跳以内是常态,三跳以上要找机会收敛。
CNAME 的目标只能是域名,写成 IP、带协议、带端口、带路径都不成立。常见错误是把服务商给的 https://xxx.pages.dev 整段粘进值里,正确写法只留 xxx.pages.dev。
2. 与其它记录的互斥
同一个名字下,CNAME 不能与任何其它类型的记录共存。这条来自 DNS 规范,不是 Cloudflare 的限制:
| 冲突 | 结果 |
|---|---|
| CNAME + A | 同一名字两种答案,解析器行为不确定 |
| CNAME + MX | 邮件路由混乱,部分发信方拒收 |
| CNAME + TXT | 域验证记录失效 |
| CNAME 指向 CNAME | 允许,但形成链,注意成环 |
所以接入前先查一下这个子域上有没有别的记录。给 shop 加 CNAME 之前,shop 上的 TXT 验证记录要先删掉,否则保存会失败或者验证不生效。
3. 根域的特殊处理
按规范根域(example.com)不能有 CNAME,因为它同时承载 SOA 与 NS,而 CNAME 要求该名字下没有其它记录。Cloudflare 用 CNAME flattening 绕开这条限制:你在根域填 CNAME,它在回答时把目标展开成 A/AAAA 返回。
代价是这个能力只在 Cloudflare 侧成立。将来把 NS 换走,那条根域 CNAME 在别家要么被拒绝,要么行为不一致。所以根域的 CNAME 要当成"绑定 Cloudflare"的决定,接 Pages 根域时尤其要想清楚。
4. 接入流程
以接一个托管在第三方的静态站为例,下面的写记录动作未执行:
- 在服务商侧添加自定义域名,拿到它给的 CNAME 目标,形如
xxx.pages.dev或xxx.vercel-dns.com。 - 在 Cloudflare DNS 加记录:名称填子域前缀(如
blog),类型 CNAME,值填目标,先选仅 DNS。 - 等服务商完成验证并签发证书,通常几分钟到一小时。
- 验证通过后,如果需要 CDN 与 WAF,再把代理开关打开。
- 用
Resolve-DnsName确认解析结果,浏览器确认证书与内容。
第 2 步先选仅 DNS 是有原因的:代理开启后,外部看到的解析结果是 Cloudflare 的边缘 IP,服务商那边的"域名是否指向我"的校验会失败。等它验完、证书签发,再开代理。
顺序反了的表现是:服务商面板一直显示"等待 DNS 配置",而你自己查记录明明是对的。
5. 开了代理就查不到 CNAME
这点常引起误判。本机查 www.cloudflare.com 的 CNAME,返回的是 SOA 而不是 CNAME:
www.cloudflare.com CNAME -> 无 CNAME,只有 SOA
www.cloudflare.com A -> 104.16.123.96、104.16.124.96
原因是它配的是 A 记录,且开了代理,对外只回答边缘地址。同理,任何开了代理的 CNAME 在外部查询里都表现为 A/AAAA,看不到原始目标。要确认 CNAME 是否配对,去面板看,或者临时切成仅 DNS 再查。
6. 故障对照表
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 保存报错 | 同名下已有其它类型记录 | 删掉冲突记录 |
| 服务商一直验证不通过 | 代理开着,目标被隐藏 | 切仅 DNS,验完再开 |
| 打开是 522 / 521 | 目标不可达或回源被拒 | 检查目标域名是否可访问 |
| 证书报错 | 目标侧还没签发 | 等签发,或检查域名拼写 |
| 解析到旧地址 | TTL 未过期 | 等 TTL,或提前降 TTL |
TTL 的处理方式与 A 记录一致,迁移前降到 300 秒能显著缩短切换窗口。
常见问题
CNAME 能指向 IP 吗?
不能。要指向 IP 就用 A / AAAA。有些服务商面板允许填 IP,实际是它替你转成了 A 记录,不是 CNAME。
能不能 CNAME 到自己的另一个子域?
可以,注意别成环(a 指 b、b 指 a),成环会让解析直接失败。多级链也尽量收敛到一跳。
一个 CNAME 能给多个子域用吗?
可以,多个子域各自写一条 CNAME 指同一个目标,这是标准做法。反过来一条 CNAME 指多个目标不行。
小结
CNAME 解决的是"目标会变、我的域名不变"这个需求。它的规则不复杂,真正让人卡住的是两件事:同名记录的互斥,以及代理开关与第三方验证的先后顺序。
接入时的稳妥做法是先仅 DNS 跑通,确认证书与内容都对,再开代理拿 CDN 与防护。这个顺序能避免大部分"记录没错但就是不通"的情况。多域名统一跳转的做法见 94-multi-domain-redirect.md。
数据来源与检索时间
检索时间 2026-11-10。CNAME 与 A 查询为本机实跑。
| 来源 | URL | 对应数据 |
|---|---|---|
| Cloudflare CNAME 记录 | https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/ | CNAME 的写法与代理状态 |
| Cloudflare CNAME flattening | https://developers.cloudflare.com/dns/cname-flattening/ | 根域 CNAME 的展开与限制 |
| Pages 自定义域 | https://developers.cloudflare.com/pages/configuration/custom-domains/ | 接入 Pages 时的 CNAME 目标与验证 |
| RFC 1034 | https://www.rfc-editor.org/rfc/rfc1034 | CNAME 与其它记录不能共存、根域限制 |
核验说明
- 实查:
www.github.com的 CNAME 返回github.com;www.cloudflare.com的 CNAME 查询只返回 SOA、A 查询返回104.16.123.96与104.16.124.96,用于说明代理开启后外部看不到 CNAME。 - 依据文档:同名记录互斥、根域 CNAME 限制、Pages 与 SaaS 的验证顺序、代理对验证的影响,来自 Cloudflare 文档与 RFC,未做端到端接入。
- 未执行:添加或修改 CNAME、切换代理开关、绑定 Pages 自定义域,本机无 Zone 权限,全部未落地。