假设我想要查找某个域的 A 和 AAAA 记录,例如:google.com
我可以用host
:
$ host google.com
google.com has address 172.217.169.46
google.com has IPv6 address 2a00:1450:4009:801::200e
google.com mail is handled by 20 alt1.aspmx.l.google.com.
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
google.com mail is handled by 10 aspmx.l.google.com.
但这显然没有列出所有内容,因为如果我直接查询名称服务器,我会得到不同的答案:
$ host google.com ns2.google.com
Using domain server:
Name: ns2.google.com
Address: 216.239.34.10#53
Aliases:
google.com has address 216.58.205.46
google.com has IPv6 address 2a00:1450:4009:808::200e
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 10 aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
google.com mail is handled by 20 alt1.aspmx.l.google.com.
结果甚至似乎因查询而异...所以我推断一定发生了一些事情,DNS 服务器并没有告诉我们全部情况。
从另一个角度来看,如果你去像 robtex.com 这样的网站查看域名,你会发现我的查询没有返回一长串 IP:
https://www.robtex.com/dns-lookup/google.com#records
目前列出了这一长串的 IP 号码:
2404:6800:4003:c02::8b
2404:6800:4004:807::200e
2404:6800:4006:803::200e
2607:f8b0:4004:811::200e
2607:f8b0:4005:802::200e
2607:f8b0:4005:808::200e
2607:f8b0:400a:809::200e
2800:3f0:4001:803::200e
2a00:1450:400b:805::200e
74.125.68.100
74.125.68.101
74.125.68.102
74.125.68.113
74.125.68.138
74.125.68.139
172.217.0.46
172.217.5.110
172.217.15.110
172.217.27.78
172.217.29.14
172.217.171.14
216.58.194.174
216.58.199.46
如果正确的话,则表明我所得到的答案host
仅暗示了真实情况。
如何才能得到完整且权威的答案?
答案1
从客户端来看,您可能永远无法获得完整的情况,因为许多 DNS 端点都在使用 GeoDNS 和其他基于地理位置的负载平衡。
但是,假设您可以访问分布在全球的客户端,则可以使用 GNU dig 来实现这一点。
首先,您需要找到要查询的根名称服务器 - 要获取根名称服务器列表,只需运行dig
。获取其中一个输出服务器(在此示例中为 l.root-servers.net)并对其进行查询:(
dig @l.root-servers.net -t NS DOMAIN.NEt
产生如下输出:
;; AUTHORITY SECTION:
net. 172800 IN NS a.gtld-servers.net.
net. 172800 IN NS b.gtld-servers.net.
net. 172800 IN NS c.gtld-servers.net.
net. 172800 IN NS d.gtld-servers.net.
net. 172800 IN NS e.gtld-servers.net.
net. 172800 IN NS f.gtld-servers.net.
net. 172800 IN NS g.gtld-servers.net.
net. 172800 IN NS h.gtld-servers.net.
net. 172800 IN NS i.gtld-servers.net.
net. 172800 IN NS j.gtld-servers.net.
net. 172800 IN NS k.gtld-servers.net.
net. 172800 IN NS l.gtld-servers.net.
net. 172800 IN NS m.gtld-servers.net.
;; ADDITIONAL SECTION:
a.gtld-servers.net. 172800 IN A 192.5.6.30
b.gtld-servers.net. 172800 IN A 192.33.14.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
m.gtld-servers.net. 172800 IN A 192.55.83.30
这将提供 TLD 名称服务器列表。现在,如果您想要全球完整的视图,您需要从分布在全球各地的客户端执行剩余的查询(使用 CDN 或类似的东西)。
为了获得真正完整的视图,您应该从所有全局客户端端点遍历所有这些名称服务器;但您可以简化这一过程,只需查询其中一个名称服务器,即可获得它们所知道的目标域的所有名称服务器:
dig @a.gtld-servers.net. -t NS DOMAIN.NET
这会给你类似这样的结果:
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;DOMAIN.NET. IN NS
;; AUTHORITY SECTION:
domain.net. 172800 IN NS a.dns.domain.net.
domain.net. 172800 IN NS b.dns.domain.net.
domain.net. 172800 IN NS c.dns.domain.net.
;; ADDITIONAL SECTION:
a.dns.domain.net. 172800 IN A 173.246.98.1
b.dns.domain.net. 172800 IN A 213.167.229.1
c.dns.domain.net. 172800 IN A 217.70.179.1
^^^^ 这是 domain.net 的名称服务器的起始列表。请记下它们。
接下来,遍历这些输出名称服务器,并确保它们不会委托给其他名称服务器:
dig @c.dns.domain.net -t NS DOMAIN.NET
如果产生了上一个查询中未列出的任何名称服务器,请将它们添加到要查询的 DOMAIN.NET 名称服务器列表中。
现在,遍历 DOMAIN.NET 名称服务器列表并像这样查询每个服务器(其中 $NAME_SERVER 是您当前正在查询的列表中的名称服务器):
dig -t A @$NAME_SERVER domain.net
dig -t AAAA @$NAME_SERVER domain.net
将上述两个查询的结果添加到 DOMAIN.NET 的 A 和 AAAA 记录列表中。
一旦您查询了所有全球分布的客户端的所有权威名称服务器,您将获得相当完整的视图。