DNSSEC感觉像是一个高风险的协议。如果您正确配置了所有内容,客户端将获得额外的保证,即他们正在访问正确的主机。如果你做错了什么,你的DNSSEC没有验证,你的域名就会从互联网上消失。这会让你很受欢迎。只有两种类型的系统管理员错误会破坏DNSSEC:密钥不匹配和时钟不正确。
通过确定是否真的是DNSSEC问题来开始调试DNSSEC。
第六章:故障模式和故障排除DNSSEC 和网络DNSSEC状态是 DNS还是 DNSSEC?在线 DNSSEC调试器安全区域不安全区域缺少DS记录碎屑虚假区域在您的名称服务器上调试日志示例错误使用 Dig进行调试剖析RRSIG时间错误DS和DNSKEY验证编译BIND区域其他人的问题
我想说的是,网络设备已经达到了21世纪初的标准,现代设备不可能干扰DNSSEC。我真的很想这么说。我不能。如果您的新DNSSEC部署不起作用,或者有人更换了您网络上的设备,并且一切都坏了,请检查网络问题。
DNS解析器最初只在UDP端口53上使用小数据包。自1999年以来,DNS已经使用了大型UDP数据包和TCP,并且可以根据查询、客户端和网络条件的需要在它们之间进行切换。许多底层馈送路由器、物联网(IoT)设备和网络管理员强加的幼稚(Naïve)数据包过滤器会干扰现代DNS。在过去的12个月里,在“友好”设备中,我看到“Allow RFC 2671 DNS”GUI复选框不可原谅地默认为“off ”。
验证您的网络通过现代DNS流量的能力。从您的名称服务器运行一个大型dig查询。我将使用OARC的回复大小测试仪,如引言中所述。
$ dig +short rs.dns-oarc.net TXT
dig +short rs.dns-oarc.net TXT
rst.x4050.rs.dns-oarc.net.
rst.x4058.x4050.rs.dns-oarc.net.
rst.x4064.x4058.x4050.rs.dns-oarc.net.
"149.28.122.136 sent EDNS buffer size 4096"
"149.28.122.136 DNS reply size limit is at least 4064"
这部分网络可以传递最多4096字节的DNS消息。没事的。
xxxxxxxxxx
$ dig +short rs.dns-oarc.net TXT
rst.x1196.rs.dns-oarc.net.
rst.x1206.x1196.rs.dns-oarc.net.
rst.x1212.x1206.x1196.rs.dns-oarc.net.
"2001:19f0:5401:1eb3:5400:1ff:fef9:2ab9 sent EDNS buffer size 1232"
"2001:19f0:5401:1eb3:5400:1ff:fef9:2ab9 DNS reply size limit is at least 1212"
网络的这一部分可以传递高达1232字节的消息。这个网络不好。
翻转查询,从外部询问您的名称服务器。虽然各种网站声称提供此类服务,但许多网站从其输出中删除了DNSSEC。DNS管理员必须能够访问其网络外的调试工具。在任何云服务上启动临时虚拟机并检查。输出不会完全匹配您在名称服务器本身上运行相同查询时得到的结果,但仅凭大小就可以告诉您网络是否阻塞了流量。
如果发现瓶颈,请在网络的各个点运行查询,直到识别出违规者。如果你是网络管理员,你可能会发现数据包嗅探器很有用。
如果网络可以传递大型DNS消息,则问题出在DNS上。
DNSSEC响应有三种可能的状态:secure(安全)、insecure(不安全)和 bogus(虚假)。
有两件事导致了大多数bogus(虚假)区域:
那么,不是由这两个问题引起的虚假区域呢?也许您的密钥滚动失败,或者您过早删除了旧的DS记录。你可能对你的信任锚做了什么。系统管理员在发现新的错误配置方面拥有无与伦比的天赋。或者,你可能发现了一个完全独特的边缘案例,引发了协议或软件中的错误。您的网络甚至可能受到攻击。
让我们看看一些不同的工具来识别问题,从最漂亮的开始。
只有在尝试使用验证解析器解析已签名区域时,才会出现DNSSEC问题。如果目标或解析器不执行DNSSEC,则不是DNSSEC问题。这是一个传统的DNS问题。我的大多数DNS问题都涉及区域文件中的拼写错误,而不是签名。
下面例子是我的一个域名,已经从外界消失了:
xxxxxxxxxx
$ dig mwlucas.org @8.8.8.8
…
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 44646
…
;mwlucas.org. IN A
这里的关键部分是SERVFAIL声明。我的验证解析器说权威名称服务器无法给出答案。也许系统管理员错过了一个时间段并破坏了区域,引发了常规DNS故障。也许DNSSEC被搞得面目全非。添加 +cd
标志以禁用验证,并查看是哪一个。
xxxxxxxxxx
$ dig mwlucas.org @8.8.8.8 +cd
…
;; ANSWER SECTION:
mwlucas.org. 3600 IN A 45.63.79.193
当我停止检查DNSSEC时,此问题就会消失。我的DNSSEC无法验证;这是虚假的。(记住,“虚假”——bogus——是一个技术术语。)这不是协议方面的错误;密钥在某个地方出错,或者签名时间戳不是最新的,因此验证解析器拒绝了该区域。这就是DNSSEC的目的。
如果您碰巧正在运行支持RFC 8914的现代dig,并查询具有相同支持的现代名称服务器,您将在OPT PSEUDOSECTION下收到一条扩展的错误消息:
xxxxxxxxxx
$ dig fail03.dnssec.works
…
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; EDE: 6 (DNSSEC Bogus)
…
漂亮,当它可用时。
几个网站提供在线DNSSEC故障排除,但最漂亮的是桑迪亚国家实验室的DNSViz(Sandia National Laboratories’ DNSViz https://dnsviz.net)。 输入域名并点击“Analyze”。它会运行一系列查询,并生成该域名的信任链图。顶层是当前的DNS信任锚。域的每个级别都是一个单独的框,链的每个链接都是一圈,箭头说明了一切之间的联系。将鼠标悬停在任何东西上,您将看到一个包含低级细节的弹出框。
DNSViz会缓存其结果,因此在进行故障排除时,请检查页面的时间戳。我强烈推荐“Update Now”按钮。
在识别错误之前,您必须能够识别正常。如果我在 www.tiltedwindmilpress.com
的电子书店查看DNSSEC,我会得到这个。
【此处有图】
顶部框表示根区域。在最上层,我们在DNSViz的解析器中配置了信任锚。信任锚是密钥签名密钥,密钥20326。该KSK对根区域的区域签名密钥,即中间圆圈中的密钥26838进行签名。根区域的ZSK在指向 .com
区域的KSK的DS记录上签名。
中间的框是 .com
区域。最上面的圆圈,编号30909,是 .com
KSK。中间的盒子,编号39343,是ZSK。我的域名的DS记录由 .com
ZSK签名。
在底部,我们有一个 tiltedwindmilpress.com
的框。这个区域只有一个密钥,所以它是一个组合签名密钥。该区域拥有主机 www.tiltedwindmillpress.com
的A和AAAA记录,两者都有签名。此区域具有完整、功能齐全的DNSSEC。
如果您的区域缺少DNSSEC,您可以期望信任链从根节点向下追踪,并在区域父域中的NSEC或NSEC3记录中结束。记住,NSEC记录是不存在的权威声明。这是我的主域名上的DNSViz,直到那些可怕的虚拟键盘使 mwl.io
成为一个更明智的选择。
【此处有图】
根区域是一个安全区域。 .com
也是如此。 .com
区域没有此域的DS记录,因此它有一个NSEC3记录,声明该域没有DNSKEY记录。而且,该区域确实缺乏DNSKEY。
如果一个区域已签名,但DS记录缺失,DNSViz也会显示出来。现在我意识到这个旧区域缺少签名,我已经签名了。
【此处有图】
同样,根区域和 .com
区域是安全的。中间的 .com
区域仍然有NSEC3记录,声明我的域没有密钥。我的域名就在底部的盒子里,挥舞着它的手,宣布它也有密钥。但是,由于缺少DS记录,无法识别该区域的DNSSEC。
如果您看到如图6-3所示的内容,请通过发布DS记录来激活DNSSEC。
并非所有地区都有原始的信任链。这是我的主机 www.mwl.io
的链。
【此处有图】
我的根区域和我的区域的框显示有效签名。
查看图6-4的中间方块,其中包含 .io
域的记录。那个带感叹号的三角形代表一个问题。你偶尔会看到这样的碎屑(detritus)。然而,这并没有影响我领域的信任链。它在我的父区域( parent zone),所以这正式不是我的问题。只要信任锚点和您的区域之间至少存在一条有效路径,您的DNSSEC就完全正常。
首先,安全和不安全的实例代表了正确的配置——可能不完整,但不会造成损害。域名 dnssec-failed.org
的存在就是一个坏例子。
【此处有图】
最上面的两个框,root和 .org
区域,都很好。 .org
区域包含 dnssec-failed.org
的DS记录,指向带有标签106的密钥。(如果您将鼠标悬停在DS记录上,您将看到密钥哈希等详细信息。)该区域的实际DNSKEY记录具有标签29521。它与父域的DS记录不匹配。验证解析器将拒绝它。有时,此区域上的签名也会过期。
如果您的区域如图6-5所示,请修复您的DS记录。
签名过期的区域看起来非常相似,但有一个红色的大箭头。如果你看到这一点,要么是你的域名服务器的时钟出现了偏差,要么是签名确实已经过期。首先检查权威服务器的时钟。
如果你四处逛逛,你会发现其他在线工具,比如威瑞信(Verisign)的DNSSEC调试器(https://dnssec-debugger.verisignlabs.com/)。挑一个你喜欢的。
网站很漂亮,但你并不总是可以访问它们。一旦排除了网络问题,正常的DNSSEC特定故障可能有两个根本原因。DS记录与子域的DNSKEY不匹配,或者某个地方的时钟错误到签名无效。调试它们只需要 dig(1)
、 date(1)
和 tail -f
工具。
从递归名称服务器的日志开始。
要了解递归名称服务器拒绝验证区域的原因,最简单的方法是启用调试日志。在这里,我在BIND中配置了一个DNSSEC特定的调试日志。我始终在递归服务器上启用此日志。
xxxxxxxxxx
logging {
channel dnssec_log {
file "working/dnssec_log" size 20m;
print-time yes;
print-category yes;
print-severity yes;
severity debug 1;
};
category dnssec { dnssec_log; };
};
第一节(stanza)创建了一个名为 dnssec_log 的日志实体。它定义了一个包含日志的文件,并将大小限制为20MB。此日志应包括时间、类别和严重性为1(最严重的错误)的所有消息。BIND日志不断旋转;当它们达到最大大小时,BIND会删除最旧的数据,为新数据腾出空间。
第二节告诉 named
向名为 dnssec_log 的日志发送DNSSEC消息。如果您花费大量时间对DNS进行故障排除,BIND包括许多日志记录类别。
重新加载 named
并在新创建的日志文件上运行 tail -f
。在另一个终端中,进行一个你知道会失败的查询。
xxxxxxxxxx
$ dig dnssec-failed.org @localhost
日志会告诉你到底发生了什么。
xxxxxxxxxx
27-Aug-2021 10:53:12.873 dnssec: info: validating dnssec-failed.org/DNSKEY: no valid signature found (DS)
“No valid signature found”(找不到有效签名)听起来很笼统,但它通常表示DS/DNSKEY不匹配,如上一节所示。其他错误消息更具体。下面,我挖掘了一个在父域中具有过期签名的主机:
xxxxxxxxxx
$ dig ok.ok.sigexpired.bad-dnssec.wb.sidnlabs.nl
日志准确地指出了问题所在:
xxxxxxxxxx
27-Aug-2021 11:04:11.929 dnssec: info: validating sigexpired.bad-dnssec.wb.sidnlabs.nl/DNSKEY: verify failed due to bad signature (keyid=61837): RRSIG has expired
ok
子区域的签名很好。中间区域 sigexpired
上的签名已过期,日志也显示了这一点。
如果您需要更多详细信息,请提高 named.conf 中的严重性级别。调试级别 2
为我提供了所需的一切,而调试级别 3
则超出了我的应对能力。
在需要调试之前,最好熟悉错误。专门设置自己的权威名称服务器来提供错误是一项相当大的工作,但幸运的是,一些过于慷慨的人向公众提供了这样的服务。虽然立即关闭公共技术资源的最确定方法是我在一本书中提到它,但我会在这里讨论一些,并希望其中一些能够存活下来,直到这本书到达你手中。
最著名的是直接的 dnssec-failed.org
,它的DS记录和密钥不匹配。
在 dnslab.org
上,条目 bad1
到 bad6
展示了不同的失败。它们在dig中看起来都一样,但你的错误日志会说明原因。
xxxxxxxxxx
$ dig bad2.dnslab.org
…
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 36184
…
您可以通过检查 reason.badX.dnslab.org
上的TXT记录来了解DNSLab认为每个错误的具体原因。请确保禁用检查,以便您可以看到该错误,并将其解释与您的日志进行比较。
xxxxxxxxxx
$ dig reason.bad2.dnslab.org txt +cd
…
reason.bad2.dnslab.org. 86396 IN TXT "signatures long expired"
如果你读德语,https://dnssec.works/
提供了几种不同类型的故障。绕过主机 fail01.dnssec.works
通过 fail05.dnssec.works
。
SIDN Labs在 https://workbench.sidnlabs.nl/bad-dnssec.html
。他们的目录包括中间区域破碎的区域。
最后,您可以在以下网址找到一些损坏的DNSSEC https://caatestsuite.com/
。本网站旨在测试证书颁发机构授权记录,但损坏的DNSSEC肯定会影响您的CAA记录。
选择一个方便的地点运行dig。看看不同的错误是什么样子的。当你不可避免地破坏自己的DNS或DNSSEC时,你会珍惜这种经历。
如果您无法访问递归名称服务器或任何其他无法验证区域的主机上的日志,则只能使用dig和date进行调试。它们足以向你展示你正在经历的两种失败中的哪一种。
从区域的RRSIG记录开始。将 +dnssec
标志添加到您的 dig
命令中以查看它们。如果该区域是伪造的,请添加 +cd
标志。您可以添加 +multi
标志以在多行之间分割输出。
xxxxxxxxxx
$ dig www.mwl.io +dnssec +cd +multi
…
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
www.mwl.io. 3421 IN A 45.63.79.193
www.mwl.io. 3421 IN RRSIG A 13 3 3600 (
20210908132044 20210825125200 44950 mwl.io.
t99CfAWljvGaVkyWHnN5KqgGkPeOYN62RdgAVJb1iJAj
sbh6gasAneE0aYe4VEjPdcsQed3rt29yX4mRYOlK7A== )
…
这让我们开始了。让我们拆开这个资源记录(Resource Record)签名。
记录名称后的 3421
是记录将保留在缓存中的时间(秒)。如果你使用的是公共解析器,比如谷歌或Cloudflare提供的解析器,你实际上是在查询整个服务器群中的一个。
以下 IN RRSIG A
表示这是一条互联网记录,一条资源记录签名(Resource Record Signature)记录,与 A
记录有关。该区域可能有多个匹配的 A
记录——记住,签名在资源记录集(Resource Record Set)上,而不是单个记录。这证明没有其他匹配的 A
记录。
接下来,13
给出算法编号。算法13是ECDSAP256SHA256,是当前两个标准之一。
下面的 3
是此资源集中的记录数。
接下来是这些数据的原始生存时间。此记录可以缓存3600秒或一小时。
接下来,我们知道这个签名的到期日期和生效日期。这些日期使用四位数字的年份、两位数字的月份、两位数据的小时、两位数的分钟和两位数的秒。此记录将于2021年9月8日下午1:20分44秒到期。它在20210825125200之后或2021年8月25日下午12:52时生效。
密钥ID 44950如下。
然后我们有几行实际的公钥。如果你需要复制和粘贴公钥,去掉 +multi
选项。
DNSSEC区域签名者会自动更新RRSIG记录,以便在旧记录过期之前进行传播。我们的示例RRSIG记录将于8月25日生效,并于9月8日到期。如果是9月9日,并且您的递归服务器缓存了此RRSIG,则该区域将不会验证。大多数情况下,这是由时钟问题引起的。过载的硬件上的虚拟主机特别容易受到时钟漂移(clock drift)的影响。
与允许少量时钟漂移的Kerberos等协议不同,验证DNSSEC签名时间戳没有回旋余地。如果签名在今天10:04:07到期,则在10:04:08验证失败。签名更新必需足够早,以便旧签名在过期之前从递归服务器缓存中过期。
我强烈建议自动监控所有名称服务器上的时间和日期,无论是权威的还是递归的。如果另一个组织的权威名称服务器正在提供已过期或尚未生效的签名,您将无能为力,但您可以加倍确保您的主机是准确的。
如果时间戳看起来不错,请比较DS和RRSIG记录中的密钥标签。区域可以有多个RRSIG和DS记录,我们将在下一章中看到,但只要信任锚和RRSIG记录之间至少有一条有效路径,就可以了。
一旦您熟悉了DNSSEC的故障排除,跟踪密钥不匹配的最简单方法是使用 dig
的 +trace
选项。(演练程序还有一个很好的 -S
选项,专门用于跟踪DNSSEC密钥错误。)不过,对于DNSSEC初学者来说,输出结果是压倒性的(overwhelming),因此我们将首先使用测试域 dnssec-failed.org
进行更具体的查询。
我总是从信任链的底部开始排除故障。如果 .com
或 .org
等域名失去了DNSSEC,你很快就会知道。如果常规组织注册的域类型丢失了DNSSEC,则几乎可以肯定错误发生在该域。
xxxxxxxxxx
$ dig dnssec-failed.org +cd +multi dnskey
…
;; ANSWER SECTION:
dnssec-failed.org. 3441 IN DNSKEY 256 3 5 (
…
) ; ZSK; alg = RSASHA1 ; key id = 44973
dnssec-failed.org. 3441 IN DNSKEY 257 3 5 (
…
) ; KSK; alg = RSASHA1 ; key id = 29521
此区域有两个密钥,一个密钥签名密钥(Key Signing Key)和一个区域签名密钥(Zone Signing Key)。记住,该地区的KSK标志着ZSK。父域的DS记录应指向KSK。KSK是密钥id(tag)29521。
xxxxxxxxxx
$ dig dnssec-failed.org ds
…
;; ANSWER SECTION:
dnssec-failed.org. 21600 IN DS 106 5 1 4F219DCE274F820EA81EA115063…
dnssec-failed.org. 21600 IN DS 106 5 2 AE3424C9B171AF3B202203767E5…
紧随DS之后的字段是密钥标签。DS记录指向标签106。
如果这是您的区域,您应该立即在域注册表中更正DS记录。如果是别人的,好吧,你知道这不是你的问题。除非是您的父区域、托管平台或CDN,在这种情况下,这是您的问题。
对于DNS错误,有时您唯一能做的就是查看区域的内容并尝试找出发生了什么。如果您正在运行BIND的DNSSEC自动化,即使是由静态文件支持的区域也是动态的。动态区域通常由二进制文件支持,因此您无法轻松查看它们。使用 named-compilezone(8)
从二进制文件创建文本区域文件。
$ named-compilezone -j -f raw -o outputfile zone zonefile.signed
使用 -j
选项包含日志文件。 -f raw
参数告诉 named-compilezone
它正在读取一个二进制文件。使用 -o
指定一个输出文件。输出文件为 -
会将区域溢出到终端。然后给出区域的名称和已签名的区域文件。区域文件将以 .signed 结尾。在这里,我从签名到 /tmp 中的文件的数据文件 mwl.io.db.signed 编译我的区域 mwl.io
。
人们破坏了DNS。如果您确定某个主要业务合作伙伴破坏了他们的DNSSEC并伪造了他们的区域,您可以暂时禁用他们的区域的DNSSEC验证。RFC7646中定义的负信任锚(negative trust anchor —— NTA)告诉递归名称服务器您知道该区域是伪造的,并且您故意选择禁用该区域的验证。NTA是短暂的,通常在一小时内到期。这给了你足够的时间联系域名的DNS管理员,并通知他们他们已经伪造了。所有主要的域名服务器都支持NTA。
使用BIND,使用 rndc
在BIND上声明NTA。
$ rndc nta zone
例如,如果我炸毁了我的区域,而你想给我发电子邮件让我知道,你可以在 mwl.io
上设置NTA:
xxxxxxxxxx
$ rndc nta mwl.io
Negative trust anchor added: mwl.io/_default, expires 16-Nov-2021 11:28:06.000
BIND每五分钟检查一次NTA的区域,看看该区域是否有效。如果该区域再次生效,则NTA将自动过期。
默认情况下,NTA将在一小时后过期。您可以使用 nta-lifetime
named.conf 选项设置不同的过期时间(秒)。通过 nta-recheck
调整轮询间隔。
要在命令行中设置不同的过期时间,请添加 -lifetime
选项。如果我能看到另一家公司已经修复了他们的DNSSEC,但他们的TTL说虚假数据将在第二天缓存,我可以分配一个适当的生命周期,继续我的生活。
xxxxxxxxxx
$ rndc nta -lifetime 24h mwl.io
现在您已经了解了如何调试DNSSEC,让我们看看如何通过更改密钥来严重破坏它。