您已经看到了不同类型的记录,并对信任链的工作原理有了基本的了解,但没有什么能取代对现实世界实现的观察。DNS信息是公开的,因此我们可以研究其他域如何实现DNSSEC。
首先配置缓存解析器以验证DNSSEC,然后我们将检查各种输出。
大多数桌面系统都有一个存根解析器(stub resolver)——它们将DNS查询发送到缓存递归名称服务器,但不处理响应或缓存它们。他们不会自行验证DNSSEC。如果本地递归名称服务器声称DNS响应已签名,那对他们来说就足够了。
如果攻击者位于缓存名称服务器和客户端之间的网络上,他们可能会欺骗该递归服务器的结果。技术上最正确的解决方案是让存根解析器验证DNSSEC,但这还没有成为标准。
一些应用程序正在通过使用DNS over TLS(DoT)或DNS over HTTPS(DoH)安全地联系缓存解析器来解决缺少存根解析器DNSSEC验证的问题。我们将在第9章讨论这些。
如果您希望Unix工作站验证DNSSEC,请启用本地名称服务器并将其配置为仅接受来自本地主机的查询。一些Linux确实在桌面上验证DNSSEC。
客户端工具不会验证DNSSEC,但您需要一个客户端来查询验证解析器。我们将重点介绍使用最广泛的DNS工具 dig(1)
。它由BIND的作者开发,通常符合标准。如果您是dig的常规用户,请确保您没有任何选项可以在 .digrc 中隐藏调试输出。
另一个流行且可靠的工具是由NLNet Labs开发的 drill(1)
,正是这些人给我们带来了Unbound和NSD。命令行选项与 dig
不同,但如果你对 drill
很熟悉,就没有理由切换。
排除DNS故障时,避免使用 host(1)
或 nslookup(1)
。 host
命令用于非常简单的检查,缺乏 dig
或 drill
的细节和自由裁量权(discretion)。 nslookup
命令已被弃用、放弃、复活、杀死、重建、重新实施、重新放弃、部署,被委托给某些骇人听闻的村庄外的一家废弃工厂,被判犯有一项移动违规行为和二百七十四项恶意逗留罪,并被集成到Microsoft Windows中。(The nslookup command has been deprecated, abandoned, resurrected, slain, rebuilt, re-implemented, re-abandoned, deployed, consigned to an abandoned factory outside the village of Something Awful, found guilty of one moving violation as well as two hundred seventy-four counts of Malicious Lingering, and integrated into Microsoft Windows.)我无法判断您正在使用的nslookup的无数版本中的哪一个,也无法判断该实现的质量。我可以告诉你,一些声称可以验证DNSSEC的nslookup其实并没有实现此功能。不要使用它。
还有其他工具。BIND 9.10引入了 delv(1)
,这是一种支持DNSSEC的下一代 dig(1)
。Knot DNS提供 kdig(1)
,Unbound有 unbound-host(1)
。只要它不是 host(1)
或 nslookup(1)
,就使用对您最方便的工具。
大多数解析器都可以通过一个简单的选项、复选框或其他简单的切换来启用DNSSEC验证。BIND的现代版本默认执行DNSSEC验证,但随着这些知识不断从我的脑海中消失,我更喜欢在 named.conf 中明确声明支持。
dnssec-validation auto;
将此语句放入全局选项中,然后重新加载 named(8)
。
验证DNSSEC需要使用 dig(1)
等客户端。
dig(1)
要素Dig是检查DNS数据最常用的工具,因此我将在详细的示例中使用它。像 drill
这样的工具以不同的格式显示相同的信息,所以如果你喜欢另一种工具,请遵循这些概念,而不是确切的格式和选项。配置 /etc/resolv.conf 以指向您的验证解析器。
让我们运行一个基本查询,并从DNSSEC的角度研究结果。
xxxxxxxxxx
$ dig mwl.io
; <<>> DiG 9.16.16 <<>> mwl.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36121
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
我们首先看到我们使用的dig版本(9.16.16)和查询的主要主题。Dig的版本号与其附带的BIND版本相匹配。命令行上使用的任何其他选项也会显示在此处。基本DNS在UDP上运行,因此DNS使用id号来匹配对查询的响应。
HEADER 行声明dig正在执行什么类型的操作,以及DNS服务器是否返回错误。此特定请求是QUERY,NOERROR的状态意味着服务器为您提供了答案。NOERROR并不意味着答案是新的、权威的,或者不会从缓存中过期。它只是表明它有答案。
flags 行提供了有关查询的具体详细信息。如果你正在调试DNS,更不用说DNSSEC了,这些标志就是你的新伙伴。他们确切地说明了发生了什么。您将看到的标志包括 qr
、 aa
、 rd
、 ra
、 ad
和 cd
。
我们的示例有标志 qr
、 rd
、 ra
和 ad
。这是对查询的响应。我们要求递归,递归是可用的。最后,这是一个DNSSEC验证的响应。
QUERY条目显示了我们的要求。我们发送了一个查询。
ANSWER字段显示了我们收到了多少回复。在这里,我们得到一个答案。如果有多条记录,正如您查询“any”记录时常见的那样,记录数量将显示在此处。如果它为零,则您要查找的记录类型不存在。
ADDITIONAL字段表示存在额外内容。
xxxxxxxxxx
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;mwl.io. IN A
接下来的几行用于扩展DNS(Extended DNS —— EDNS),或使用较大UDP数据包的DNS。我们使用的是扩展DNS的版本0。到目前为止,只定义了一个 flag :do ,用于DNSSEC OK。当客户端专门请求DNSSEC验证时,它会被设置,在正常查询中不会出现。最后,我们看到客户端和服务器之间的网络可以处理多达4096字节的UDP数据包。这已经足够了。
如果您正在运行支持RFC 8914的现代dig,并查询具有相同支持的递归服务器,您将在EDNS语句下方看到任何扩展DNS错误(extended DNS errors —— EDE)。如果存在,这些错误将确切地告诉您名称服务器拒绝响应的原因。
在 Question 部分,dig重复查询。
xxxxxxxxxx
;; ANSWER SECTION:
mwl.io. 7200 IN A 45.63.79.197
;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Jul 16 12:05:07 EDT 2021
;; MSG SIZE rcvd: 65
最后,答案。Dig为您的查询提供了完整的RRSet。主机 mwl.io
只有一个IP,所以你会得到一个答案。我们还可以获得有关查询执行方式和处理位置的调试信息。
如果要查看区域中的DNSSEC信息,请添加 +DNSSEC
标志。我还添加了 +nocomments
来删除不必要的细节。
xxxxxxxxxx
$ dig isc.org +dnssec +nocomments
…
IN A
isc.org. 60 IN A 149.20.1.66
isc.org. 60 IN RRSIG A 13 2 60 20210713170049 20210613160056 27566 isc.org. pxHny0SKMI0ih9LWCW/11e0YMBaryH4cFjYR/f/1Tr/XSh+WqvDkuEhk ljopRVOqGeBrDvRmdYYUM2k+dM+a7Q==
…
RRSIG记录的存在表明此区域已使用DNSSEC签名。然而,仅仅因为区域被签名并不意味着你的递归服务器验证了答案。只有广告标志的存在表示验证。
如果你想看到DNSSEC记录存在,但不关心哈希和密钥的长字符串,请添加 +nocrypto
标志。
在本例的HEADER部分, status
字段显示NOERROR。dig出去了,找到了数据,并把它反馈给了我们。一切正常。也许我们得到了一个有用的答案。也许我们没有。但这个系统奏效了。状态错误表示系统不工作。
您可能会看到SERVFAIL的状态。名称服务器没有对此查询的缓存响应,无法从权威服务器获取响应。传统上,这意味着权威服务器要么停机,要么配置错误。但是,当一个区域具有DNSSEC时,当您的名称服务器收到答案但无法验证时,您将收到SERVFAIL。
如果您要查找的特定记录不存在,并且该名称不存在,则名称服务器将返回NXDOMAIN。这是一份权威声明,表明你问的具体问题不存在。没有主机 www2.mwl.io
,如果你要求它,我的权威服务器会说“不,NXDOMAIN。”
NXDOMAIN不同于没有所需类型记录的权威答案。还记得响应早期的ANSWER字段吗?您可能会得到一个权威的答案,说NOERROR,但答案为0。这表示存在具有该名称的记录,但不是您请求的排序。假设我要求提供 www.mwl.io
的MX记录:
xxxxxxxxxx
$ dig www.mwl.io mx
…
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45341
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
没有错误,但我的查询没有答案。没有MX记录,但A和AAAA记录确实存在。Dig说“我能找到记录,但不是你想要的那种。”这并不意味着主机 www.mwl.io
没有收到邮件,只是它没有自己的MX记录。传入邮件将使用该区域的MX记录。
2020年10月,RFC 8914定义了各种新的DNS错误消息和添加更多错误消息的可扩展方法。这些错误包括“DNSSEC虚假”(DNSSEC Bogus)和“伪造答案”(Forged Answer)等消息,这将降低诊断DNS问题的难度。他们将在未来几年出现。
要查看区域的DNSSEC信息,请添加 +dnssec
选项。在这里,我使用验证解析器检查 isc.org
上的DNSSEC记录。由于这些人是DNSSEC专家,我希望他们的区域能够正常工作。
两个选项有助于使输出更清晰。添加 +multi
将输出拆分为多行。 +nocrypto
选项不会隐藏DNSSEC记录,但会省略您可能无论如何都不想读取的关键信息。
xxxxxxxxxx
$ dig +dnssec +multi +nocrypto isc.org
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29878
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
…
我们收到了 ad
标志,因此这是经过身份验证的数据。答案已通过DNSSEC验证。进一步向下查找签名,如RRSIG(资源记录签名)记录所示。
xxxxxxxxxx
…
;; ANSWER SECTION:
isc.org. 6794 IN DNSKEY 257 3 13 (
[key id = 7250]
) ; KSK; alg = ECDSAP256SHA256 ; key id = 7250
isc.org. 6794 IN DNSKEY 256 3 13 (
[key id = 27566]
) ; ZSK; alg = ECDSAP256SHA256 ; key id = 27566
isc.org. 6794 IN RRSIG DNSKEY 13 2 7200 (
20211123004729 20211024000151 7250 isc.org.
[omitted] )
isc.org. 6794 IN RRSIG DNSKEY 13 2 7200 (
20211123004729 20211024000151 27566 isc.org.
[omitted] )
如果验证解析器无法验证RRSIG记录,则返回SERVFAIL错误。对于最终用户来说,这似乎是主机从互联网上消失了。这样的区域被称为伪区(bogus)。我在第6章中展示了各种故障以及如何诊断它们。
如果您请求,非验证解析器将显示区域的DNSSEC记录,但它不会验证该签名。这就是非验证解析器非验证的原因。即使签名无效,非验证解析器也总是返回权威服务器为该区域提供的任何数据。或者,如果你愿意的话:非验证解析器的行为与往常一样。
向ISC的权威服务器询问 isc.org
区域并检查标志。
xxxxxxxxxx
$ dig +dnssec +multi isc.org @ns1.isc.org
…
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
…
这是该区域的权威服务器,但其响应不包括 ad
标志。你确实会得到 aa
标志,它代表权威的答案。这个直接来自消息来源的权威答案不知何故没有经过验证。直接来自主名称服务器的响应不应该是加密安全的吗?
直接来自权威服务器的权威答案不应是经过身份验证的数据。为您计算DNSSEC验证不是权威名称服务器的工作。这是验证解析器的工作。权威服务器通过提供签名供他人验证来完成其工作。
将解析器与权威服务器分离是强烈推荐的最佳实践。不要试图通过在权威服务器上测试验证来排除区域上的DNSSEC故障,否则将无法正常工作。
当权威名称服务器被破坏时,以及当DNSSEC验证失败时,您的解析器将返回SERVFAIL。在进行故障排除时,您必须能够区分这两种类型的错误。找出错误类型的最简单方法是使用 +cd
选项禁用DNSSEC验证。
我建议您在实际排除故障之前,先看看这在测试环境中是如何工作的。Comcast为此提供了域名 dnssec-failed.org
。在这个域名上运行dig。
xxxxxxxxxx
$ dig dnssec-failed.org
…
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 34316
…
如预期的那样,SERVFAIL错误,没有其他结果。现在,在禁用检查的情况下尝试相同的查询。
xxxxxxxxxx
$ dig dnssec-failed.org +cd
…
dnssec-failed.org. 7197 IN A 69.252.80.75
禁用DNSSEC时收到响应表示域的签名无效。
现在您可以检查DNSSEC数据了,让我们弥补权威名称服务器中的一个弱点。