Cloudflare 的 CNAME 展平(拉平)到底做了什么?

在别家 DNS 上,根域名填 CNAME 会被直接拒掉;在 Cloudflare 上它不但能填,还会静悄悄变成另一种东西。这中间被替换掉的那一步,正是后面所有奇怪现象的来源。

更新于 2026年8月26日 · 阅读时间 约 10 分钟

展平就是 Cloudflare 替你把 CNAME 解析成 IP,返回一条 A 记录而不是 CNAME。根域名上的 CNAME 在所有方案下都强制展平,关不掉。

把域名接进 Cloudflare 之后,很多人第一次发现「原来根域名也能填 CNAME」。别的 DNS 服务商在这里会直接报错,Cloudflare 却连眉头都不皱,顶多在保存时提示一句「我们用 CNAME 展平来实现这一点」。于是这条记录就这么留下了,一切看着都正常。

问题往往几个月后才浮上来:第三方域名验证怎么都过不去;国内 CDN 买了却没提速;dig 查自己的域名,回来的居然是一条 A 记录。这些症状看着不相干,根却在同一处——展平不是把你的 CNAME 原样搬到线上,而是用另一样东西替换了它。

根域名上,本来就不该有 CNAME

DNS 规范里有一条硬约束:一个名字上如果有 CNAME,就不能再有同名的其它记录。CNAME 的语义是「这个名字整体是另一个名字的别名」,别名之下再挂别的东西,语义上说不通。

而域名的顶点——也就是 example.com 本身,Cloudflare 文档里叫zone apex,面板里填 @ 的那一格——身上必然带着 SOA 和 NS 记录,它们是这个域名存在的凭据,删不得。两条规矩撞在一起,结论就是根域名上放不了 CNAME。想让 example.com(而不是 www.example.com)指向某个 SaaS 或 CDN 给的主机名,标准 DNS 里没有正路。

Cloudflare 给出的解法是绕过去而不是打破它:面板里允许你填 CNAME,但对外永远不把它当 CNAME 返回。官方对这套机制的定位写得很直白——让根域名上的 CNAME 「符合 DNS 标准地」被解析掉。换句话说,你填的那条记录是一份配置意图,不是最终会被广播出去的答案。

展平那一刻,Cloudflare 做了什么

当解析器来问 example.com 的 A 记录,Cloudflare 查到顶点上是一条 CNAME,不会把这条 CNAME 递回去,而是就地把它当成一次待办:去解析目标主机名,拿到 IP;如果目标底下还是 CNAME,就继续追,直到落在 A 或 AAAA 上。拿到最终 IP 之后,把答案里的记录名改写成 example.com,再返回。

CNAME 展平返回的是什么访客的解析器example.com IN A ?Cloudflare 权威 DNS根域名上是一条 CNAME,强制展平替你去解析目标主机名cdn.example.net → 192.0.2.1答案的形态,取决于这条记录的代理状态代理开着 · 小黄云example.com 300 IN A [Cloudflare IP]多条任播 IP,TTL 固定 300代理关着 · 灰云example.com 3600 IN A 192.0.2.1源站 IP,TTL 取两者中较小的那个
查询走到 Cloudflare 就停了:那一次对目标主机名的解析发生在 Cloudflare 一侧,访客的解析器从头到尾只拿到一条 A 记录。

这一步最容易被忽略的性质是:那次对目标主机名的解析,发生在 Cloudflare 一侧,不在访客一侧。访客的解析器只发出了一个问题、收到了一条 A 记录,全程不知道中间还隔着一个主机名。后文那些看着不相干的坑,几乎都是这句话的推论。

返回的答案长什么样,取决于这条记录的代理状态,两种情况的 TTL 规则也不一样:

代理状态返回的内容TTL
开着代理(小黄云)多条 Cloudflare 任播 IP,跟你填的目标无关固定 300 秒
关着代理(灰云)展平出来的那个真实 IPCloudflare 这条 CNAME 与目标那条 A 记录中较小的一个

第二行值得多看一眼。把 CNAME 的 TTL 调到 60 秒,并不意味着改动一分钟内就能扩散开;调到 86400 秒也未必留得住——对方那条记录一小时就到期的话,整条答案跟着一小时过期。TTL 的话语权在更保守的那一方手上。

什么时候会展平,什么时候不会

展平不是一个非开即关的全局设置,而是几条触发条件叠在一起的结果。官方的设置文档把它们分得很清楚:

情形会不会展平方案要求
记录在域名顶点(@强制展平,没有开关所有方案,含免费
记录开着代理默认展平,因为返回的本来就是任播 IP所有方案
目标主机名在同一个域名内直接展平,无视下面两个开关所有方案
「对所有 CNAME 记录展平」全局开关打开后所有 CNAME 一并展平仅付费方案
单条记录上的 Flatten 选项只展平勾中的那条仅付费方案

所以免费方案能碰到的展平只有前三种,而且都不可关闭。付费方案多出来的两个开关,作用范围也只在子域名的灰云 CNAME 上——真正让人栽跟头的顶点那条,任何方案都动不了。

单条勾选的 Flatten 会在区域文件里留下 cf-flatten-cname 标记,导入导出不丢配置;走 API 的话,全局开关是 DNS 设置里的 flatten_all_cnames,单条的是记录 settings 里的 flatten_cname。面板上有三种情况看不到 Flatten 这个勾选框:记录在顶点上、记录已经开着代理、全局开关已经打开——这三种都意味着「已经在展平了,不用你选」。

展平会咬到你的四种情况

第三方域名验证过不去。不少服务要求你加一条 CNAME 指向它给的主机名,然后它去查这条 CNAME 是否存在。展平之后应答里只有 IP,CNAME 记录本身不再直接返回,验证方查不到自己要的东西,就会一直卡在「等待验证」。官方文档专门为这种场景留了警告。处理方式是把这条记录留成灰云,并确认全局展平没打开。

目标是悬空 CNAME,应答直接变空。如果一路追下去,最终那个主机名底下并没有 A 或 AAAA 记录,展平就没有 IP 可返回,Cloudflare 会给出一个空应答(NODATA)。表现出来很像「解析怎么还没生效」,其实是解析已经完成、答案里什么都没有。查一下目标主机名本身能不能解析出 IP,比反复刷新解析工具管用。

指向别人 Cloudflare 账号下的主机名会被封。CNAME 到另一个 Cloudflare 账号里的域名是被明确禁止的,触发的是 Error 1014:CNAME Cross-User Banned。这条在「我用 CNAME 接一个朋友的服务」这类场景里踩得最多。

灰云顶点会把源站 IP 摆到台面上。顶点上的 CNAME 只要是灰云,展平的结果就是把目标的真实 IP 当成一条普通 A 记录返回。任何人 dig example.com 都能直接拿到它——本来隔着一个主机名的间接性,被展平这一步抹平了。这一点值得和源站 IP 泄露的其它路径放在一起看。

反过来说,展平也不全是麻烦。Cloudflare Pages 之所以能把根域名直接绑成自定义域,靠的正是这套机制;解析路径少一跳,查询也确实更快。它只是有代价,而代价通常不写在你保存记录的那个弹窗里。

在国内用,多出来的那一层麻烦

把「那次解析发生在 Cloudflare 一侧」这句话放到国内的网络环境里,麻烦会明显放大,因为国内这套体系高度依赖「按解析来源做调度」。

最常见的一种是把根域名 CNAME 到国内 CDN。国内 CDN 给你的是一个主机名,它的智能调度全靠这个主机名被查询时的来源判断访客大致位置,再返回就近节点。展平把发问的人从你的访客换成了 Cloudflare,调度依据当场消失;更麻烦的是,展平出来的结果会作为一条普通 A 记录发给所有人,等于把一次本该千人千面的调度,冻结成了一个全球统一的 IP。买了 CDN 却没有提速,多半就卡在这里。

这件事没有「在 Cloudflare 里关掉展平」这个解,顶点那条关不掉。可行的路只有三条:把 DNS 托管交回给 CDN 厂商或别的支持根域名 CNAME 的服务商;退回到 A 记录直接写 IP,接受失去调度、对方换 IP 时手动跟;或者承认这个域名的主力访客不在国内,让它走 Cloudflare。三条各有代价,但都好过一直以为「配好了只是还没生效」。

另一种是备案与解析分家的场景。国内业务常常要求域名解析到已备案的境内 IP,而顶点上一旦挂了 CNAME 并被展平,最终返回什么 IP 就取决于展平那一刻解析到的结果——你在面板里看到的是主机名,实际对外广播的是 IP,两者不是一回事。做备案核验或者排查解析问题时,一律以 dig example.com 实际收到的应答为准,别拿面板截图当证据。

还有一种是跨境链路带来的观感差异。顶点记录一旦开着代理,展平返回的就是 Cloudflare 的任播 IP,TTL 固定 300 秒。国内访客大概率被引到境外节点,链路本身的抖动会盖过 DNS 层面的任何优化——这时候纠结 TTL 设多少是没有意义的,瓶颈不在这里。把顶点改成灰云也只是换了个方向:解析快了,但代理带来的缓存、WAF 和 DDoS 防护同时也就没了,这笔账要一起算。

怎么确认自己这条记录到底是什么状态

面板不会告诉你对外返回的是什么,命令行会。查一次顶点,看回来的记录类型是 CNAME 还是 A,基本就有答案了:

dig +short example.com A
dig +noall +answer example.com

第二条会连 TTL 一起显示。看到的是 A 记录且 TTL 是 300,说明顶点开着代理;是 A 记录但 TTL 是个别的数字,说明灰云展平生效,那个 IP 就是你的源站或 CDN 节点;如果什么都没返回,多半撞上了前面说的悬空 CNAME。想确认展平之前那一层长什么样,直接去查目标主机名本身,把两边的结果对着看。

官方的 顶点记录 CNAME 字段说明可以对照着看:面板里那个 TTL「自动」,在代理开着时就是 300。

常见问题

Cloudflare 的 CNAME 展平能关掉吗?

根域名上的那条关不掉。只要记录名是 @,也就是落在域名的顶点上,Cloudflare 在所有方案下都会强制展平,面板里连开关都不会出现。能关的只有另外两件事:付费方案上的「对所有 CNAME 记录展平」这个全局开关,以及单条记录上的 Flatten 选项——它们管的是子域名上那些 CNAME 要不要一并展平。想让根域名真正返回一条 CNAME,只能把域名的 DNS 托管换到别家。

CNAME 展平和 CNAME 拉平是一回事吗?

是同一件事。CNAME flattening 在中文里有人译成展平,有人译成拉平,也有人直接叫「根域名 CNAME」,指的都是 Cloudflare 替你把 CNAME 一路解析到最终的 IP、然后返回 A 或 AAAA 记录而不是 CNAME 记录这个行为。Cloudflare 面板里的设置项叫 CNAME Flattening,API 字段是 flatten_all_cnames 和 flatten_cname。

根域名 CNAME 到国内 CDN,为什么国内访问反而变慢了?

因为那次解析不是访客做的,是 Cloudflare 做的。国内 CDN 的调度靠的是「谁在查」——按解析请求的来源判断访客大概在哪,再返回就近节点的 IP。展平把这一步搬到了 Cloudflare 的权威侧,CDN 看到的提问者变成了 Cloudflare,返回的节点自然也不再是照着你的访客选的。更要命的是这个结果会被当成一条普通 A 记录发给全世界,所有访客共用同一个 IP,调度整个失效。

展平之后 TTL 是多少?

分两种。这条记录开着代理时,返回的是多条 Cloudflare 任播 IP,TTL 固定为 300 秒。关着代理时,返回的是展平出来的源站 IP,TTL 取 Cloudflare 这条 CNAME 记录和目标那条 A 记录里较小的那个值。所以把 CNAME 的 TTL 设小并不能让整体变快,设大也未必生效——真正说了算的是两者中更保守的一方。

第三方服务让我加一条 CNAME 做域名验证,加完一直验证不过怎么办?

先看这条记录是不是被展平了。验证方通常要查到 CNAME 记录本身,而展平之后返回的是 IP,CNAME 记录不再直接出现在应答里,验证就会失败。对应的处理是:关掉「对所有 CNAME 记录展平」这个全局开关,或者取消这条记录上的 Flatten,同时确认它是灰云状态。另一种情形是目标主机名底下压根没有 A 或 AAAA 记录,展平会返回一个空应答,看起来就像解析一直没生效。

在手机上管好 Cloudflare

Orange Cloud 是 Cloudflare 的第三方 iOS / Android 客户端,用 Cloudflare 官方 OAuth 登录,随手切代理状态、改 DNS 记录、看隧道状态和流量分析。

下载 Orange Cloud