也来谈谈关于 CNAME 和 MX 冲突的一些事 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
SukkaW
V2EX    DNS

也来谈谈关于 CNAME 和 MX 冲突的一些事

  •  
  •   SukkaW 2018-09-08 22:07:26 +08:00 5820 次点击
    这是一个创建于 2641 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文不是什么解决 CNAME 和 MX 冲突的教程贴。

    本文转载自我的博客: https://blog.suka.moe/post/about-cname-and-mx-conflicts/


    这本来是一个颇老生常谈、甚至是一个本应该盖棺定论的问题了。虽然 RFC 1034 早就给出了规范,但是 CNAME 和 MX 不能同时添加的问题之前 在 V2EX 再次出现,所以我打算也来谈一谈这个问题。

    缘由

    CDN 服务商的众多节点大多都是使用 GSLB 进行调控的,大部分 CDN 服务的 GSLB 又都是通过 CDN 服务商的权威 DNS 设施上部署的 GeoDNS 实现的(少数如 Cloudflare、Fastly、Stackpath、MaxCDN、Google Global Load Balancer 等 CDN 服务商使用了 Anycast、通过调整 BGP Route 实现 GSLB )。所以用户的网站如果需要接入 CDN 一般有两种方法,将用户的域名接入到 CDN 服务商的权威 DNS ( 360 网站卫士和百度云加速的 NS 接入),或者用户通过添加 CNAME 记录从而实现 CDN 服务商的权威 DNS 接管 GeoDNS。

    对于一些需要在根域(@)接入 CDN、同时需要添加域名邮箱所需的 MX 记录时,就会导致冲突问题。

    剖析问题

    毫无疑问,只要了解一些 DNS 的基础知识的都知道,CNAME 的意思是当前域名的解析结果应该全部、毫无保留的采用返回的 CNAME 域名的解析结果;递归 DNS 会直接向下追踪 CNAME 域名的解析记录、会直接无视其它解析结果。而且,因为 RFC 规范,权威 DNS 和递归 DNS 都不会允许 CNAME 和其它类型的解析结果同时、一起返回。

    常见的解决方案

    使用 CNAME,无非是因为 SLB、GSLB 由其它服务商提供,而且服务商在使用自己的权威 DNS 设施实现 SLB 和 GSLB。解决的方法也很简单,不使用 CNAME 而直接使用 A/AAAA 就可以和 MX 共存了。

    所以,最完美的解决方案,应该就是用户直接使用 NS 接入 CDN 服务商、直接使用 CDN 服务商的权威 DNS (如本文一开始就提到的 360 网站卫士、百度云加速,以及 Fatstly 和 Akamai 的定制版业务),不仅 GeoDNS 和使用 CNAME 一样精准,而且 CDN 服务商的权威 DNS 可以直接给 @ 返回 A/AAAA 记录,和 MX 记录并不冲突。

    另一个相对最完美的解决方案是在 CNAME 域名中返回 MX 记录。Cloudflare 的 CNAME Setup 就是采用这种解决方案。以使用 CNAME Setup 的 globalsign.com 为例,globalsign.com 对应的 CNAME 是 globalsign.com.cdn.cloudflare.net ,你们可以在终端里 dig 一下这个 CNAME 域名:

    $ dig globalsign.com.cdn.cloudflare.net ;; ANSWER SECTION: globalsign.com.cdn.cloudflare.net. 300 IN A 198.41.214.154 globalsign.com.cdn.cloudflare.net. 300 IN A 198.41.215.154 
    $ dig globalsign.com.cdn.cloudflare.net MX ;; ANSWER SECTION: globalsign.com.cdn.cloudflare.net. 300 IN MX 10 globalsign-com.mail.protection.outlook.com. 

    这样如果 globalsign.com 的根域名添加了 globalsign.com.cdn.cloudflare.net 的 CNAME 记录,就不会导致找不到 MX 记录而丢失信件。

    然而,globalsign.com 是直接在 @ 添加了两条 A 记录( Cloudflare Anycast IP ),并不是直接添加 CNAME 而且,大部分 CDN 服务商内部的 GSLB 系统会导致多个 CNAME 递归,七牛这种卖二手 CDN 更会导致 CNAME 之间的递归。所以这种方案并不现实。

    还有相对不完美的解决方案。部分权威 DNS 服务商提供这样一种服务:由权威 DNS 的节点解析 CNAME 的 A/AAAA 的结果,然后权威 DNS 直接返回 A/AAAA 记录。这样的服务通常会被命名为 ALIAS ANAME Flatten CNAME 等。使用这类服务将 CNAME 变成 A/AAAA 的方案的确可以解决冲突的问题,但是 Flatten CNAME 又要保留 GeoDNS,就会高度依赖于权威 DNS 服务商的节点分布,所以最终得到的 GeoDNS 结果一定会~~非常~~不精确。

    DNSPod 的共存和 CloudXNS 的 LINK 记录

    接下来就是本文的重点了。之前 DNSPod 支持同时添加 CNAME 和 MX 记录(虽然添加时面板会提示可能导致问题)、CloudXNS 的面板不允许 CNAME 记录和 MX 记录共存,但是 CloudXNS 官方在他们的用户社区中发过使用 LINK 记录绕过这个限制的方法。

    前面说过,规范已经规定了 CNAME 和 MX 记录不能同时返回,那么 DNSPod 是怎么做的? DNSPod 自称他们是自研的架构而不是使用 BIND 这类成熟的程序。这并不是重点,重点在于 DNSPod 可以根据向他们的权威 DNS 节点的请求的不同 Type 返回不同的结果,说人话就是你向 DNSPod 请求 MX 记录他们就会返回 MX 记录,你向 DNSPod 请求 A/AAAA 这些就返回 CNAME。 但是,用户并不会直接请求 DNSPod 的权威 DNS 的用户都是请求的递归 DNS,你不能保证所有用户都使用你 DNSPod 提供的公共 DNS 嘛。一旦递归 DNS 缓存了 CNAME 记录,就会沿着 CNAME 域名继续向下请求解析,就会导致邮件丢件。

    CloudXNS 的 LINK 也不是 Flatten CNAME 这类服务,而是一个便捷的管理多个 CNAME、减少 CNAME 递归次数的一个工具;如果你为 CDN CNAME 域名添加的 LINK 记录,最终依然会返回 CNAME 记录。使用 LINK 绕过 CNAME 和 MX 不能共存的限制,和 DNSPod 的允许在控制台中同时为 @ 添加 CNAME 和 MX 本质上并没有什么区别。 如果权威 DNS 支持 CNAME 和 MX 共存,那么为了防止邮件丢件,就应该尽可能少的让 CNAME 被缓存,这样 MX 依然有机会会被返回,也就是把 TTL 调整地尽可能短。但是,权威 DNS 服务商为了降低自己的服务的负载,会限制最短 TTL ;即使你成功缩短了权威 DNS 返回的 TTL,递归 DNS 也会为了降低自己的服务负载而篡改 TTL。所以这并不是一个可行的解决方案。

    最近 DNSPod 也开始禁止 CNAME 和 MX 共存 了,已经共存的会把 MX 暂停掉,看来 DNSPod 应该放弃他们的自研架构了。

    9 条回复    2018-09-10 10:54:56 +08:00
    HXM
        1
    HXM  
       2018-09-08 23:04:41 +08:00 via Android
    感谢科普
    CNAME 和 TXT 不能共存也是类似原因吧?
    博客现在扔在 Coding Page 上,但它不像 GitHub 可以通过 A 记录解析,必须用 CNAME,这就很难过了。。
    shansing
        2
    shansing  
       2018-09-08 23:28:35 +08:00
    前不久还遇到过京东云解析的不规范实现,在设置了 CNAME 的情况下,请求 TXT 并不会返回 CNAME,导致 acme.sh 的 alias-mode 使用失败。
    SukkaW
        3
    SukkaW  
    OP
       2018-09-08 23:34:49 +08:00   2
    @HXM #1 是的。不过 Coding Pages 就一堆 Zenlayer HK、没有 GeoDNS,配个 Flatten CNAME 就行了
    @shansing #2 一般“自研架构”都会有这种问题,比如之前 DNSPod 请求 CAA 时,不存在相关记录时不返回 SOA,导致很多 SSL 签发失败的问题
    Binarization
        4
    Binarization  
       2018-09-09 00:50:25 +08:00 via Android
    这样一想,将来 IPv6 很多,运营商都建 anycast 网络,CDN 都在 IP 后面,cname 就不要用了
    mason961125
        5
    mason961125  
       2018-09-09 02:31:13 +08:00 via iPhone
    我记得 Cloudflare 默认把 @的 CNAME 记录做了 flatten
    isCyan
        6
    isCyan  
       2018-09-09 11:55:44 +08:00 via Android
    很详细
    realpg
        7
    realpg  
    PRO
       2018-09-09 15:01:18 +08:00
    想玩 CNAME 就抛弃空头 空头直接 301/302 redirect 到 www 就好了
    要么就换个域名做邮箱
    zhxhwyzh14
        8
    zhxhwyzh14  
       2018-09-09 17:39:18 +08:00 via Android
    这是因为标准中 CNAME 记录太过于霸道了吗,
    johnjiang85
        9
    johnjiang85  
       2018-09-10 10:54:56 +08:00
    DNSPod 前端禁止同时添加共存并不是改架构了,而是为了减少客户出现问题和减少对一线的反馈。其实 DNSPod 后台也是支持类似的 LINK 记录的,是 CNAME 加速的额外附加功能,当 CNAME 和 MX 共存时会尝试直接返回 A 记录,而不是返回 CNAME 记录,但是限制条件太多,并不实用,具体可以看这里: https://support.dnspod.cn/Kb/showarticle/tsid/246
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1256 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 23:55 PVG 07:55 LAX 15:55 JFK 18:55
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86