![dig +trace 总是准确的吗?](https://linux22.com/image/606985/dig%20%2Btrace%20%E6%80%BB%E6%98%AF%E5%87%86%E7%A1%AE%E7%9A%84%E5%90%97%EF%BC%9F.png)
当 DNS 缓存的准确性受到质疑时,dig +trace
往往是确定面向互联网的 DNS 记录的权威答案的推荐方法。当与 搭配使用时,这似乎特别有用+additional
,后者还显示了粘合记录。
有时似乎对这一点存在一些分歧——有些人说它依赖于本地解析器来查找中间名称服务器的 IP 地址,但命令输出没有表明这种情况发生在初始根名称服务器列表之外。如果目的是从根服务器开始并向下追踪,那么假设情况并非如此似乎是合乎逻辑的。+trace
(至少如果您有正确的根名称服务器列表)
是否dig +trace
真的使用本地解析器来处理根名称服务器之外的任何事务?
答案1
这显然是一场有预谋的问答,但是这往往会让人感到困惑我找不到涵盖该主题的规范问题。
dig +trace
是一个很好的诊断工具,但其设计的一个方面被广泛误解:每个要查询的服务器的 IP 都是从解析器库中获取的。这很容易被忽视,而且通常只有在本地缓存有错误的回答名称服务器缓存的问题。
详细分析
使用输出样本来分解这一点会更容易;我将省略第一个 NS 委派之后的所有内容。
; <<>> DiG 9.7.3 <<>> +trace +additional serverfault.com
;; global options: +cmd
. 121459 IN NS d.root-servers.net.
. 121459 IN NS e.root-servers.net.
. 121459 IN NS f.root-servers.net.
. 121459 IN NS g.root-servers.net.
. 121459 IN NS h.root-servers.net.
. 121459 IN NS i.root-servers.net.
. 121459 IN NS j.root-servers.net.
. 121459 IN NS k.root-servers.net.
. 121459 IN NS l.root-servers.net.
. 121459 IN NS m.root-servers.net.
. 121459 IN NS a.root-servers.net.
. 121459 IN NS b.root-servers.net.
. 121459 IN NS c.root-servers.net.
e.root-servers.net. 354907 IN A 192.203.230.10
f.root-servers.net. 100300 IN A 192.5.5.241
f.root-servers.net. 123073 IN AAAA 2001:500:2f::f
g.root-servers.net. 354527 IN A 192.112.36.4
h.root-servers.net. 354295 IN A 128.63.2.53
h.root-servers.net. 108245 IN AAAA 2001:500:1::803f:235
i.root-servers.net. 355208 IN A 192.36.148.17
i.root-servers.net. 542090 IN AAAA 2001:7fe::53
j.root-servers.net. 354526 IN A 192.58.128.30
j.root-servers.net. 488036 IN AAAA 2001:503:c27::2:30
k.root-servers.net. 354968 IN A 193.0.14.129
k.root-servers.net. 431621 IN AAAA 2001:7fd::1
l.root-servers.net. 354295 IN A 199.7.83.42
;; Received 496 bytes from 75.75.75.75#53(75.75.75.75) in 10 ms
com. 172800 IN NS m.gtld-servers.net.
com. 172800 IN NS k.gtld-servers.net.
com. 172800 IN NS f.gtld-servers.net.
com. 172800 IN NS g.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
com. 172800 IN NS e.gtld-servers.net.
com. 172800 IN NS j.gtld-servers.net.
com. 172800 IN NS c.gtld-servers.net.
com. 172800 IN NS l.gtld-servers.net.
com. 172800 IN NS d.gtld-servers.net.
com. 172800 IN NS i.gtld-servers.net.
com. 172800 IN NS h.gtld-servers.net.
com. 172800 IN NS a.gtld-servers.net.
a.gtld-servers.net. 172800 IN A 192.5.6.30
a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
b.gtld-servers.net. 172800 IN A 192.33.14.30
b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
c.gtld-servers.net. 172800 IN A 192.26.92.30
d.gtld-servers.net. 172800 IN A 192.31.80.30
e.gtld-servers.net. 172800 IN A 192.12.94.30
f.gtld-servers.net. 172800 IN A 192.35.51.30
g.gtld-servers.net. 172800 IN A 192.42.93.30
h.gtld-servers.net. 172800 IN A 192.54.112.30
i.gtld-servers.net. 172800 IN A 192.43.172.30
j.gtld-servers.net. 172800 IN A 192.48.79.30
k.gtld-servers.net. 172800 IN A 192.52.178.30
l.gtld-servers.net. 172800 IN A 192.41.162.30
;; Received 505 bytes from 192.203.230.10#53(e.root-servers.net) in 13 ms
- (根名称服务器)的初始查询
. IN NS
命中本地解析器,在本例中为康卡斯特。(75.75.75.75
)这很容易发现。 - 下一个查询针对的是
serverfault.com. IN A
,它e.root-servers.net.
是从我们刚刚获得的根名称服务器列表中随机选择的。它的 IP 地址为192.203.230.10
,并且由于我们已+additional
启用它出现来自胶水。 - 由于它对 serverfault.com 没有权威性,因此将其委托给
com.
TLD 名称服务器。 - 从这里的输出中不明显的是没有从胶水中
dig
得出 IP 地址。e.root-servers.net.
在幕后,真正发生的事情是这样的:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
02:03:43.301022 IP 192.0.2.1.59900 > 75.75.75.75.53: 63418 NS? . (17)
02:03:43.327327 IP 75.75.75.75.53 > 192.0.2.1.59900: 63418 13/0/14 NS k.root-servers.net., NS l.root-servers.net., NS m.root-servers.net., NS a.root-servers.net., NS b.root-servers.net., NS c.root-servers.net., NS d.root-servers.net., NS e.root-servers.net., NS f.root-servers.net., NS g.root-servers.net., NS h.root-servers.net., NS i.root-servers.net., NS j.root-servers.net. (512)
02:03:43.333047 IP 192.0.2.1.33120 > 75.75.75.75.53: 41110+ A? e.root-servers.net. (36)
02:03:43.333096 IP 192.0.2.1.33120 > 75.75.75.75.53: 5696+ AAAA? e.root-servers.net. (36)
02:03:43.344301 IP 75.75.75.75.53 > 192.0.2.1.33120: 41110 1/0/0 A 192.203.230.10 (52)
02:03:43.344348 IP 75.75.75.75.53 > 192.0.2.1.33120: 5696 0/1/0 (96)
02:03:43.344723 IP 192.0.2.1.37085 > 192.203.230.10.53: 28583 A? serverfault.com. (33)
02:03:43.423299 IP 192.203.230.10.53 > 192.0.2.1.37085: 28583- 0/13/14 (493)
+trace
作弊并咨询本地解析器以获取下一跳名称服务器的 IP 地址,而不是咨询胶水。鬼鬼祟祟!
这通常“足够好”,不会对大多数人造成问题。不幸的是,存在极端情况。如果出于某种原因,您的上游 DNS 缓存为名称服务器提供了错误的答案,则此模型将完全失效。
真实世界的例子:
- 域名过期
- glue 重新指向注册商重定向域名服务器
- ns1 和 ns2.yourdomain.com 缓存了虚假 IP
- 域名已使用恢复的胶水更新
- 任何含有虚假域名服务器 IP 的缓存都会继续将人们引导至声称该域名正在出售的网站
在上述情况下,+trace
将表明域所有者自己的名称服务器是问题的根源,并且您差点就错误地告诉客户他们的服务器配置错误。您是否可以(或是否愿意)采取措施解决此问题又是另一回事,但掌握正确的信息非常重要。
dig +trace
是一个很棒的工具,但是像任何工具一样,您需要知道它能做什么和不能做什么,以及当它无法满足需求时如何手动解决问题。
编辑:
还应注意,dig +trace
不会就NS
指向别名的记录向您发出警告CNAME
。这是 RFC 违规行为,ISC BIND(可能还有其他)不会尝试纠正。+trace
将完全乐意接受A
从您本地配置的名称服务器获取的记录,而如果 BIND 要执行完全递归,它将使用 SERVFAIL 拒绝整个区域。
如果有胶水存在,这可能很难排除故障;但这种方法很好用直到 NS 记录刷新,然后突然破裂。没有凝聚力的代表团将总是NS
当记录指向别名时中断 BIND 的递归。
答案2
另一种跟踪 DNS 解析的方法是使用本地解析器,除了查找根名称服务器之外,无需使用本地解析器域名系统(完全披露:这是我写的)。它有一个命令行工具和一个 Web 版本,您可以在以下位置找到一个实例http://ip.seveas.net/dnsgraph/
以 serverfault.com 为例,它现在确实存在 DNS 问题:
答案3
很晚才加入这个帖子,但我认为关于为什么 dig +trace 使用递归查询本地解析器的问题部分还没有直接解释,而这个解释与 dig +trace 结果的准确性有关。
在对根区域的 NS 记录进行初始递归查询之后,dig 可以在以下条件下向本地解析器发出后续查询:
由于响应大小超过 512 字节,因此对于下一个迭代查询,引用响应被截断
dig 从引荐响应的 AUTHORITY 部分中选择一条 NS 记录,而该记录的 ADDITIONAL 部分中缺少相应的 A 记录(glue)
由于 dig 仅从 NS 记录中获取域名,因此 dig 必须通过查询本地 DNS 服务器将该名称解析为 IP 地址。这就是根本原因(双关语,抱歉)。
AndrewB 举了一个例子,它与我刚才描述的并不完全一致,即所选的根区域 NS 记录:
. 121459 IN NS e.root-servers.net.
有相应的 A 记录:
e.root-servers.net. 354907 IN A 192.203.230.10
但请注意,e-root 没有相应的 AAAA 记录,并且其他一些根服务器也没有 AAAA 记录。
另请注意响应的大小:
;; Received 496 bytes from 75.75.75.75#53(75.75.75.75) in 10 ms
496 字节是被截断的响应的常见大小(即下一个胶水记录将大于 16 字节,使响应超过 512 字节)。换句话说,在对根的 NS 记录的查询中,完整的 AUTHORITY 和完整的 ADDITIONAL(A 和 AAAA 记录)将超过 512 字节,因此任何未通过 EDNS0 选项指定更大查询大小的基于 UDP 的查询都将获得在 ADDITIONAL 部分某处被截断的响应,如上面的跟踪所示(只有 f、h、i、j 和 k 具有 A 和 AAAA 胶水记录)。
e.root-servers.net 缺少 AAAA 记录,并且对“NS .”查询的响应大小强烈表明,下一个递归查询是出于我声称的原因而进行的。也许客户端操作系统支持 IPv6,并且更喜欢 AAAA 记录——或者其他原因。
但无论如何,在阅读此帖子后,我研究了 dig +trace 在对 root 执行初始查询后执行递归查询的现象。根据我的经验,选择没有相应胶水 A/AAAA 记录的 NS 记录和 dig 然后将针对该记录的递归查询发送到本地 DNS 之间的对应关系是 100%。反之亦然——当从引用中选择的 NS 记录具有相应的胶水记录时,我还没有看到递归查询。