递归DNS如何选择权威DNS的IP-SRTT优化及实践

本文主要介绍递归DNS的SRTT本身机制及如何进行更进一步的优化,来达到更好的递归效果。都是字,不想弄图、表和数字,格式也有点乱,不想整理了,凑合看吧

1. SRTT本身机制

本节仅对SRTT进行简单的介绍供了解,不进行特别深入和详细的分析。

SRTT(Smoothed Round-Trip Time,平滑往返时延)是在递归DNS系统里,用加权平均算法计算出的上游DNS服务器的“响应时延”估值,它用于优化解析性能和选择最快的上游服务器。

延伸阅读

BIND的SRTT机制总体做的还是相对比较好的,可以参考 https://developer.aliyun.com/article/622410。

而Unbound社区版的SRTT做的则不够好,基本就是可用权威IP完全随机,递归的平均延迟非常高,所以在实际业务使用前必须进行优化,具体算法优化可以参考相关论文或BIND的实现等。

虽说递归DNS选择权威服务器时都希望选择延迟更低,但在最大限度降低递归时延的前提下,也要遵循一定的规则,如

  • 需要有一定的随机性选择非延迟最低的权威IP来自适应权威IP的RTT的波动和服务器的突然故障。
    • 如某个权威IP正常RTT很低,但偶发丢包被惩罚延迟后,需要能够逐步平滑降低其RTT。
    • 如果低RTT的权威IP突然故障,除了丢包惩罚延迟外,还需要随机性来选择其他权威DNS IP,防止单个IP不可用导致整个域名解析异常。
  • 标记不可用的IP也需要定时发送DNS请求。
    • 不可用的IP恢复可用后需要使用该机制探活标记为恢复可用
    • BIND和UNBOUND都会在15或30分钟完全重置一次权威IP的相关状态,其中包括RTT,以及IP的EDNS支持状态等。
    • 也可以低频率的对惩罚到标记不可用的IP做并发异步的DNS探活请求。
  • 不能向单一权威IP发送过于集中的请求,降低被权威封禁递归IP的概率。
    • 一个可探讨的方案介绍:如果本次不进行随机选择递归IP,选择最低RTT的IP时候再进行二次选择,1/2直接选择最低RTT的权威服务器,1/2在最低RTT差距一定范围内(如minrtt + 20ms,也认为有比较低的延迟)的其他权威服务器IP中随机选择。
    • 国内的各大权威DNS服务商的服务只要不是真实的攻击,常规的SRTT优化很是很难触发递归IP被封禁的场景的,但是一些单位、机构等自建的权威DNS,如果单个IP请求量较大则比较容易触发,所以这里也是递归DNS必须要考虑的一种场景。

2. SRTT的配套机制优化

只有SRTT本身的选择机制对一个递归DNS是不够的,还必须配合多个其他配套系统来使用,而这些配套系统对递归DNS的整体递归时延也是非常重要的。

2.1 某个权威DNS IP的SRTT生效范围

在实际业务中,存在以下两种场景会使多个域名使用相同的权威DNS IP

  • 不同的域名会使用相同的NameServer(NS)
  • 不同的域名使用的NS不同,但NS对应的IP相同(如腾讯云解析/DNSPod提供的个性化NS功能)

在我们的常规认知中,既然权威DNS IP相同,那么统一进行SRTT的探测和选择即可,这样多个域名的平均递归延迟都可以有效降低,如在每次权威IP状态重置后快速重新探测到RTT最低的权威DNS IP,且对所有域名生效。

但现实是相反的,多数递归DNS对这种场景的权威DNS IP探测是域名相关的,不同域名的权威DNS IP即使相同,也是分别独立探测和存储状态的(如Unbound的)。

对于某些特殊场景,这种做法可能有一定用处,如同一个IP对域名A支持EDNS,对域名B不支持等,但这极大增加了递归DNS解析时延(也浪费了一些内存,虽然现代服务器不怎么在意了)。

目前腾讯云/DNSPod的递归服务器的做法是所有域名只要权威DNS IP相同即共享一份SRTT的探测和选择结果,可以大幅提高选择RTT低的权威DNS概率(尤其是请求量不大的域名),降低解析延迟,不考虑一些特别极端的场景(也可以解析,但可能不是最优的结果,且此类极端场景在国内的权威DNS服务商中基本不存在)。

2.2 权威DNS IP的GEO优化

大家都知道普通域名的DNS解析可以做智能解析(分线路、GEO、基于延迟等),来给不同地域不同运营商的客户端分配不同的解析结果,达到降低延迟或节省成本的目的。那么对于给递归DNS使用的NameServer(NS)域名是否可以使用智能解析,来达到同样的目的呢?毕竟因为各种原因,国内大部分权威DNS服务商很难完全使用完全相同的Anycast IP在全球同时提供很高的高可用和很低的延迟,如果该方案可行,则权威DNS服务商有了一个变通的方式来同时满足高可用和低延迟的需求,如除了Anycast IP外还可以在不通地区提供一些本地的Unicast IP来降低本地递归DNS的访问延迟,比如目前腾讯解析/DNSPod和阿里云解析都做了该操作,那么效果如何呢。

答案是一半一半。

递归获取一个域名的权威DNS的NS IP有两个渠道,胶水记录和权威服务器的记录,其中NS域名在注册商/局设置胶水记录不支持智能解析,而在其本身权威DNS设置的解析记录则是可以支持设置智能解析线路的,下面分别进行介绍。

2.2.1 注册局的TLD服务器返回的glue record

  • 胶水记录(Glue Record)是一种特殊的DNS记录,用于解决域名解析过程中的循环依赖问题。当域名的权威DNS服务器(NS记录)是当前域名的子域名时,胶水记录是必须存在的(如后续示例所示),由域名所有者直接在注册商/局(父域DNS,如.com的TLD服务器)中提供子域名服务器的IP地址,确保递归DNS能够正确找到目标的权威DNS服务器。
dig @a.gtld-servers.net ns3.dnsv5.com

; <<>> DiG 9.11.26-RedHat-9.11.26-6.tl3 <<>> @a.gtld-servers.net ns3.dnsv5.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45009
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 11
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ns3.dnsv5.com.                 IN      A

;; AUTHORITY SECTION:
dnsv5.com.              172800  IN      NS      ns3.dnsv5.com.
dnsv5.com.              172800  IN      NS      ns4.dnsv5.net.

# 因为NS域名ns3.dnsv5.com是请求域名dnsv5.com的子域名,此时胶水几率是必须返回的,否则后续继续向TLD服务器请求ns3.dnsv5.com还是返回上面两条NS记录,造成死循环
# 只返回tld相同的ns3.dnsv5.com的胶水记录,而不返回ns4.dnsv5.net的胶水记录
;; ADDITIONAL SECTION:
ns3.dnsv5.com.          172800  IN      A       1.12.0.17
ns3.dnsv5.com.          172800  IN      A       1.12.0.18
ns3.dnsv5.com.          172800  IN      A       1.12.14.17
ns3.dnsv5.com.          172800  IN      A       1.12.14.18
ns3.dnsv5.com.          172800  IN      A       101.227.168.52
ns3.dnsv5.com.          172800  IN      A       108.136.87.44
ns3.dnsv5.com.          172800  IN      A       163.177.5.75
ns3.dnsv5.com.          172800  IN      A       220.196.136.52
ns3.dnsv5.com.          172800  IN      AAAA    2402:4e00:1470:2::f
ns3.dnsv5.com.          172800  IN      A       35.165.107.227

;; Query time: 217 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Fri Aug 15 15:59:20 CST 2025
;; MSG SIZE  rcvd: 255
  • TLD服务器一般只有请求的域名的TLD和本域名设置的NS的TLD一致,会返回胶水记录的(这里大部分其实是非必须的,但是同时返回了胶水记录可以减少一次额外的请求,降低延迟),否则一般不返回胶水记录。如example.com设置NS为ns1.example.com, ns2.example.net, 那么这时候向TLD服务器请求example.com的时候,TLD服务器就会返回example.com的NS记录ns1.example.com和ns2.example.net,且同时返回ns1.example.com的A和AAAA记录(TLD相同,都是.com),但并不会返回ns2.example.net的胶水记录(TLD不同, .com vs .net),如上述和下述请求所示
dig @a.gtld-servers.net dnsov.net

; <<>> DiG 9.11.26-RedHat-9.11.26-6.tl3 <<>> @a.gtld-servers.net dnsov.net
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8363
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 11
;; WARNING: recursion requested but not available

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

;; AUTHORITY SECTION:
dnsov.net.              172800  IN      NS      ns3.dnsv5.com.
dnsov.net.              172800  IN      NS      ns4.dnsv5.net.

# 只返回tld相同的ns4.dnsv5.net的胶水记录,而不返回ns3.dnsv5.com的胶水记录,但其实这里的胶水记录并不是必须要返回的,因为dnsov.net和dnsv5.net是两个不同的域名,再次请求并不会造成死循环,但是同时返回了胶水记录可以减少一次额外的请求,降低延迟
;; ADDITIONAL SECTION:
ns4.dnsv5.net.          172800  IN      A       1.12.0.16
ns4.dnsv5.net.          172800  IN      A       1.12.0.19
ns4.dnsv5.net.          172800  IN      A       1.12.14.16
ns4.dnsv5.net.          172800  IN      A       1.12.14.19
ns4.dnsv5.net.          172800  IN      A       112.80.181.106
ns4.dnsv5.net.          172800  IN      A       117.135.128.152
ns4.dnsv5.net.          172800  IN      A       124.64.205.152
ns4.dnsv5.net.          172800  IN      A       13.37.58.163
ns4.dnsv5.net.          172800  IN      AAAA    2402:4e00:111:fff::8
ns4.dnsv5.net.          172800  IN      A       49.7.107.152

;; Query time: 192 msec
;; SERVER: 192.5.6.30#53(192.5.6.30)
;; WHEN: Fri Aug 15 16:00:30 CST 2025
;; MSG SIZE  rcvd: 261
  • 这里未介绍子域名授权场景的胶水记录,总体原则是一致的。

2.2.2 NS域名本身权威服务器返回的IP记录

NS域名(如ns3.dnsv5.com)在其权威DNS(如腾讯云解析/DNSPod)设置解析记录的时候,和普通域名可以一样设置智能解析(如境内设置一批IP,境外设置另一批IP等),和普通域名的使用没有区别。

2.2.3 递归DNS的行为及优化

递归DNS在进行迭代查询时,有可能从TLD服务器直接获取到NS域名的胶水记录,也可能从权威DNS获取,且两处获取的记录可能不同(部分检测系统会告警,但忽略即可),而权威DNS设置的IP支持智能解析,提供了更大的优化空间,一般相比胶水记录是更好的选择(且非专业技术人员常常忽视对胶水记录的维护),那递归DNS如何使用和优化呢。

常规的递归DNS(如BIND和UNBOUND)一般是这种行为(会略有不同,总体行为类似)

  • 如果向TLD服务器请求某个域名时,TLD服务器同时返回了NS的胶水记录,那么直接使用胶水记录作为NS的IP,不会再去向NS的权威请求记录
  • 如果向TLD服务器请求某个域名时,TLD服务器没有返回NS的胶水记录,则再去正常查询NS域名的记录时,可能回会权威请求NS记录,获取到权威可能设置的分线路智能解析结果,从而后续优先使用权威返回的解析记录
  • 有用户向递归DNS显示请求NS域名的A/AAAA记录,那么递归DNS必然会向NS域名的权威请求一次NS的A/AAAA记录(胶水记录不是其域名权威返回的,用户显式的请求去需要去获取权威设置的记录,而不能直接返回缓存的胶水记录),获取到权威可能设置的分线路智能解析结果,从而后续优先使用权威返回的解析记录
  • 如果权威返回的解析记录全部不可用,则重新回退到使用胶水记录提升可用性

可以看出来,常规的递归DNS不会主动去获取权威DNS的分线路智能解析结果,只会在被动获取到权威返回结果的时候,代替胶水记录进行优先使用,从腾讯云解析/DNSPod使用的实际效果看,权威解析才会设置的解析IP的流量比例总体并不低,这样设置还是有比较好的效果的(具体数据就不提供了)。

那对递归DNS能不能更进一步的进行优化呢,当然可以

  • 即使递归DNS从TLD服务器获取到了NS域名的胶水记录,在正常向胶水记录IP发起查询请求的同时,也自动异步去解析NS域名在权威的A/AAAA记录, 使用NS权威解析记录的比例可以大幅提高。
    • 根域名、TLD域名以及海外大厂的NS等域名不必做这个操作,因为记录一般都是一致的Anycast IP
    • 腾讯云/DNSPod所有对外提供服务的公共DNS、HTTPDNS、DoH、DoT、云内网DNS等的后端递归DNS都支持该项优化

2024年某些”小众”递归DNS那些事儿

本文就不写运营商递归DNS和相对比较知名一些的公共DNS了,通过几个case聊聊2024年当前可以应答DNS请求、在国内用户量不小,但是又搜索不到什么公开信息的一些”小众“递归DNS的那些事儿,部分已经无法访问的递归DNS就不再包含进来了。这些递归DNS的用户体量并不比不少知名公共DNS小,只是基本不为人知,关注该领域的可以大概了解下。

使用这些DNS比较容易出现解析线路不准确(如国内用户解析到国外IP)、域名被劫持等场景,因为让所有用户修改DNS并不现实,一般还是更建议有端的客户端(如APP等)尽量使用HttpDNS或其他技术手段规避类似场景。

【注1】本文部分线索来自其他伙伴。

【注2】本文所有数据为简单测试,仅供参考。

case 1:183.2.x.x

该DNS疑似某供应商为园区、公司等场景提供的递归DNS,在本省的使用率不低。在24年5月的时候测试,使用该DNS会大概率将域名解析到国外的IP,会导致终端用户访问延迟升高,也造成该省份域名解析到国外IP的概率略微高于其他省份。但是在24年下半年测试没什么大的问题了,可以正常解析为本省份结果,只是解析结果没有区分运营商,基本不影响正常使用。

下图分别为24年5月和12月的测试递归DNS出口IP的结果对比

case 2:45.14.x.x、45.128.x.x

该组递归DNS分布于多个C段,多个海外其他国家,目前看国内各省份运营商皆有固网/wifi用户访问,设置比例大约在小万分之x,使用移动网络则不会访问该组递归DNS,疑似从2024.12.04 16:00+开始对外提供DNS解析服务。

该组递归DNS后端在进行递归请求时固定携带127.0.0.1作为ECS IP,大部分域名可以解析到默认线路,无省份运营商区分,解析到国外IP的概率倒是不高。

该组DNS貌似会随机劫持某些域名到其他IP,并302跳转到其他违规网站。历史测试截图如下。

注3】截止本文时间(2024.12.18),之前历史被劫持域名已经没有被劫持,且之前被劫持到的相关IP也已经无法访问,疑似已经被处理。

case 3:154.86.x.x

该组递归DNS分布于多个C段,部署于中国香港,目前看国内各省份运营商皆有固网/wifi用户访问,设置比例大约在小千分之x,使用移动网络则不会访问该组递归DNS,具体对外提供服务时间则不确定。

该组递归DNS后端在进行递归请求时会随机转发给国内外多个其他公共DNS,且并未携带ecs,大部分域名的解析结果IP为国外IP,会导致终端用户访问延迟升高,递归DNS后端出口IP测试结果如下所示,其中包括Google、UltraDNS等其他的公共DNS的递归出口IP

该组DNS因为是纯转发,所以部分特征会测试到转发目标公共DNS的特征,如NeuStar家的UltraDNS,但实际并非该集群本身的版本特征,也并非转发目标公共DNS部署的DNS缓存转发服务,部分特征测试结果如下所示:

dig version.bind chaos txt @154.86.x.x +short
“1733297354.ultradns”
dig hostname.bind chaos txt @154.86.x.x +short
“rcrsv2.jptyo1.ultradns”

dig version.bind chaos txt @154.86.x.x
version.bind. 86400 CH TXT “PowerDNS Recursor 5.1.1 (built Jul 22 2024 13:49:14 by root@localhost)”

dig version.bind chaos txt @154.86.x.x +short
version.bind. 75428 CH TXT “Q9-P-7.6”

该组DNS貌似会随机劫持某些过期域名到其他IP,并302跳转到其他网站(有点类似纠错页),当前(2024.12.18)跳转的目标网站实测无法访问,也未找到历史网页内容,且很多安全情报都会报告风险并进行访问拦截,没有什么实质性的影响。

DNS 解析中的搜索引擎线路那些事儿

本文不会贴出任何搜索引擎蜘蛛实际的测试数据,仅作理论分析,感兴趣的同学可以根据一些公开的第三方工具和文章中提到的一些技术方案自行分析。

首先简单介绍下 DNS 解析中搜索引擎线路的作用,当代权威 DNS 的基本功能都包括分线路解析(也有智能解析、view、geo 等等名字) ,其中很多权威 DNS 服务商会提供针对搜索引擎蜘蛛抓取的线路(包括搜索引擎线路、SEO 优化、搜索引擎回源等等名字),主要目的是对普通用户返回 CDN 或其他通用的地址,而准对搜索引擎蜘蛛的抓取则直接返回源站的地址,可以提高权重、收录等目的。

搜索引擎蜘蛛在抓取网页前,首先要进行域名解析,获取目标域名的 IP 地址之后再进行抓取,此处需要涉及到蜘蛛使用的 LocalDNS 和目标域名使用的权威 DNS 两个部分的解析过程,首先介绍权威 DNS 解析过程。

权威 DNS 解析过程

权威 DNS 主要是依靠 LocalDNS 发送的 DNS 请求中的 IP 地址来进行分线路的解析的,而携带 IP 地址主要有两个位置,分别进行说明。

DNS 请求源地址

一个标准的 DNS 请求不管是 UDP 还是 TCP 协议,都必然要有其源 IP 地址,权威 DNS 服务器可以通过获取该地址来查询 IP 库和线路设置情况来进行分线路解析。

edns_client_subnet(ECS) 选项中携带 IP 地址

DNS 扩展协议中的 ECS 段可以在 DNS 请求包额外携带 IP 地址来供权威 DNS 获取并依此进行分线路解析,主要用于提升节点分布于全球的公共 DNS 来提升解析准确度,但是 ECS 的现状是大量权威 DNS 已经实现了对 ECS 的支持,但是 LocalDNS 对 ECS 的支持情况则很不乐观,除了 Google Public DNS 和 OpenDNS 有相对比较完整的支持外,其他包括运营商 DNS 和大部分其他公共 DNS 并没有很完整的支持 ECS 协议(ECS 协议支持情况可以参考之前的一篇文章《国内主要公共 DNS 支持 ECS 情况测试 – 20210315》)。

当然可知目前绝大部分的搜索引擎蜘蛛使用的 LocalDNS 也都是不支持 ECS 协议的,而权威 DNS 要正确解析蜘蛛访问的域名的线路主要就依赖蜘蛛使用的 LocalDNS 本身的外网出口 IP 来判断。下面再讨论蜘蛛使用的 LocalDNS 几种不同的场景。

蜘蛛使用的 LocalDNS

蜘蛛使用的 DNS 可能分为几种情况:

1. 使用蜘蛛独占的网段搭建 LocalDNS 进行解析

这种情况是对权威 DNS 的搜索引擎线路最友好的方式,该网段为蜘蛛独占,不与其他业务混用,尤其是公共DNS,目标域名的权威 DNS 只需要定期收集更新其蜘蛛使用的 LocalDNS 的外网出口 IP 即可达到很好的优化效果。

如果蜘蛛 IP 和 LocalDNS 的外网出口 IP 地址位于相同网段,通过搜索引擎官网公布或第三方收集的蜘蛛 IP、蜘蛛的 UA、IP 段的反解析结果等收集、验证、更新蜘蛛 IP 段即可。

如果 LocalDNS 的外网出口 IP 地址与蜘蛛 IP 位于不同网段,但是只要该网段依然是蜘蛛独占,可以通过一些技术手段来收集这些 LocalDNS 的外网出口 IP,如向 LocalDNS 请求 whoami.ip.dnspod.net,则返回结果即为该 LocalDNS 的外网出口 IP,如果 LocalDNS 支持 ECS,则会同时返回 LocalDNS 请求的源 IP 和携带的 ECS IP。

类似可以检测 LocalDNS 的外网出口 IP 的域名现网有多家大厂都有提供,仅返回结果的展示方式不一致。

但是想想就知道,蜘蛛全部独占相关的网段的可能性有多低,现网的相关测试数据也完全证明蜘蛛使用的网段大部分是也有其他业务在使用, 其实大部分其他业务复用蜘蛛 IP 段不会对搜索引擎线路优化有什么影响 ,除了公共 DNS。

2. 蜘蛛 LocalDNS 的外网出口 IP 网段和公共 DNS 网段重合

这种场景对同时提供搜索引擎服务和公共 DNS 服务的厂商是非常常见的,此处也不再进行举例说明,仅说明存在的问题。

目前从各种渠道获取到的蜘蛛 IP(包括其使用的 LocalDNS 外网出口 IP)在 IPv4(IPv6 本文不额外讨论) 中一般精度可达到 C 段 IP(/24),非常难达到非常准确的 /32 精度,这就导致权威 DNS 无法区分来访问的 IP 到底是蜘蛛来访问的还是普通用户使用公共 DNS 来访问的,从而无法给双方都解析到准确的结果,只能折衷选取一种策略。

举例说明,目前腾讯云 DNSPod 的解析策略是对此类 IP 不添加到蜘蛛 IP 库中,结果是蜘蛛很大概率无法获取搜索引擎线路设置的特定结果,但是也不会造成普通用户错误的获取到蜘蛛线路的解析结果,尤其是在其公共 DNS 服务的普通用户体量巨大的时候。

3. 直接使用公共 DNS 进行解析

公开的 LocalDNS 包括运营商 DNS 和其他公共 DNS,因为运营商 DNS 大多有源 IP 段必须为本运营商的限制,对于可能分布于各地的蜘蛛来说不是很好的选择,公共 DNS 则可以作为主要选择。

蜘蛛可以直接使用这些公共 DNS 进行解析或者自建的缓存 LocalDNS 本身不进行递归查询,只是将解析请求转发至公共 DNS 并缓存解析结果。

此类场景在蜘蛛中也是比较常见的,因为可以节省大量的 LocalDNS 的部署维护成本,导致的结果和策略选择也与第二种场景一致。

解决方案

如果想让权威 DNS 的搜索引擎线路更有效,解决目前存在的问题,可以考虑 2 种方案,但是都存在相同的问题,虽然理论上是有一定的可操作性的,但是实际中确较难达成,主要维护成本或资源成本,且依赖搜索引擎的部署策略,与权威 DNS 不是一家的^_^。

  1. 蜘蛛及其 LocalDNS 使用 IP 段不要与公共 DNS 复用
  2. 蜘蛛使用支持完整 ECS 的递归 DNS

方案 1 主要针对蜘蛛自建 LocalDNS ,实施难度本身不大,主要是在部署自己的 LocalDNS 时能够和公共 DNS 隔离即可,需要更多的IP段资源,且在后续变更时需要注意一直维护该策略不变才可。

方案 2 主要针对直接使用或者转发到公共 DNS 的蜘蛛,因为完整的 ECS 在 LocalDNS 中对域名的解析结果会按照网段进行缓存,即使蜘蛛与普通用户复用相同 DNS 也不会造成很大的影响,仅对蜘蛛 IP 同网段的其他业务可能产生一定的影响,范围非常有限,不会影响到大量的普通用户的访问。

此方案存在的问题主要是公共 DNS 支持完整 ECS 的少之又少,尤其是在国内短期内不一定会有长期持续而稳定支持完整 ECS 的公共 DNS,而 Google Public DNS 和 OpenDNS 则对国内使用者非常不友好,可操作性不如方案 1。


IOS14对使用8.8.8.8进行DNS(CDN)调度的影响

2023-12-21更新:虽然8.8.8.8对MX、CAA以及其他类型等依然不支持ecs(符合RFC标准),但是在cname链中已经不会对A/AAAA等其他记录类型造成影响,看上去像是单独处理了,已经修复了该问题。

但是依然存在ecs失效的可能,比如8.8.8.8的递归到权威的请求偶发超时、请求权威跨国且请求了同权威IP被污染的域名等场景,依然可能造成递归判断权威的IP不支持ecs,导致后续一段时间内的ecs失效,暂无太好的办法。


2021-04-02 更新: Google 公共 DNS 已经对 HTTPS 和 SVCB 支持了 ECS,其他类型正在评估,测试正常。


2021-03-26 更新:标准化组织正在对该问题进行讨论,大体方案可能为:

  1. 如果递归 DNS 准备解析 HTTPS 记录指向的域名,并且在返回给客户端的应答附加段中添加 A/AAAA 记录,则递归在向权威请求HTTPS 记录时应携带 /0,表示递归支持 ECS,但对 HTTPS 记录类型禁用,此时权威在响应时不能在附加段中添加相关 A/AAAA 记录,以便递归 DNS 携带正常的 ECS 进行 A/AAAA 记录的请求。
  2. 如果递归 DNS 不准备执行上面的方案,则递归在向权威进行 HTTPS 类型的请求时应携带与请求 A/AAAA 类型相同的 ECS。

方案1实现较复杂,递归 DNS 需要对 HTTPS 记录类型进行单独处理,此处也要注意 HTTPS 记录类型也包括对应的 CNAME,但是可以减轻缓存压力;方案2简单粗暴,对应增加的就是递归 DNS 的缓存压力。

具体信息可以参考: https://issuetracker.google.com/issues/181593657https://github.com/MikeBishop/dns-alt-svc/pull/308


我们一直的观点是在国内不要使用 Google 的公共 DNS(8.8.8.8),这里再从技术层面讨论下 IOS 14 更新后使用 8.8.8.8 进行 DNS 解析对 CDN 调度的影响。

结论

  1. 在国内任意地区都不应该系统上直接设置或转发到 8.8.8.8 进行 DNS 解析,这个结论依然有效。
  2. IOS 14 更新后会对域名自动发出 TYPE HTTPS (TYPE65) 类型的请求,这会导致 8.8.8.8 对于包含 CNAME 记录的解析结果 ECS 判断失效的情况极大增多,调度不准确的情况会远多于 IOS 14 更新之前,CDN 调度受影响比较严重。
  3. 仅限于当前时间(2021.03.04)有效,如果后续相关 DNS 请求行为有变化,则结论可能不再准确。

解析过程

公共 DNS 的解析准确度一般是通过在尽量多的地区和运营商部署递归节点,以及是通过 ECS (EDNS Client Subnet,常简称为 EDNS) 技术来提示解析准确度,最主要的使用场景就是 CDN 的调度,所以一旦 ECS 失效,对 CDN 调度的影响也是最大的。

虽然任何 DNS 都不能保证完全解析准确,但是此前 8.8.8.8 做的还是不错的,但是从 20 年 IOS 14 更新后,解析准确度每况愈下,尤其是对部分使用 CDN 进行调度的域名影响较大,经常发生国内解析到国外、不同地区使用多家 CDN 时解析结果不符合预期等问题,下面分析下 IOS 14 对该现象的具体影响过程。

假设在权威 DNS 上对typehttps.example.com配置以下记录, 并且权威 DNS 对 ECS 的支持正确,8.8.8.8 的自动检测也可以正确检测到权威 DNS 是支持 ECS 的。

typehttps   默认  600 CNAME   test1.example.com.
typehttps   境外 600 CNAME   test2.example.com.
test1       默认 600 A       8.8.8.8
test2       默认 600 A       8.8.4.4

当我们从国内向 8.8.8.8 请求 typehttps.example.com或携带国内IP(如 119.29.0.0/24)的 ECS IP 时,正常过程是这样的,

dig @8.8.8.8 typehttps.example.com +subnet=119.29.0.0/24

正常的结果应该是类似这样的,因为权威 DNS 是根据 8.8.8.8 请求时携带的119.29.0.0/24进行解析的,

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; CLIENT-SUBNET: 119.29.0.0/24/24
;; QUESTION SECTION:
;typehttps.example.com.           IN     A

;; ANSWER SECTION:
typehttps.example.com. 550 IN CNAME   test1.example.com.
test1.example.com       600 IN A       8.8.8.8

但是现在你有很大概率拿到会是以下的错误结果,

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; CLIENT-SUBNET: 119.29.0.0/24/24
;; QUESTION SECTION:
;typehttps.example.com.           IN     A

;; ANSWER SECTION:
typehttps.example.com. 590 IN CNAME   test2.example.com.
test1.example.com       600 IN A       8.8.4.4

解析到了境外的 CNAME 及其 IP,以前虽然也可能出现这种解析错误的情况,但是相对少很多,那是什么原因呢,此时如果我们指定请求 CNAME 类型再来看下有什么区别,

dig @8.8.8.8 typehttps.example.com +subnet=119.29.0.0/24 CNAME
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; CLIENT-SUBNET: 119.29.0.0/24/0
;; QUESTION SECTION:
;typehttps.example.com.           IN     CNAME

;; ANSWER SECTION:
typehttps.example.com. 590 IN CNAME   test2.example.com.

此时可以看到 ECS 段中的 scope 为 0,这就表示 8.8.8.8 的缓存中将境外线路的 CNAME 记录作为全局结果缓存了,那为什么会出现这种错误的解析和缓存结果呢?

通过抓包分析可以发现,8.8.8.8 对权威 DNS 发起的查询请求中,即使权威是支持 ECS 的,8.8.8.8 也并不会对所有类型的请求记录携带 ECS 段,大部分常见的请求类型,如 A 记录(IPv4)、AAAA 记录(IPv6)、CNAME 记录等并不会出现问题,但是有部分请求类型则不会携带 ECS 进行请求,而这其中有部分类型可能会返回 CNAME 记录,比如 MX 、CAA 以及 HTTPS 类型,权威 DNS 就会按照 8.8.8.8 的递归 DNS 的 IP 所在地返回境外线路的 CNAME 记录,而后 8.8.8.8 就会按照全局 /0 的 scope 缓存该 CNAME。

所以这里就破案了,具体过程是如下两图所示,

A 记录请求过程
HTTPS 记录请求过程
  1. IOS14 升级后会支持 TYPE HTTPS 的记录类型,解析一个域名时应同时请求 A/AAAA/HTTPS 记录类型。
  2. 则 A 和 AAAA 记录可以正常获得境内的 CNAME 和 IP 并正常按照 119.29.0.0/24 的 IP 段缓存,但该缓存仅对该 IP 段有效.
  3. HTTPS 类型的返回的错误 CNAME 结果就会因为上述原因作为全局 /0 的缓存。
  4. 后续所有非119.29.0.0/24网段 请求都会命中全局缓存的错误 CNAME 记录,然后再对 CNAME 记录进行正常的递归查询,客户端最后拿到的就是错误的境外结果。
  5. 虽然 MX 、CAA、HTTPS 类型都会造成此问题,但是在实际的网络环境中,普通域名的 MX 和 CAA 记录类型都是很少被请求到的,所以 8.8.8.8 虽然一直存在类似的问题,但是并不严重。直到 IOS14 更新后, HTTPS 记录类型默认被请求,该问题就变得比较严重了。

影响范围

对不同地区设置了不同 CNAME 记录的域名会有较大影响,一般常见于 CDN,所以对 CDN 影响比较大,具体分析话大概是这样的,

  1. 如果境内和境外使用了不同的 CNAME 记录,如国内使用国内的 CDN,国外使用国外的 CDN,则国内使用 8.8.8.8 会大概率解析到国外线路的 CNAME,很可能解析到国外节点影响访问体验。
  2. 如果未设置其他国家、大洲、境外等线路,只是不同省份运营商使用不同的 CNAME 记录进行负载均衡,则国内使用 8.8.8.8 会大概率会解析到默认线路上,虽然会造成负载均衡效果不符合预期,但在客户端的访问体验上总体影响不大。
  3. 对境外用户影响有限,因为虽然也存在一样的 ECS 失效问题,但根据递归 DNS IP 获取到的 CNAME 结果范围不会差距很大。

规避方法

  1. 在国内避免使用 8.8.8.8,当然这里有部分运营商已经帮忙搞定这一步了,移动端则可以考虑使用 HTTPDNS 等技术手段规避。
  2. 如果条件允许,不同地区应使用相同的 CNAME,如果必须使用不同的CNAME,则需要关注默认和境外相关线路的容量等问题,如境外线路的 CDN 能提供境内 CDN 节点则可以很大的缓解该问题。

其他公共DNS

  1. OpenDNS 208.67.222.222 仅 CAA 记录可能存在此问题;腾讯云/DNSPod 119.29.29.29,各请求类型均不受影响;阿里云 223.5.5.5 不受影响。
  2. 1.1.1.1、9.9.9.9、180.76.76.76、114.114.114.114,默认未支持 ECS ,仅能通过后端递归节点的部署进行调度,不涉及该问题。

参考资料

draft-ietf-dnsop-svcb-httpssvc-03.