解析一个域名,其实是沿着 根 → 顶级域 → 权威服务器 这条链一路问下去。这篇自己扮演递归解析器,不借助任何缓存,从根服务器开始一问一问地迭代,看每一层给的是什么,再和直接问 1.1.1.1 对比。过程中我意外发现,这台机器所在网络里有些域名的应答被抢先伪造了。
第 1 问:a.root-servers.net 242.6 ms 转介到 com.:授权区 13 个 NS,附加区带 6 个 IPv4 胶水地址
第 2 问:l.gtld-servers.net. 251.6 ms 转介到 example.com.:授权区 2 个 NS,附加区带 6 个 IPv4 胶水地址
第 3 问:hera.ns.cloudflare.com. 287.5 ms 回答:1 条 A(AA)
共 3 问,总耗时 783 ms;最终 ['172.66.147.243', '104.20.23.154']
每一问只回答“我知道的最近一层”:根服务器不知道 example.com,但知道谁管 com.;com. 的服务器不知道地址,但知道谁管 example.com;最后一问才是权威服务器的 AA 回答根给 com. 的转介,com. 的服务器给 example.com 的转介,权威服务器给答案。每一问都是 RD=0。
RCODE NOERROR;标志 QR TC;问题 1,回答 0,授权 13,附加 11 条;489 字节 授权区(前 3 条):com. NS l.gtld-servers.net.;com. NS j.gtld-servers.net.;com. NS h.gtld-servers.net. …共 13 条 附加区(胶水记录):A 6 条、AAAA 5 条——有了它们才能不绕回头去查这些 NS 名字自己的地址 标志里没有 AA(根服务器对 example.com 不权威),也没有 RA(根服务器不做递归);回答区是空的
转介报文的授权区放 NS,附加区放这些 NS 的地址(胶水)。不用 EDNS0 时 UDP 响应上限 512 字节,会被截断(TC)。
example.com:
第 1 问:a.root-servers.net 234.3 ms 转介到 com.:授权区 13 个 NS,附加区带 6 个 IPv4 胶水地址
第 2 问:l.gtld-servers.net. 232.7 ms 转介到 example.com.:授权区 2 个 NS,附加区带 6 个 IPv4 胶水地址
第 3 问:hera.ns.cloudflare.com. 289.4 ms 回答:1 条 A(AA)
共 3 问,总耗时 757 ms;最终 ['172.66.147.243', '104.20.23.154']
iana.org:
第 1 问:a.root-servers.net 303.0 ms 转介到 org.:授权区 6 个 NS,附加区带 6 个 IPv4 胶水地址
第 2 问:a2.org.afilias-nst.info. 210.6 ms 转介到 iana.org.:授权区 4 个 NS,附加区带 1 个 IPv4 胶水地址
第 3 问:a.iana-servers.net. 193.9 ms 回答:1 条 A(AA)
共 3 问,总耗时 708 ms;最终 ['192.0.43.8']
www.bbc.co.uk:
第 1 问:a.root-servers.net 7.6 ms 回答:1 条 A(AA)
共 1 问,总耗时 8 ms;最终 ['199.59.148.206']
www.github.com:
第 1 问:a.root-servers.net 220.9 ms 转介到 com.:授权区 13 个 NS,附加区带 6 个 IPv4 胶水地址
第 2 问:l.gtld-servers.net. 268.4 ms 转介到 github.com.:授权区 8 个 NS,附加区带 1 个 IPv4 胶水地址
第 3 问:ns-520.awsdns-01.net. 178.2 ms 回答:1 条 A,1 条 CNAME(AA)
共 3 问,总耗时 668 ms;最终 ['20.205.243.166']
python.org:
第 1 问:a.root-servers.net 220.2 ms 转介到 org.:授权区 6 个 NS,附加区带 6 个 IPv4 胶水地址
第 2 问:a2.org.afilias-nst.info. 208.7 ms 转介到 python.org.:授权区 4 个 NS,附加区带 1 个 IPv4 胶水地址
第 3 问:ns-484.awsdns-60.com. 191.0 ms 回答:1 条 A(AA)
共 3 问,总耗时 620 ms;最终 ['151.101.192.223', '151.101.64.223', '151.101.0.223', '151.101.128.223']
汇总:example.com 3 问 757 ms;iana.org 3 问 708 ms;www.bbc.co.uk 1 问 8 ms;www.github.com 3 问 668 ms;python.org 3 问 620 ms常见名字 3 问;最后一问的权威服务器可能顺带把 CNAME 指向的 A 一起带回。
example.com:5 次往返(ms):[286, 284, 235, 294, 284];中位 284 ms www.bbc.co.uk:5 次往返(ms):[36, 42, 38, 48, 44];中位 42 ms www.github.com:5 次往返(ms):[286, 292, 301, 306, 230];中位 292 ms 对比自己迭代:example.com 757 ms,www.bbc.co.uk 8 ms,www.github.com 668 ms(本机到各服务器的往返都是公网,没有缓存)
交给 1.1.1.1 只发一个查询,耗时就是到它的往返。
a 252;b 227;c 171;d 240;e 280;f 7;g 248;h 111;i 122;j 7;l 8;m 126(单位 ms,各问 3 次取中位) 根服务器名字共 13 个;最快 j 7 ms,最慢 e 280 ms
13 个名字背后是很多台机器,本机到各个根的往返差了近 40 倍。
向 192.0.2.1 问 example.com:0 个响应 向 192.0.2.1 问 www.bbc.co.uk:0 个响应 向 192.0.2.1 问 www.facebook.com:0 个响应 向 198.41.0.4 问 www.bbc.co.uk:2 个响应;+6 ms 来自 198.41.0.4,47 字节,答案 ['157.240.11.40'],TTL [122],标志 QR RD RA;+6 ms 来自 198.41.0.4,47 字节,答案 ['199.59.148.209'],TTL [75],标志 QR RD RA 192.0.2.1 是预留给文档的地址,不会有任何真实的 DNS 服务;如果它“回答”了,说明响应是路径上的某个设备伪造的。结论只限于“这台机器所在的网络路径”,不涉及别的网络
向根服务器问 www.bbc.co.uk,6 ms 内收到两个互相矛盾、带 RA 的答案——不是根能给出的。明文 DNS 无法分辨真假。