Cloudflare 的 CNAME Flattening

今天推一波 Cloudflare 的 CNAME Flattening 功能,它能解决什么问题呢?我们先来看一个需求:

现在我有一个域名 awen.me 我希望用户访问 https://awen.me 就可以看到我的网页,同时我又想使用邮件服务(邮件服务需要添加 MX 记录),如果你直接添加 A 记录解析到你的网站是没有问题的, 也就是 A记录+MX记录;但是如果你希望使用 CNAME记录+MX记录,通常会在使用 CDN 的时候用到 CNAME 解析,则会冲突

大多数域名厂商是不允许你这么添加的,但是有的也允许你添加只不过会提示你,不过你的邮件服务可能无法正常收发邮件。这是因为 DNS 就是这样设计的。参考 RFC 1034 文档

 If a CNAME RR is present at a node, no other data should be
present; this ensures that the data for a canonical name and its aliases
cannot be different.

意思是如果CNAME记录指向了一个域名节点,为了确保不会出现不同的解析结果,那么这个域名节点将不在接受其他的记录值了。

那么假如说你希望使用 CDN 服务的同时又使用邮件服务其实也不是不可以的:

第一种方法,就是使用类似 Cloudflare 这种 CDN 加速服务,使用 NS 解析,把域名 DNS 解析修改为 Cloudflare 这种 CDN 厂商的进行加速基本不需要做任何过多的配置,Cloudflare 免费版解析得到的是国外的地址很可能加速有效果还不如不加速。但是你如果不想备案又想用 CDN 也是可以的,当然你也可以付费 Cloudflare 和百度合作国内也有不少节点(需要付费+备案),但是Cloudflare 都是按功能收费的,你也可以尝试找找国内的类似服务。目前看我基本没有发现什么特别满意的,国内我还是比较喜欢又拍云的服务,只不过又拍不支持 NS 解析这种方式,又拍除了 CDN 加速之外还有各种附加功能,例如 HTTPS、webp 自适应、Let’s Encrypt 自动续签证书以及支持 Rewrite 规则等等非常好用的功能,这里有些功能在 Cloudflare 这种国外 CDN 大厂可都是要另外单独付费才可以使用的,就比如说自定义缓存规则这个,又拍云可以非常精细的控制不同文件类型、不同路径的文件缓存规则,而 Cloudflare 界面上我只看到了个全局环境配置。

第二种方法,是获取 CDN 厂商的边缘 IP 地址,将其添加为 A 记录,例如解析得到的 CDN 厂商 IP 为 1.1.1.1,则你可以添加 A 记录,因为上面说了 A 记录和 MX 记录是可以同时存在的:

记录名称 记录类型  记录值
@        A       1.1.1.1

但是 CDN 的节点 IP 有很多,你如果希望达到 CDN 加速效果其实这样做非常麻烦,你要自己根据运营商线路做解析,并且 CDN 厂商的节点 IP 经常变更,不好维护。

那么上面说的 CNAME Flattening 功能就能解决这个问题,你只需要使用 Cloudflare 的 DNS 解析服务即可。在 Cloudflare 默认该功能是开启的

你只需要按 CDN 厂商的要求添加 CNAME 解析即可。例如我使用又拍云的 CDN 解析值为

生效后我查询解析

➜  www dig awen.me

; <<>> DiG 9.10.6 <<>> awen.me
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5204
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;awen.me.            IN    A

;; ANSWER SECTION:
awen.me.        264    IN    A    183.131.200.74
awen.me.        264    IN    A    183.131.200.69
awen.me.        264    IN    A    183.131.200.75
awen.me.        264    IN    A    183.131.200.81
awen.me.        264    IN    A    183.131.200.61

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Apr 02 20:05:35 CST 2018
;; MSG SIZE  rcvd: 116

得到的 IP 是 CDN 边缘节点的 IP 地址,可以看到这一个地区解析的 IP 地址就这么多,那么多节点你觉得你能管理好吗?

同时我还做了邮件解析

➜  www dig awen.me MX

; <<>> DiG 9.10.6 <<>> awen.me MX
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60041
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;awen.me.            IN    MX

;; ANSWER SECTION:
awen.me.        300    IN    MX    20 mx2.zoho.com.
awen.me.        300    IN    MX    10 mx.zoho.com.

;; Query time: 383 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Apr 02 16:29:07 CST 2018
;; MSG SIZE  rcvd: 83

太棒了,鱼与熊掌同时可得。

之前我使用腾讯的 DNS 解析 发现居然可以同时添加 CNAME 和 MX 记录把我高兴的,因为在阿里云 DNSPOD 提交都直接提示冲突,我还以为腾讯解决了这个难题呢,没想到咨询后发现是他们的 BUG。