我在 Google Compute Engine 上全新安装了 Ubuntu 18.04。我使用以下配置编译了最新版本的 Dnsmasq (2.80):
no-resolv
server=8.8.8.8
conf-file=/usr/share/dnsmasq-base/trust-anchors.conf
dnssec
port=5353
然后我发出以下命令:
dig @127.0.0.1 -p 5353 pir.org
之后经过长时间的停顿,然后返回结果:
:~$ dig @127.0.0.1 -p 5353 pir.org
;; Truncated, retrying in TCP mode.
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 5353 pir.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62921
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;pir.org. IN A
;; ANSWER SECTION:
pir.org. 299 IN A 97.107.141.235
;; Query time: 56 msec
;; SERVER: 127.0.0.1#5353(127.0.0.1)
;; WHEN: Thu Aug 15 00:55:35 UTC 2019
;; MSG SIZE rcvd: 52
这表明它正在恢复到 TCP 模式。
dnsmasq 日志显示:
dnsmasq: reducing DNS packet size for nameserver 8.8.8.8 to 1280
如果我在 Amazon Web Services 上执行完全相同的操作,dig 会立即返回,而无需诉诸 TCP 模式。
当 1.1.1.1 在 GCE 上的 dnsmasq 中用作上游服务器时,dnsmasq 日志中没有长时间暂停且没有任何记录。但是,它仍然报告截断结果/TCP 模式:
~$ dig @127.0.0.1 -p 5353 pir.org
;; Truncated, retrying in TCP mode.
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 5353 pir.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61800
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;pir.org. IN A
;; ANSWER SECTION:
pir.org. 220 IN A 97.107.141.235
;; Query time: 53 msec
;; SERVER: 127.0.0.1#5353(127.0.0.1)
;; WHEN: Thu Aug 15 01:44:23 UTC 2019
;; MSG SIZE rcvd: 52
数据包捕获(GCE):
03:39:06.405852 IP 10.154.0.29.32748 > 8.8.8.8.53: 53258+ [1au] A? pir.org. (48)
03:39:06.420540 IP 8.8.8.8.53 > 10.154.0.29.32748: 53258$ 2/0/1 A 97.107.141.235, RRSIG (219)
03:39:06.420726 IP 10.154.0.29.14117 > 8.8.8.8.53: 46254+ [1au] DS? org. (32)
03:39:06.421028 IP 8.8.8.8.53 > 10.154.0.29.14117: 46254$ 3/0/1 DS, DS, RRSIG (403)
03:39:06.421154 IP 10.154.0.29.8094 > 8.8.8.8.53: 56315+ [1au] DNSKEY? . (28)
03:39:06.422456 IP 8.8.8.8.53 > 10.154.0.29.8094: 56315$ 3/0/1 DNSKEY, DNSKEY, RRSIG (864)
03:39:06.422995 IP 10.154.0.29.34809 > 8.8.8.8.53: 46400+ [1au] DS? pir.org. (36)
03:39:06.429627 IP 8.8.8.8.53 > 10.154.0.29.34809: 46400$ 3/0/1 DS, DS, RRSIG (283)
03:39:06.429974 IP 10.154.0.29.26859 > 8.8.8.8.53: 55747+ [1au] DNSKEY? org. (32)
03:39:06.430307 IP 8.8.8.8.53 > 10.154.0.29.26859: 55747$ 7/0/1 DNSKEY, DNSKEY, DNSKEY, DNSKEY, RRSIG, RRSIG[|domain]
03:39:11.405991 IP 10.154.0.29.26859 > 8.8.8.8.53: 55747+ [1au] DNSKEY? org. (32)
03:39:11.406544 IP 8.8.8.8.53 > 10.154.0.29.26859: 55747| 0/0/1 (32)
数据包捕获(AWS):
03:39:26.312403 IP 192.168.0.131.17535 > 8.8.8.8.53: 7225+ [1au] A? pir.org. (48)
03:39:26.327521 IP 8.8.8.8.53 > 192.168.0.131.17535: 7225$ 2/0/1 A 97.107.141.235, RRSIG (219)
03:39:26.327571 IP 192.168.0.131.1520 > 8.8.8.8.53: 37804+ [1au] DS? org. (32)
03:39:26.329798 IP 8.8.8.8.53 > 192.168.0.131.1520: 37804$ 3/0/1 DS, DS, RRSIG (403)
03:39:26.329893 IP 192.168.0.131.62316 > 8.8.8.8.53: 12792+ [1au] DNSKEY? . (28)
03:39:26.332070 IP 8.8.8.8.53 > 192.168.0.131.62316: 12792$ 3/0/1 DNSKEY, DNSKEY, RRSIG (864)
请问您知道为什么 GCE 的行为与 AWS 不同吗?
答案1
您的最终查询很小,但验证 DNSSEC 所需的某些中间查询可能要大得多。这就是 DNSSEC 的本质。
DNS 的原始最大 UDP 响应大小为 512 字节,但 DNSSEC 响应可能为几千字节。EDNS0 允许客户端宣传它支持更大的 UDP 响应,但 DNS 服务器将有自己的最大 UDP 响应大小,并且可能根本不支持 EDNS0。
有很多方法可能会出错。一些较旧的 DNS 服务器根本不支持 EDNS0,如果您向他们发送带有 EDNS0 的查询,他们会默默地丢弃整个查询。有些支持它并允许足够大的响应导致 UDP 数据包被碎片化,这可能会导致响应在防火墙丢弃碎片化的 DNS 响应时消失在漏洞中,或者响应在设置了不碎片位的情况下发送,然后在需要碎片化时被丢弃。
似乎发生的情况是来自 8.8.8.8 的初始响应被丢弃,导致 dnsmasq 超时并回退到使用较小的最大值(1280 字节),而这个最大值对于响应来说太小,导致截断并随后回退到 TCP。而来自 1.1.1.1 的响应从一开始就被截断,可能是因为该服务器支持较小的最大 UDP 响应大小,不会导致碎片化。如果您愿意,可以使用数据包捕获来验证这一点。
而在 AWS 中,这些 DNS 服务器都是任播的,因此响应的服务器(或它与您之间的网络)可能配置不同,并且支持 EDNS0,其 UDP 响应大小足够容纳整个 DNSSEC 查询响应,然后该响应成功传递给客户端。
8.8.8.8 的查询响应丢失不应该发生,这可能是由于配置错误导致的,但 DNSSEC 查询回退到 TCP 的情况并不罕见。当响应大于 DNS 服务器允许的 UDP 响应时,这是预期行为。
为了避免这种情况,您要么必须找到一个允许更大 UDP 响应的其他递归 DNS 服务器,要么自己使用 Unbound 等运行一个,因为 dnsmasq 不支持递归 DNS。