A vs CNAME 困惑:到底该用哪种 DNS 记录?

主机文档说 A、教程说 CNAME,apex 解析不了或邮件还断了。一张经过核实的速查表,讲清 apex / www / 子域分别该用什么(Vercel、Netlify、GitHub Pages、Cloudflare)。

你在给新域名配 DNS。Vercel 文档说”加 A 记录”,YouTube 教程说”用 CNAME”。你在 apex(裸根域,example.com)上试了 CNAME,结果 DNS 提供商要么直接拒绝,要么接受了之后 MX 邮件就投递不了了。

最快修复apexA 记录(如果提供商有 ALIAS/ANAME 或 CNAME flattening 选项也可以用);子域(比如 www)用 CNAME。所有这些背后只有一条硬规则,来自 RFC 1912 §2.4CNAME 在同一个 name 上不能跟任何其它记录共存。 apex 上一定带着别的记录(SOANS,通常还有 MX),所以在那儿放 CNAME 是非法的,会把这些记录顶掉;子域上一般没别的记录,所以用 CNAME 没问题。拿不准时,以你主机平台后台显示的值为准,别信通用教程。

先判断你属于哪一类

你的情况该用什么
apex / 根域(example.com@A 记录指向平台 IP。只有需要跟踪会轮换的目标时才用 ALIAS/ANAME 或 Cloudflare CNAME flattening。
www 或其它子域CNAME 指向平台目标(*.vercel-dns.com / *.netlify.app / *.pages.dev / username.github.io)。
提供商报错 “CNAME at apex”apex 改成 A(或 ALIAS)。
加完记录后邮件断了你在 apex 放了 CNAME,把 MX 顶掉了。换成 A
站点时而旧时而新同一个 name 上同时有 ACNAME(或旧 + 新)。删掉错的那条。

常见原因

按命中率从高到低排。

1. 在 apex 用了 CNAME

RFC 1912 §2.4 禁止在 zone apex 用 CNAME,因为 apex 必须持有 SOANS(通常还有 MX),而 CNAME 不能跟任何其它记录共用一个 name。提供商会报类似 CNAME records cannot coexistCNAME conflicts with NS 的错,或者静默接受、然后邮件就发不出去了。

怎么判断:DNS 提供商错误里提到 “CNAME and apex”、“CNAME flattening required”,或者根上有 CNAMEMX 记录突然解析不出来。

2. 跟了两套文档

一套说用 A、一套说 CNAME,你同一个 name 两个都配了。提供商可能拒绝第二条,也可能静默接受导致解析结果不可预测。

怎么判断:DNS 面板里同一个 name 有两条记录。应该只留一种,绝不能两条都在。

3. 该用 CNAME 时用了 A

子域上,像 Vercel(www)、Netlify 给你的 CNAME 目标会解析到负载均衡、会轮换的 IP。你硬编码一条 A 记录指向单个 IP,主机更换服务器那天,你就指向了一台过期的机器。

怎么判断:主机文档说 CNAME cname.vercel-dns-0.com 但你设了 A 76.x.x.x。今天正常,几周后莫名其妙就挂了。

4. 该用 A 时用了 CNAME

Vercel 的 apex 要求 A 76.76.21.21,不是 CNAME。某些平台接受 ALIAS/ANAME(或 CNAME flattening)作为 apex 上类 CNAME 的选项。如果你的 DNS 提供商没有这类选项,就只能用 A

怎么判断:你的 DNS 提供商没有 apex CNAME 选项,你还是在 apex 设了 CNAME,然后平台拒发 SSL 证书,或显示 Invalid Configuration / DNS verification failed

5. 迁移过程中混了记录

你换了主机。旧的 A 记录还在,新的 CNAME 指向别处。解析器在两者间轮询,或不一致地挑一个。

怎么判断:同一个 name 两条记录指向不同地方;站点时而加载新部署、时而加载旧的。

6. 用了 ANAME/ALIAS,但提供商底层把它实现成真 CNAME

ANAMEALIAS 是非标准扩展,通过在查询时把目标解析成 A/AAAA 答复来模拟 apex CNAME 的行为。有些提供商实现得对;少数把 ANAME 底层映射成真正的 CNAME,于是又把 MX 破坏了。

怎么判断:看提供商关于 ANAME 兼容性的说明。加一条 MX 记录测试一下;如果它消失或报冲突,说明你的 ANAME 其实是 CNAME

最短修复路径

第 1 步:查你主机平台的要求

下面是截至 2026 年 6 月的官方值。务必再对照你自己后台显示的值,因为有些平台会发给每个项目专属的目标。

平台Apex(@)www / 子域
VercelA 76.76.21.21(或把 nameserver 切到 Vercel)CNAME cname.vercel-dns-0.com(或你后台显示的项目专属目标)
NetlifyA 75.2.60.5,或 ALIAS/ANAMEapex-loadbalancer.netlify.comCNAME yoursite.netlify.app
Cloudflare PagesCloudflare nameserver;在 @CNAME yoursite.pages.dev(自动 flatten)CNAME yoursite.pages.dev
Firebase Hosting控制台给出的两条 A 记录控制台给出的 CNAME
GitHub PagesA 185.199.108.153185.199.109.153185.199.110.153185.199.111.153CNAME username.github.io
AWS(S3 + CloudFront)A-ALIAS 到 CloudFront 分发(Route 53)CNAME 到 CloudFront 域名

照平台文档或后台的精确值用。

第 2 步:apex 用 A 或 ALIAS/ANAME(或干脆切 nameserver)

如果你的 DNS 提供商支持 ALIAS/ANAME(Route 53、Cloudflare、DNS Made Easy、Namecheap、Porkbun),就可以在 apex 用它来跟随一个类 CNAME 的目标。否则用 A 记录 + 平台 IP。

  • Cloudflare:直接在 @ 上放一条 CNAME 就行。只要记录 name 是 @,Cloudflare 在所有套餐(含 Free)上都会自动做 CNAME flattening——把链条解析到 A/AAAA 再返回,既符合 RFC、MX 又照常工作。
  • Vercel / Netlify / Firebase:最干净的做法是把整个域名委派给平台的 nameserver,之后平台会替你管理 apex 的 A 记录。如果你坚持用外部 DNS,就用上面表里的 A 值。

第 3 步:子域用 CNAME

wwwblog.yourdomain.comstaging.yourdomain.com 都应该用 CNAME 指向平台目标。绝不要在主机做负载均衡的子域上,用 A 记录硬塞一个 apex IP。

第 4 步:删掉冲突记录

同一个 name 上不要 ACNAME 都留,也别留着上一个主机的过期记录。每个 name 只留一条,其余删掉。

第 5 步:用 dig 验证记录类型

dig +short example.com           # apex:应打印一个 IP(A 记录)
dig +short www.example.com CNAME # www:应打印 CNAME 目标

如果 apex 打印出来的是主机名而不是 IP,说明那儿还留着 CNAME。如果 wwwCNAME 查询什么都没打印,说明你在该放 CNAME 的地方设了 A。再确认邮件没被波及:

dig +short MX example.com        # 应仍列出你的邮件主机

第 6 步:等传播后再验证一次

DNS 改动不是即时生效。要给缓存清理留出最多 24 小时(有些提供商提示最多 48 小时),不过大多数解析器会在 15-60 分钟内更新。从几个公共解析器查一查,再刷新浏览器:

dig +short example.com @1.1.1.1   # Cloudflare 解析器
dig +short example.com @8.8.8.8   # Google 解析器

当所有解析器都返回新值、平台显示域名为 Valid Configuration(且 SSL 证书签发成功)时,就搞定了。

怎么确认已经修好

满足下面三条就算彻底修好:

  1. dig +short example.com 返回平台 IP(一条 A),dig +short www.example.com CNAME 返回平台主机名(一条 CNAME)。
  2. dig +short MX example.com 仍列出你的邮件主机,说明邮件没断。
  3. 主机后台显示域名有效,并以 HTTPS 提供服务、没有证书报错。

常见问答

根域到底能不能用 CNAME? 真正的 CNAME 不行。变通方案是 ALIAS/ANAME 或 Cloudflare 的自动 CNAME flattening——它们对外像 CNAME 目标,但实际返回 A/AAAA 记录,所以 apex 上的 SOANSMX 照常工作。

我在根域加了 CNAME 之后邮件为什么停了? CNAME 不能跟同名的任何其它记录共存(RFC 1912 §2.4),所以它把 apex 的 MX 记录顶掉了。把 apex 的 CNAME 换成 A 记录(或 ALIAS/flattening),MX 记录就又可见了。

A 记录和 CNAME 到底有什么区别? A 记录把一个 name 直接映射到一个 IPv4 地址(IPv6 用 AAAA)。CNAME 是别名,意思是”去查另一个 name”,解析器再去取那个 name 的 A/AAAAA 钉死在某个 IP 上;CNAME 跟随目标当前解析到的结果。

我该用 A 记录,还是把 nameserver 切到主机? 如果你只在这个平台上托管网站、不跑复杂的外部 DNS,委派 nameserver 最省心,因为平台会替你更新 apex 的 IP。如果你需要在别处管理 MXTXT 等记录,就保留外部 DNS、用 A 记录。

主机给的是 cname.vercel-dns-0.com 而不是 cname.vercel-dns.com,哪个对? 以你自己后台显示的值为准。Vercel 会发给每个项目专属的 CNAME 目标,后缀在不同项目间可能不一样;从后台复制那个值永远是对的。

dig 输出看着没问题,但浏览器还是显示旧站点,为什么? 是你本地的 DNS 缓存或浏览器还留着旧答复。清一下操作系统的解析缓存,用 dig +short example.com @1.1.1.1 查公共解析器,等公共解析器返回新值后,再开一个无痕窗口试试。

预防建议

  • 信你主机提供商后台显示的值,不要信通用教程。
  • 每个 name 选了哪种记录类型,在 DNS 提供商的备注字段里记下来。
  • apex 域名:永远用 AALIAS/ANAME/flattening,永远不用真正的 CNAME
  • 同名不要混类型;选一条、删冲突。
  • 换主机时,先彻底删掉旧记录,再加新的。

相关阅读

标签: #排查 #DNS #排查