KernelRanch
返回文章列表

CNAME 接入:把第三方服务挂到自己的子域

2026-11-10 #域名

把 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. 接入流程

以接一个托管在第三方的静态站为例,下面的写记录动作未执行:

  1. 在服务商侧添加自定义域名,拿到它给的 CNAME 目标,形如 xxx.pages.dev 或 xxx.vercel-dns.com。
  2. 在 Cloudflare DNS 加记录:名称填子域前缀(如 blog),类型 CNAME,值填目标,先选仅 DNS。
  3. 等服务商完成验证并签发证书,通常几分钟到一小时。
  4. 验证通过后,如果需要 CDN 与 WAF,再把代理开关打开。
  5. 用 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 flatteninghttps://developers.cloudflare.com/dns/cname-flattening/根域 CNAME 的展开与限制
Pages 自定义域https://developers.cloudflare.com/pages/configuration/custom-domains/接入 Pages 时的 CNAME 目标与验证
RFC 1034https://www.rfc-editor.org/rfc/rfc1034CNAME 与其它记录不能共存、根域限制

核验说明

  • 实查: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 权限,全部未落地。