DNSSEC允许客户端对服务器发送的信息进行加密验证。如果我的权威DNS服务器声称 mwl.io
的IP地址为 2001:db8::f00d
,客户端应根据请求获取该地址。如果有人伪造DNS响应数据包或毒害递归服务器的缓存,验证DNSSEC查询的服务器将识别污染并拒绝虚假数据。但是“加密验证”(cryptographically verify)是什么意思呢?
大多数人认为密码学是一种在可读明文和不可读密文之间转换文本的方法。只有知道密钥和加密方法的人才能执行任何转换。这是惊悚片、间谍和另类的伪维多利亚艺术家的作品,但虽然密码学最初是作为秘密信息开始的,但现在它支持各种工具和技术。密码学是DNSSEC的必要组成部分,但它不是主要重点。你不需要了解如何加密和解密文本、计算数字签名或将密钥隐藏在鞋底,这样你就可以通过检查站走私它们。我在许多其他书中详细讨论了这些,其他作者可以带你深入数学。你确实需要了解这些部分是如何组合在一起的,以及如何处理各种组件。
DNSSEC使用的许多加密概念也被HTTPS和TLS等协议所利用。它们与DNSSEC之间的关键区别在于,DNSSEC不进行任何在线加密和签名。DNS客户端不协商加密参数或构建“安全”通道。在SSH或SNMPv3中找不到与加密握手等效的东西。主DNS服务器每周左右对记录进行签名,并根据需要重新生成这些签名。DNS客户端下载记录并验证签名。
我们将讨论加密哈希(cryptographic hashes)、公钥加密(public key cryptography)、数字签名(digital signatures)、DNSSEC密钥(DNSSEC keys)和信任链(Chain of Trust)。
hash (哈希)或 checksum (校验和)是一种计算,它从任何数据块中生成固定长度的字符串,并用作完整性验证工具。产生哈希的方法称为 algorithm (算法)。每种算法都会产生一个固定长度的哈希,但不同的算法会产生不同长度的哈希。SHA256哈希的长度始终为256位,而SHA512哈希的长度为512位。哈希可以是加密的,也可以不是。
当你预期会损坏而不是篡改时,non-cryptographic hash (非加密哈希)是有用的。一个测试电子书完整性的简单哈希可能是 “计算书中的单词数,并在前面加上足够的零,使其长度为12位。” 如果电子书在运输过程中损坏,这个哈希可能会捕获它。你会在TCP和整个制造过程中看到类似的哈希。这本书印刷版的ISBN的最后一位是一位数字哈希。这些都是有效的哈希值,但很容易伪造。检测更改的数据需要更稳健的哈希算法。
使用 cryptographic hash (加密哈希),数据中的任何更改都会更改从数据生成的哈希。取IP地址 2001:db8::f00d
。其SHA256哈希值为0bc7561a5faae51787e0900e7e577e8f67382883068f32205229665db9b8a4。如果入侵者移动了冒号,使其变为 2001::db8:f00d
,典型的过度劳累和薪酬过低的系统管理员甚至可能不会注意到。然而,此地址的SHA256哈希值为4fdc0949e0f203bc11fe1cb3b4de262b63c6898dc775d8322c83ad05ba094ebd。即使是对哈希值最粗略的检查也会显示出差异。
可能的数据集数量是无限的,而SHA256只有256个字节。最终,两个数据集将具有相同的哈希值。这被称为 hash collision (哈希碰撞)。对计算这种冲突的抵抗力是哈希加密的原因。
考虑一下“how many words are in a book.”的哈希值。使用相同的哈希值创建一个文档是微不足道的。非加密哈希对于检测故意篡改毫无用处。如果你使用的是现代加密哈希,那么在服务器场上找到一个与目标数据存在哈希冲突的数据集将需要几十年的时间。当你找到匹配项时,它肯定看起来不像是有效的DNS数据。当你找到一个合适的哈希冲突时,你所针对的原始数据几乎肯定已经发生了变化。
应用程序使用加密哈希来验证消息的内容是否没有更改。如果服务器发送的消息类似于对DNS查询的响应,并且包含消息内容的哈希,则收件人可以使用哈希来验证原始消息。哈希必须小心发送,以确保它没有被篡改。
使哈希更安全的一种可能方法是 salting (加盐)。盐是在计算哈希值之前添加到原始数据中的值。假设我使用 GiveLucasYourGelato
盐计算 2001:db8::f00d
的哈希值。我会根据字符串 2001:db8::f00dGiveLucasYourGelato
计算哈希值。您对每条明文使用不同的盐,盐是众所周知的。当DNSSEC使用盐时,盐会出现在DNS记录中。当Unix的 /etc/master.passwd 文件中出现盐密码(salted password)时,盐就出现在盐密码旁边。
虽然DNSSEC文档中提到了盐,但最近的研究表明,盐在这种应用中没有用。最近不鼓励在DNSSEC中使用它们。BIND 9.18将默认不使用盐。
Symmetric (对称)加密算法使用密钥将明文与密文进行转换。大多数算法使用相同的密钥来加密和解密文本。如果你有密钥并且知道算法,你就可以破译消息。通过对称加密交换的消息的机密性依赖于密钥的保密性。这是数千年来使用的传统加密算法。
一些算法使用两个不同的密钥进行加密和解密。这些 asymmetric (非对称)算法之所以有效,是因为密钥是非常大的数字,当非常大的数相乘时,它们的行为会很奇怪。两个匹配的密钥称为 keypair (密钥对)。调用密钥X和Y。拥有密钥X的人可以加密只能用密钥Y解密的消息,也可以解密用密钥Y加密的消息。反之亦然。但是,密钥所有者无法解密用自己的密钥加密的消息。
有两个不同的密钥,只在一起工作,创造了有趣的可能性。public key cryptography (公钥密码学)背后的想法是,你保留一个密钥的秘密,称之为 private key (私钥)。另一把钥匙,public key (公钥),你把它交给全世界。把它喷在墙上。把它放在你的网站上。或者,由于我们正在使用DNS,请将其列在DNS记录中。任何用私钥加密的消息都可以被世界上任何人读取。这会使信息保密吗?不。但它确实证明了加密消息的人可以访问私钥。如果只有一个人拥有私钥,则消息来自该人。如果有人想解密用她自己的私钥加密的消息,她还需要使用公钥。
在攻击者能够拦截消息之前,使用哈希来验证消息是很好的。如果我可以在传输过程中捕获您的消息,更改消息,并更改附带的哈希值以匹配新消息,则哈希值已失败。消息认证码(Message Authentication Code —— MAC)是一种使用只有发送方和接收方知道的对称密钥加密的哈希。开发人员可以选择任意数量的加密方法来创建MAC。
哈希消息认证码(Hashed Message Authentication Code —— HMAC)是使用定义的加密算法创建MAC的特定标准。每个都有一个名称,如HMAC-SHA256或HMAC-MD5。HMAC提供真实性和完整性。
当人们讨论密码学时,当他们指的是HMAC时,他们经常说“哈希”。这更容易说,许多经验不足的系统管理员不知道其中的区别,但你应该知道这是一种高度具体和明确的创建和管理哈希的方法。
将哈希与公钥加密相结合可以产生 digital signatures (数字签名)。数字签名的目标是确保消息是真实的——它来自签名的来源,没有改变。数字签名有很多组成部分,你不需要知道所有的,但它包括用发送者的私钥加密的消息的加密哈希。任何人都可以获取公钥并解密签名,然后计算自己的消息哈希值。如果哈希值匹配,则消息是真实的。
如果接收到的消息具有与数字签名不同的哈希,则签名无效。消息被更改或签名计算不正确。DNSSEC丢弃所有签名无效的数据。(当然,调试工具可以禁用验证并检查这些数据。)
DNSSEC的数字签名过期。现代名称服务器自动续订签名,无需系统管理员干预。即便如此,时钟偏差也会导致过期签名错误。如果名称服务器的时钟慢了一周,即使世界其他地方看到签名已过期,服务器在几天内也不会看到任何更新签名的需要。
你不需要自己计算数字签名。每个有价值的名称服务器都包含计算和验证签名的软件。BIND包括几个,如 dnssec-keygen(8)
、 dnssec-verify(8)
, dnssec-signzone(8)
和 delv(1)
。
数字签名是DNSSEC的核心,一个受DNSSEC保护的区域据说是被签名的 ( signed )。
每个区域至少有一个密钥对。此密钥用于对区域中的记录进行签名。父区域必须知道密钥对公钥的指纹。你需要一种方法来更新这些密钥。
密钥可以使用多个密钥或组合密钥进行管理。
DNSSEC密钥有多个相互冲突的要求。密钥必须定期更改,以阻止入侵者通过暴力计算私钥,但很少更改到与父域的必要交互不会乏味和麻烦的程度。此外,在DNSSEC的早期,密钥管理软件从笨重到令人恼火。应对这些相互冲突的要求的最佳方法是使用多个密钥(一些供应商称之为分割密钥),一个密钥持续时间长,另一个密钥更换得更频繁。
长期密钥是 Key Signing Key (密钥签名密钥),简称 KSK 。KSK仅用于对区域公钥的DNS记录进行签名。每个区域的父域都需要KSK公钥的指纹。域名注册商或RIR负责使用指纹更新父区域,但您必须通知注册商。
Zone Signing Key (区域签名密钥),简称 ZSK ,用于对区域进行签名。每个区域都有自己的ZSK。这是最常用的钥匙。
从本质上讲,您的DNS数据有自己的微小信任链。大部分DNS数据是用ZSK签名的,而ZSK本身是用KSK签名的。
现代DNSSEC包括向父域传递密钥翻转的标准。自动化允许将KSK和ZSK组合成组合签名密钥(Combined Signing Key —— CSK),有时也称为单签名密钥(Single Signing Key —— SSK)。使用具有自动化功能的CSK比使用两个密钥更简单,并提供了一个更简单的信任模型。
CSK在技术上有什么特别之处?没什么,真的。它被称为组合密钥,但它是角色和职责的组合。
组合密钥和多密钥都可以很好地与DNSSEC配合使用,自动化可以处理其中任何一种。你应该部署哪一个?
在大多数环境中,组合签名密钥(Combined Signing Key —— CSK)是完全足够的。
多个密钥对于入侵者和罪犯高度重视的区域非常有用。攻击者可能会试图从公开信息中对密钥进行反向工程(reverse-engineer)。精明的攻击者可以收集用特定私钥签名的所有数字签名,将其提供给服务器场,并研磨出相应的公钥。帮助此类攻击者的一件事是拥有大量已知明文的加密样本,这正是数字签名所提供的。DNS数据是公开的。大型区域有许多条目,通常属于足够大的组织,足以引起犯罪分子的兴趣。KSK只提供了几个示例。
像 .com
这样的区域通常使用单独的KSK和ZSK。像 mwl.io
这样的区域,我在那里托管我的博客并列出我写的书,没有那么多。每个区域都有自己的选择。英国的商业实体专区 .co.UK
使用CSK。
攻击者可以使用您的公钥,试图通过纯粹的暴力计算对您的私钥进行反向工程。这可能需要数年时间。Key rollover (密钥翻转)或密钥轮换(key rotation)会替换区域上的密钥,因此此类攻击者必须重新开始。如果私钥被泄露,您也可以轮换密钥。系统管理员不同意是否需要常规密钥滚动。目前,请理解密钥轮换是DNSSEC的一部分。
我们将在第7章讨论密钥轮换。
每当你查看公钥加密系统时,你应该问的第一个问题是“信任是如何分配的?”谁决定信任谁?DNS是非交互式的,因此排除了任何信任模型,如OpenPGP的信任网络。DNSSEC使用 trust anchor (信任锚),即根区域的可信密钥。名称服务器附带了信任锚,并有一个更新它的协议。
信任锚的使用方式与X.509证书和TLS的信任锚非常相似,但只有一个锚,而不是证书颁发机构的激增。递归名称服务器信任信任锚点,该锚点用于对根区域进行签名。所有支持DNSSEC的顶级区域,如 .com
、 .org
和 .uk
,其密钥都由根区域的密钥签名。这些子区域,如 isc.org
和 mwl.io
,其密钥由其父区域的密钥签名。这创造了一个 chain of trust (信任链)。
Trust Anchor ==》 Root Zone ==》 .io ==》 mwl.io
DNSSEC客户端自下而上建立信任。客户端在记录上看到DNSSEC签名,并前往父区域获取用于签名的密钥信息。如果它还不信任该密钥,它将获得链上的下一个密钥。最终,它会找到一个可信的密钥并验证结果——或者不验证。
假设你的解析器有一个空缓存,并在 www.mwl.io
上看到一个签名。解析器转到 mwl.io
并获取用于对该记录进行签名的密钥的公钥。密钥存在,但您的解析器不信任它们。它升级到 .io
并获取 mwl.io
的密钥信息。您的解析器还没有理由信任 .io
区域,因此它不信任这些区域。它前进到根区域并提取 .io
密钥上的记录。根区域中的记录由配置为解析器信任锚的密钥签名。现在,它可以通过构建从信任锚点到我的web服务器的信任链来验证原始请求。由于所有这些记录都在DNS中,您的解析器将缓存所有内容。当解析器被要求验证 www.embrogl.io
时,它已经知道并信任 .io
及其以上所有内容的公钥。它将从 embrogl.ia
名称服务器以及A和AAAA记录中获取密钥信息,并更快地验证所有内容。
你信任根,所以你信任根告诉你要信任的每一个人。DNSSEC允许您在链的每个环节验证信任。如果这些签名或密钥中的任何一个不匹配,则信任被破坏,验证失败。解析器拒绝该信息,并通知客户端没有这样的主机。第3章讨论了调试DNSSEC验证失败,包括一些关于一切如何中断的漂亮图表。
只有当其父区域使用DNSSEC进行安全保护时,域才能部署可验证的DNSSEC。所有通用顶级域(gTLD —— generic top-level domains)均已签名。大多数但并非所有顶级国家代码,如 .bb
和 .do
,都没有签名。未签名的中间区域会破坏DNSSEC。假设我有一个远程办公室来支持我的全球出版帝国,并委托给他们一个子区域 fiji.mwl.io
。斐济人想在他们的专区上签名。如果 mwl.io
未签名,则 fiji.mwl.io
无法签名。信任链将在最后签署的区域终止。你会得到未签名的答案。
子区域不必签名。.com
区域已签名,但许多公司尚未部署DNSSEC。相反,父域权威地声明不存在密钥。由于解析器信任父域,因此它接受该区域未签名,并向客户端提供未签名的答案。
DNSSEC使用的算法很少,仅次于SSH和TLS等协议。当前的标准RFC 8624列出了12种算法,如RSADM5、RSASHA256和ED25519。
Number Name Signing Validation
1 RSAMD5 MUST NOT MUST NOT
3 DSA MUST NOT MUST NOT
5 RSASHA1 NOT RECOMMENDED MUST
6 DSA-NSEC3-SHA1 MUST NOT MUST NOT
7 RSASHA1-NSEC3-SHA1 NOT RECOMMENDED MUST
8 RSASHA256 MUST MUST
10 RSASHA512 NOT RECOMMENDED MUST
12 ECC-GOST MUST NOT MAY
13 ECDSAP256SHA256 MUST MUST
14 ECDSAP384SHA384 MAY RECOMMENDED
15 ED25519 RECOMMENDED RECOMMENDED
16 ED448 MAY RECOMMENDED
每个算法都由一个数字和一个名称标识。该数字出现在DNS资源记录中,该名称是为人类准备的。然后,我们得到两列,一列表示是否应使用该算法对区域进行签名,另一列声明在验证区域时是否应信任该算法。在签名(Signing)和验证(Validation)列中,MUST、MUST NOT、MAY和NOT RECOMMENDED语句适用于软件实现者。
考虑算法1,RSAMD5。软件不得允许使用RSAMD5签名,也不得验证使用它签名的区域。这曾经是一个标准,但MD5算法不再值得信赖。DSA算法3与之类似。
算法5、7和10的Signing被标记为NOT RECOMMENDED,但客户端需要验证使用这些算法签名的区域。算法5和7使用SHA1,SHA1很弱,正在淘汰,但仍然有很大的安装基础。您的DNSSEC软件应该停止支持使用SHA1的签名区域,但您还不能放弃信任其他人的区域。在相关新闻中,其他人需要更新他们的软件。
算法8和13是当前软件必须能够签名并且必须能够验证的唯一算法。RSASHA256和ECDSAP256SHA256被认为是当前最佳实践的算法。RSASHA256使用历史悠久的RSA公钥,而ECDSAP256SHA256依赖于具有P-256曲线的新颖ECDSA椭圆曲线算法。两者都使用SHA-256计算哈希值。
算法14至16是未来标准的候选者。建议支持验证,同时鼓励支持签名。更广泛的测试将显示这些算法是否可行、有用,以及是否比当前标准有所改进。并非所有这些算法都将成为标准部署选项。考虑算法10,RSASHA512。它看起来不错,但实际上并不比RSASHA256好。
当您开始使用DNSSEC时,请使用算法8和13。人们争论哪个更好,但两者都足够了。让未来的光荣算法(Glorious Algorithms of the Future)为你的区域签名。
公钥加密的另一个关键细节是私钥的管理。任何拥有公钥的实体都必须保护其私钥。我们将了解根区域和各种顶级域如何管理其密钥,然后了解您组织的选项。
整个标准描述了信任锚私钥的管理。如果您阅读了互联网号码分配机构(Internet Assigned Numbers Authority —— IANA)提供的“根区KSK运营商的DNSSEC实践声明”,您将看到从存储私钥的物理环境到持有信任锚密钥的硬件安全模块类型的所有要求。信任锚私钥由互联网名称与数字地址分配机构(Internet Corporation for Assigned Names and Numbers —— ICANN)管理。信任锚用作密钥签名密钥(Key Signing Key),偶尔用于为根区域签名新的区域签名密钥(Zone Signing Key)。
信任锚的私钥从不在互联网上;它简直是气隙。使用信任锚私钥需要多个激活卡和PIN码,类似于计算机极客认为发射核导弹的程序应该是什么样子。仪式结束后,ICANN将新的ZSK提供给威瑞信(Verisign),威瑞信每天更新并签署根区域。互联网上有数百个根域名服务器,但它们都没有信任锚的私钥。他们有一个由信任锚点签名的根区域的副本,但仅此而已。
不要担心信任锚的私钥。担心你自己的。
你会如何保护你的私钥?密钥是一个文件。入侵者可以很容易地复制文件。更大的密钥保护需要更多的持续工作。你必须决定你愿意付出多少劳动来换取什么级别的安全。大多数软件套件,包括名称服务器,在启动时必须有可用的私钥。毕竟,这就是这些程序的目的——使用私钥执行有用的工作。系统管理员习惯性地将web和VPN软件的私钥存储在服务器上,以入侵者窃取密钥的风险换取轻松重启软件的能力。
伪造的DNS数据带来了不同程度的威胁。如果入侵者窃取了您的web服务器X.509证书的私钥,他们可以建立假装是您的网站。窃取您的DNSSEC私钥的入侵者可以将人们引导到她的流氓网站,并为您的所有公共服务发布公钥。她可以在DNS中发布SSH主机密钥,以便您的远程系统管理员相信她的蜜罐是您的网络。她可以将您的公司高管引导到她的VPN集中器,并让软件相信她是合法的。如果您的DNSSEC私钥被盗,则归您所有。
并非所有这些攻击都有用。并非所有SSH客户端都会在DNSSEC中检查主机密钥。也许你不使用DNS来分发VPN信息。但是,你的客户在悄悄地回到其他数据源之前,会检查DNS中的信息吗?你确定吗?记住,供应商的兴趣不在于提供最安全的配置;它提供了一种生成最少支持呼叫的配置。假设最坏的情况。
保护私钥有三种常见方法。你应该使用哪种取决于你的威胁模型。
Hardware Security Module —— 硬件安全模块(HSM)是最强大的保护。HSM是插入服务器硬件的物理设备。私钥可以存储在HSM上或从HSM中删除,但不能从HSM中复制。程序必须查询HSM才能访问私钥。入侵者没有可以复制的“文件”。HSM硬件可以像USB密钥卡一样小而便宜。如果你在金融机构工作,你的HSM可能是一个昂贵的机架式设备,装有炸药,如果你篡改箱子,就会引爆。
许多组织依赖于 stealth primary (隐形初选)。主DNS服务器在数据包过滤器或代理后面受到严格保护,可能位于私有地址空间中。它是唯一拥有私钥的名称服务器。公众无法访问任何服务的主服务器。所有提供公共服务的名称服务器都是主服务器的备份。次级机构不需要它们所服务的区域的私钥。如果公共名称服务器受到攻击,私钥是安全的。
最后,nothing ,什么也不做。将私钥存储在名称服务器上,除了文件系统权限之外没有任何特殊保护,当然是一种选择。这甚至可能是一个受欢迎的选择。但这是最危险的选择。如果你选择将私钥保存在公共名称服务器上的文件中,任何闯入你的名称服务器的人都有密钥。在现代互联网上,问题不在于是否有人会闯入你的服务器。问题是:什么时候会发生,你会注意到吗?
你应该使用哪一种?这取决于你的组织。如果你的个人域名将密钥保存在主域名服务器上,也许没问题。一个足够大的组织有一个服务器场,可以负担得起HSM。作为一名拥有30多年Unix经验的系统管理员,我对任何涉及爆炸物(explosives)的事情都有偏见。
说到爆炸(blowing things up),让我们继续讨论DNSSEC使用的新记录类型。