Geoff Huston APNIC首席科学家
互联网早期的特点是技术的不断更新。例如,路由协议接二连三地出现和消失,传输技术处于不断变化的状态,我们用来与新兴数字环境交互的设备正在变化,我们使用的应用程序也在变化。因此有些令人惊讶的是,至少有一个协议在互联网四十多年的发展中保持相对稳定,那就是域名系统(DNS)和相关的DNS解析协议。
也许我们可以将传输协议UDP(用户数据报协议)和TCP(传输控制协议)也放入同一类协议中。在互联网协议中,它们肯定是最古老的协议之一,并且今天仍在大量使用。这是对这些协议基本设计的肯定,虽然网络和它的使用者已经增长了十亿倍甚至更多,但这些协议基本上保持不变。
通常引用的DNS规范是两个RFC,RFC1034,“域名——概念和设施”,以及RFC1035,“域名——实现和规范”,它们都发表于1987年11月。然而,这两个核心规范只是一个相当大规范集合的冰山一角。涉及DNS的RFC协议大概有292个。这意味着声称DNS在这四十年期间基本不变有点牵强,但无论如何,DNS的基本原理是不变的。这些额外的292个RFC说明了我们在这四十年中花了大量的时间和精力来修补DNS协议的边边角角!
在DNS发生的这些变化中,我必须提名DNS安全框架——域名系统安全扩展(DNSSEC)作为最重要的DNS创新。DNSSEC将数字签名添加到DNS资源记录,允许客户端解析程序确认DNS应答的真实性。你可能会认为,随着人们对互联网攻击的广泛认识,让用户验证从DNS查询收到的响应的任何行为都将被视为向前迈出的一大步,我们都会主动要求使用它。
但现实是,人们对DNSSEC的热情并不高。递归DNS解析程序的管理员并不愿意添加解析步骤来请求DNS记录的数字签名并对其进行验证,同时在网络终端节点很少有DNS存根解析程序提供类似的功能。在签名侧,将DNSSEC签名添加到DNS域的做法同样不受欢迎。准确计算互联网中所有域名的数量实际上是不可能的,因此精确计算有DNSSEC签名的域名百分比同样是一个具有挑战性的问题。DNSSEC社区一致认为,大约只有10%的DNS域名是经过DNSSEC签名的。
人们为什么对DNSSEC的反应如此缺乏热情?
DNSSEC已经存在了足够长的时间,所以对DNSSEC的无知不能成为借口。那些不在自己的管理域上签名的域管理员肯定有自己的理由。
对于是否启用DNSSEC签名和验证,似乎有很多不确定性。一些解析器运营商似乎已经接受了DNSSEC,包括由Google和Cloudflare运营的大型开放解析服务网络。另一方面,有许多解析器不执行DNSSEC验证。APNIC实验室对DNSSEC验证率的测量表明,如果已签名的DNS名称的DNSSEC签名无法验证,大约30%的用户将不会加载URL(图1)。
图1 DNSSEC验证比例
那么,DNSSEC是个好主意吗?或者仅仅是事倍功半的努力?为什么亚马逊和微软没有为域名部署DNSSEC协议?为什么美洲银行网站、汇丰银行网站没有为其网站域名添加DNSSEC签名?相关在线服务用户的安全性完全依赖于域名可验证的真实性,你可能会认为,能够验证域名到IP地址的DNS映射将是保证其在线服务真实性不可避免的第一步。然而,许多域名并没有DNSSEC签名。
我认为,没有一个明确的答案来回答这个问题,即,使用DNSSEC来签署域名是否是一个好主意。虽然DNSSEC提供了一个更有弹性和更可靠的DNS服务,让用户可以信任他们收到的DNS解析答案与当前域名权威域的内容完全匹配。但这是有代价的,在DNS域中添加DNSSEC签名和在DNS响应中验证这些签名的增量成本是否值得,是一个需要讨论的问题。
让我们从“是”与“否”两个方面来看看是否要对DNS域名进行DNSSEC签名。
DNSSEC值得吗?“不!”
我们很容易将DNSSEC看作是DNS中的又一个错误设计。对于DNS域管理员,DNSSEC又增加了一组域管理任务,包括添加密钥管理、定期密钥更新、密钥滚动以及与父域/委托域(parent zone/delegated zones)的密钥协调。鉴于即使是简单的域委托或者域配置在大部分DNS服务器中都会被错误配置,那么将加密密钥和数字签名管理元素添加到管理任务集中,只会增加那些选择DNSSEC对其域进行签名的人无意中出现域名故障的可能性。
对全域进行签名是首先要考虑的一个问题。全域签名在较小的域中可能很简单,但对于较大的域,即使将整个域作为一个文本文件的快照映像进行签名也是一项巨大的挑战。许多较大的DNS域都会不断更新,而整个DNS域的签名操作要求对更新进行批处理(冻结已签名的域内容,直到下一次计划的更新和签名操作)。
这种操作实践可能不适用于具有大量客户端的大型DNS域,因为这些客户端对更改条目的及时性有不同的需求。许多DNS域利用了动态签名的优势,该区域的DNS服务器和DNSSEC签名前端分别运行,如果查询请求DNSSEC凭据,则将响应从DNS服务器传递到DNSSEC签名前端,并将数字签名记录作为最后步骤添加到DNS响应中。
NSEC记录(Next Secure Record,下一个安全记录)为DNSSEC添加了新的挑战。通常NSEC响应会列出与名称相关的所有资源记录,包括请求域名记录不存在时,域中排列的下一个记录名称。NSEC记录可以通过负向查询(不存在的记录)对域中内容进行枚举攻击。这给某些DNS运营商带来了一些问题,他们出于商业或安全方面的原因希望将域内容保密。
这个问题导致了NSEC3记录的开发,它使用基于散列值的域标签排序来避免枚举攻击,但散列函数增加的复杂性比实际情况好很多,因为在当前的计算能力下,破解这个散列函数是可行的。最近拟议的NSEC5记录将增加更多的复杂性对抗区域枚举的脆弱性风险,但这一提议尚未引起广泛关注。
还有一个问题,就是如何在DNSSEC签名的区域保障服务的健壮性。传统的方法是使用许多与主服务器配置相同的方式运行的辅助服务器,它们可以通过共享当前DNS域配置文件的副本来实现这一点。
在使用DNSSEC的条件下,共享主服务器已签名的DNS域文件的副本是最简单的方法,辅助服务器不需要知道该DNS域的区域签名密钥(ZSK)以及DNS域的密钥签名密钥(KSK)的私钥信息。但是,如果使用前端动态签名器,则所有这些签名前端都需要配置ZSK私钥。
如果所有这些域名记录签署都由同一个实体操作,那相对简单;但如果区域管理员使用不同的实体来操作辅助域名服务器系统,那么就需要将ZSK公钥集合放入域的DNSKEY(DNS Public Key,域名公钥)记录中。这样就会增加DNSKEY记录的大小,而DNSSEC响应记录大小是DNSSEC的主要问题之一,大型DNS响应记录会影响DNS的可靠性和性能。
最早的UDP协议上的DNS响应记录大小为512字节。添加DNSSEC数字签名会导致DNS响应大小超过此限制,因此DNS查询程序需要使用EDNS(DNS扩展机制)扩展来表示它们处理大型UDP响应的能力。
但是DNSSEC可能会导致响应记录超过IP报文最大传输单元(MTU)的限制(1420字节的IPv4报文或1400字节负载的IPv6报文),从而需要使用IP分片进行报文传输。但是IP分片会让请求者暴露于DNS缓存中毒攻击的风险,并且在IPv6协议下可能需要重传报文,导致更大的时间延迟。
另一种方法是截断响应转为TCP协议传输。但是TCP协议需要花费多个传输往返时延(RTT)的时间来建立握手和传输数据,同时并不是所有的客户端都支持TCP协议下的DNS,这会带来更大的不可靠性。
然而,花费在处理大型DNSSEC响应报文上的额外时间并不是唯一的问题,DNSSEC的验证功能也需要额外的时间。为了验证DNSSEC记录的真实性,客户端需要沿着签名链一直向上验证到根域的签名者,这意味一个DNSSEC记录的验证需要产生大量的DNS查询。
如果不进行解析结果的缓存,则需要将每个父域的DNSKEY和DS(Delegation Signer,委托签名者)记录组合起来进行验证,这将带来无法克服的时间损失。大多数终端系统不直接执行DNSSEC验证。他们依赖DNS解析器来代表他们执行DNSSEC验证,并且默认信任(implicitly trust)解析器以适当的完整性级别执行此操作。但这里带来的问题是,在终端主机和验证解析器之间的中间人攻击仍然可能有效——终端主机没有验证DNS响应,因此无法检测响应是否为真实响应或是否已被篡改。
以上所有问题都说明了DNSSEC在设计或操作上并不简单。在错误发生的时候,要纠正的地方很多,而容错的地方很少。这增加了DNS的脆弱性。
还有一个棘手的问题——DNSSEC保护你免受什么威胁?最初的教科书上的答案是保护解析器不受所谓的“卡明斯基攻击(Kaminsky attack)”,这种攻击将恶意数据注入递归解析器的缓存中。DNSSEC当然可以提供针对这种攻击的保护,但仅限于有限的情况下。正如我们已经观察到的,DNSSEC可以保护递归解析器,但是不验证DNSSEC记录的客户端存根解析器仍然像以前一样容易受到攻击。
因此,这不是一个全面解决问题的办法。如果DNS响应未能通过DNSSEC验证,DNS将不会通知客户端“正确”响应可能是什么。它只是保留无法验证的响应,并将其留给客户端决定下一步要做什么。
DNSSEC反应的成本是否与威胁的性质相称?从负面的角度来看,DNSSEC还不成熟。它并非安全性和DNS功能的完美结合,而是一种相当笨拙的调整,以一种不舒服的方式放置在DNS之上。DNSSEC的增量成本和脆弱性远远超过了从一个相当模糊的威胁模型中减轻风险的潜在好处。
但也许我夸大了“不”的理由。DNSSEC的采用对用户和整个互联网都有非常现实的潜在好处。让我们看看这个话题的另一面。
DNSSEC值得吗?“是的!”
互联网安全的总体情况是相当糟糕的。当用户识别屏幕上的URL,点击它,并相信呈现的网站是用户打算访问的真正服务,这中间的路径依赖于相当多的盲目信任。我们相信DNS将域名映射到的IP地址是真实的,相信路由系统将IP数据包传递到“正确的”终端,相信屏幕上的网站名字是你打算访问的服务,相信TLS(安全传输层协议)连接是真实的,相信你从未见过的人永远不会撒谎,而这只是一大堆盲目信任中的几个例子。
这些关系和行为中不透明的信任都是以诚信为基础的,无法被审计,也不能被曝光。我们只能希望每个人的行为都是出于最好的意图。但当我们把越来越多的个人和社会功能放在一个由计算机连接的世界里时,我们对互联网的完整性的依赖也越来越大,而无论是高级黑客、犯罪团伙,都具备颠覆互联网基础设施运行的能力,并可以造成相当大的破坏。
那我们现有的强大的名称基础设施和TLS证书难道没有任何意义吗?在我看来,DNSSEC存在的理由在于现有互联网名称基础设施信任模式的弱点。
现有的信任结构基于域名的X.509公钥证书,它试图在域名、域名持有人和公钥/私钥对之间建立联系。如果客户端使用域名作为DNS查询的关键字,并使用响应结果的IP地址连接到服务器,那么只要服务器能够证明它知道与这个域名相关的私钥,域名证书就能向客户端保证它已经到达域名持有人提供的与这个域名相关的服务站点。
在这种形式的认证中,用于访问该服务的IP地址其实是不重要的。TLS协议的安全握手过程向客户提供了服务的公钥、域名证书和用服务的私钥生成的“谜题”,向客户提供了它已到达真实服务的保证。客户端并不是简单地信任这些提供的信息,它也被预先配置了一组可信的证书颁发者(认证机构)的公钥集合。只要客户端能够验证所提供的域名证书是由这些受信任的证书颁发者之一颁发的,那么它就能够相信服务站点的真实性,认为它“属于”这个域名。
这里的问题是,实际情况比设想的要糟糕的多。每个客户端有数百个受信任的证书颁发者,每一个颁发者都能够为任何域名颁发数字证书。如果任何一个证书颁发者被入侵并颁发假证书,那么这些假证书与所有其他合法颁发的真证书之间是无法区分的。只要一个证书颁发者被包括在客户信任的颁发者集合中,那么客户就无条件地信任这个颁发者,并无条件地接受其颁发的所有证书是真的。
因此,我们有一个“最薄弱环节”:域名持有者使用的证书颁发者的工作有多好并不重要。重要的是一组证书颁发者中最不可靠的那一个的工作质量;只要有一个证书颁发者被破坏了,那么它就会被迫为任何域名颁发假证书。
还有其他一些因素也破坏了对域名证书框架的信任。第一个因素是价格的侵蚀。人们一直在努力降低证书的价格,理由是为在线服务提供安全保障不应该是少数人可以获得的昂贵的奢侈品,而应该是普遍可以负担的商品。
例如,Let's Encrypt运营的自动门户提供的免费域名证书已经将这一点推向了极端。这些免费服务只需要申请人证明他们可以将指定记录添加到相关的域名区域文件中,或在域名的网站空间内生成一个URL页面。这些免费证书的合法性等同于任何其他域名证书,而入侵网站或者DNS域服务器修改文件就可以导致假域名证书的颁发。
第二个因素是,尽管证书撤销可以减轻假证书带来的风险,但证书撤销不再被普遍支持。在证书撤销过程中,证书颁发者会定期公布一个不应再被信任的证书序列号列表。当客户验证一个证书时,它应该查阅证书颁发机构(CA)的证书撤销列表(CRL),检索这个CRL并通过其签名验证其内容,然后在这个列表中查找该证书的序列号。
如果在CRL中找不到它,说明该证书没有被撤销,或者更准确地说在CRL创建(一般是过去几天)时,它还没有被撤销。撤销证书的数量越多,CRL就越大。对于一个大型CA来说,提供所有废止证书的完整列表似乎是一种过度的回答,特别在查询者只是想知道单个证书的废止状态的情形下。另外,生成CRL并不是对CA的一项强制性要求。CA可以选择定期发布CRL,也可以选择发布增量CRL更新,或者根本就不发布CRL!由于这些原因,终端客户在建立TLS会话时通常不使用CRL。
取而代之的是,我们要使用在线证书状态协议(OCSP)。OCSP会在证书中插入一个OCSP URL,客户端连接到这个URL,并向其发送要检查的序列号,URL的响应给出该证书已被撤销或者未被撤销。然而,OCSP实际情况也很糟糕。在客户端与CA联系的过程中,OCSP存在隐私问题,因为CA通过OCSP请求的来源知道客户端使用该证书的身份,并知道客户端在何时使用该证书。
每次客户端需要访问证书的OCSP数据时,不仅有隐私泄漏的问题,而且还存在生成OCSP请求和等待响应的额外时间的性能问题。OCSP有时不是一个请求,而有可能会是整个证书验证链上的多个请求,这会导致更大的性能消耗,而查询结果还不是当前的撤掉状态,仅仅是CRL建立或更新时的撤销状态。
然后,我们转向了“装订式OCSP(Stapled OCSP)”,即服务器代表客户端进行OCSP检查,并将签名的OCSP响应与证书一起发送。但如果证书在生成CRL时没有被撤销,那么,如前所述,OCSP报告的状态是好的,这对证书中已经包含的信息来说没有任何增加。
如果证书被撤销,那么CA就是在说,这个证书不应该被使用。如果是这样的话,那么服务器为什么要把证书和OCSP状态传达给客户,并让客户决定不继续进行TLS连接?为什么服务器不应该简单地立即终止TLS连接?换句话说,服务器为什么要把一个被撤销的证书传递给客户以达到TLS连接尝试失败的必然结果?
证书撤销是否值得努力?Chrome浏览器已经得出结论:不值得。对于那些以虚假借口颁发的有效证书,或者被泄漏的密钥,我们又能做些什么呢?事实是我们什么也做不了。这里没有通用的解决方案,每一种撤销证书的方法都代表着某种程度的妥协。
我们可以接受具有高注册成本的长寿命证书,但前提是我们能够支持强大而快速的撤销机制,而这一点至今仍是一个难以实现的目标。CRL和OCSP不是即时反应,尽管它们都可以减少因私钥被破坏而产生的漏洞的影响时间,但是CRL和各种类型的OCSP都有一些明显的鲁棒性问题。
我们可以沿着Let's Encrypt的道路前进,只使用由高度自动化程序生成的短期证书(这里的“短期”仍然有90天之长!)。鉴于它们的寿命很短,撤销并不是一个大问题,而且可以考虑更短的证书寿命。
但是,如果我们沿着这条短期证书的道路前进,那么为什么还要使用X.509封装证书呢?为什么不把在DNS中包装OCSP响应的方法再往前推一步,完全不使用X.509封装,而把整个公钥基础设施放到DNS中呢?我们当然可以朝这个方向发展,但要做到这一点,需要将DNSSEC应用到DNS中来保护这些信息。
现在可以总结一下证书提供的安全框架和DNSSEC提供的安全框架之间的本质区别。
域名证书框架使用分布式信任框架,证书可以由任何CA签发。这个框架中每个证书的健壮性基于系统中最薄弱CA的安全性,而这已经在过去引发了一系列安全问题。相比之下,DNSSEC的信任框架是基于单一的私钥,即根区的KSK。
域名证书可由发行人撤销,但撤销状态检查已被证明在操作上具有挑战性。实际的应对措施是将签发的证书的有效期限制在几个月内,并免去撤销检查。底层的DNS框架被设计为迫使DNS信息的持有者定期检查他们的缓存信息的有效性。在DNSSEC框架中,数小时或数天的缓存寿命都是可行的。
域名证书是对域名授权状态的一个独立证明,而DNSSEC是DNS本身的一部分,安全证书是DNS名称的一个属性。
在我看来,使用DNSSEC的理由在于,DNSSEC是一种更统一的向域名添加可信凭证的方式,其中凭证的属性与名称本身的属性密切相连,而通过域名证书证明这种密切联系的挑战则要大得多。DNSSEC的问题在于DNS协议被设计成处理按需轻量级查询/响应的交易集合,没有考虑如何有效地处理大的DNS协议载荷,也没有考虑如何在查询中指定相互关联的关系(如按需验证)。
现在呢?
不要小看一个强大而稳定的域名基础设施的作用。由于证书发放行为对网络的可信度造成了很大的冲击,现有的证书透明度、HTTP公密钥绑定(HPKP)以及证书权威认证(CAA)等认证机制并没有得到很好的应用。现在的问题在于,我们到底是否愿意为域名公钥基础设施投入更多内容,还是要换一种方式,彻底抛弃这种由第三方提供的安全性。
从理论上来说,将一个域的安全性证书放入DNS,并把域名持有人的公钥当作域名的一个属性,这样才能避免通过第三方(域名证书)对域名进行安全验证。目前看来,DNS中的域名密钥(DANE,基于DNS的域名身份认证协议)方案是我们对这个问题的最好回应,这意味着我们需要有一个可信任的DNS,用户可以验证DNS数据是否真实,而DNSSEC是我们目前知道的实现这一目标的唯一方法。
在TLS中使用DANE协议,可以采取OCSP装订的方式,将服务器的公钥响应作为DANE资源记录,然后将DNSSEC签名和相关的DNSSEC验证响应作为链式扩展数据块一起装订。如果客户端直接使用DNS,那么这些记录将出现在DNS查询响应的数据集合中,但在使用OCSP装订的情况下,服务器将收集这些数据并在TLS握手过程中传递给客户端。
DANE方法的优点是在本地证书自治域内支持更短的证书时间管理。执行OCSP装订的服务器受到DNS本地缓存生命周期(TTL)的限制,并需要在这个时间间隔内刷新DNS数据。同时,因为是服务器而不是客户端装订数据,客户端的身份和查询的域名不会暴露给DNS服务器。
但是,前文讨论的DNS报文过大的问题仍然没有解决。那么,我们可以避免大的DNSSEC响应报文,同时继续使用DNSSEC吗?令人惊讶的是,至少在某种程度上答案是“可以”。目前我们在DNSSEC签名中常用的算法是RSA算法。RSA是一种基于素数运算的加密算法,使用模运算和可变长度的密钥进行加密和解密。较短的RSA密钥在加密和解密方面更有效,但不那么鲁棒。较长的密钥使用起来更昂贵,但针对破解攻击提供了更好的鲁棒性。
这种使用越来越大的RSA密钥的趋势导致人们试图摆脱素数密码学,并寻找其他数学函数,包括椭圆曲线。椭圆曲线函数ECDSAP-256允许所有的DNSSEC资源记录,即RRSIG(Resource Record Signature,资源记录签名)、NSEC(3)、DNSKEY和DS记录,这些记录在大多数情况下都在512字节以下(密钥滚动期间例外)。所以如果我们使用椭圆曲线加密算法,就可以避免大型DNSSEC响应。
根据目前的估计,使用P-256曲线的ECDSA算法强度与带有3072位密钥的RSA大致相当。256位的ECDSA密钥比3072位的RSA密钥短得多,同样,ECDSA的签名也比RSA的签名短得多。这一点很重要,因为DNSSEC同时存储和传输密钥和签名。虽然椭圆曲线加密算法可以让DNSSEC签名的响应在UDP上以非分片的报文进行传输,但执行DNSSEC验证所需的时间问题仍然存在。DNS协议的按需“及时(just in time)”模式是20世纪80年代有限的计算和通信环境的产物。
而在一个计算和通信资源丰富的环境中,可以考虑一种新的服务模式:预先计算好响应报文的内容,“以备(just in case)”客户可能会问到这些信息,这就是使用DNS链扩展模型背后的想法。服务器将签名后的DNSKEY和DS资源记录的完整集合与域名权威服务器的记录签名结合起来,以备客户端要求提供与DNS响应相关的DNSSEC凭证。在这种情况下,服务器可以立即响应整个集合,客户端可以立刻验证签名,而不需要再执行新的DNS查询。
使用UDP报文来传输这种DNSSEC数据并不适合,而且可能会导致拒绝服务(DoS)攻击的发生。在使用DNSSEC链式扩展的背景下,使用DNS-over-TLS(DoT)或DNS-over-HTTPs(DoH)进行传输,在TLS证书交换中装订属性以方便使用DANE作为CA证书固定的措施,都具有更大的意义。
我们还需要完善DNS错误代码以明确标识DNSSEC验证失败的情形,这可以防止现有SERVFAIL(解析失败)错误代码下的解析器重新查询行为。我们也正在努力使终端主机具备DNSSEC验证能力,这样终端主机就不会依赖主机和其DNS解析器之间不受信任的(和脆弱的)连接。而且我们不要忘记,DNS中的缓存是非常有效的。DNSSEC中的数字签名的缓存方式与地址记录的缓存方式相同,因此,如果相关的资源记录已经被保存在本地缓存中,那么经过验证的DNS名称的解析就不会有额外的时间成本。
如果没有一个安全和可信赖的互联网名称基础设施,互联网的前景看起来就没有那么好。DNSSEC并没有提供一个完整的答案,但它看起来确实是一个强大的、安全和可信任的互联网的基本要素之一。也许这就是我们采用它的充分理由。我们可以而且应该在该技术上做出努力,让DNSSEC更加有效,使用起来更加方便快捷。但我们不应该让“完美(perfect)”成为“好(good)”的敌人。
等待一个“更好的(better)”DNSSEC是没有意义的。我们将无限期地等待,而攻击数字基础设施的问题则将持续存在。另一个选择是,简单地使用我们手头的东西,并充分运用经验进一步努力,以加强DNS并建设更强大的互联网基础设施。
总结
应该用DNSSEC签署你的域名吗?答案在于了解你的保护目标。如果保护域名映射到IP地址对你来说至关重要,那么DNSSEC在某种程度上无疑可以做到这一点。如果保护DNS域免受干扰和操纵很重要,那么DNSSEC在某种程度上也可以做到这一点。这里的限定条件是,DNSSEC无法防止任何第三方对DNS响应的伪造攻击,但它可以检测何时发生此类攻击,并在这种情况下拒绝DNS响应。
其次,DNSSEC对DNS信息真实性的保证依赖于客户端(或客户端的代理)使用DNSSEC进行验证。如果客户端没有验证DNSSEC签名的DNS响应,那么客户端就无法提供更好的安全性。
第三,客户端需要能区分DNSSEC验证失败和其他的DNS解析错误原因。当DNS解析框架使用默认的SERFAIL错误代码来返回DNSSEC验证错误状态时,DNS系统会花费更多时间寻找能提供答案的服务器。
最后,只要客户端主机中的DNS解析器不直接执行DNSSEC验证,那么当响应从验证解析器发送到客户端时,客户端仍然容易受到DNS欺骗的攻击。
我们可以采用更宏观的视角,提出DNSSEC应该部署在哪里以及为互联网环境带来哪些好处的问题。在广泛采用执行服务器身份验证的安全传输会话之前,互联网应用程序和服务的基本常见假设是,如果客户端将数据包地址发送到“正确”的目标地址,那么它将获得“正确”响应。在这样的框架内,保护从名称到IP地址的映射很重要。如果攻击者可以以客户端无法检测到的方式提供备用IP地址,那么客户端将认为替代IP地址是该服务的“正确”服务交付点。
网络环境在很大程度上消除了这种非常幼稚的假设,特别是浏览器在要求服务器执行TLS握手方面更加严格,要求服务器以域名证书和签名数字对象的形式提供证书,允许客户端使用第三方信任锚来验证该服务确实是客户端正在寻求的命名服务。在这种环境下,名称到IP地址的真实性不再是关键。
如果服务器能够提供适当的证书,那么客户端将接受服务器为服务的真正实例,而不考虑用于到达该服务的IP地址。如果DNSSEC所能做的只是保护从名称到IP地址的映射,那么它所提供的服务在今天的服务环境中基本上是不合时宜的。
也许所有选择不对其域名进行DNSSEC签名的网站都是明智的,可以避免当DNSSEC签名被封装到DNS响应时带来的问题,也避免了客户端花费额外的时间来验证这些DNSSEC证书。如果有假的网站试图来劫持域名,TLS协议的握手过程都会检测到这种攻击尝试。
虽然域名PKI(Public Key Infrastructure,公钥基础设施)代表了当今互联网安全框架的基础,但这并不意味着它在所要实现的目标上总是有效的。这个PKI中高度分布式的信任模式,以及缺乏CA固定的有效手段,意味着任何一个被破坏的CA都可以破坏任何服务的真实性,而且这种行为基本上不会被终端客户注意到。
缺乏一个有效的证书撤销模式意味着当一个证书不应该被信任时,大多数客户端根本不会进行任何形式的撤销状态检查。企业环境往往要求主机增加本地维护的受信任CA集合,这反过来又意味着基于主机的恶意软件可以通过向本地受信任CA集添加流氓CA来创造额外的攻击载体。证书系统已经采取了一系列的措施,如通过HPKP记录、CAA记录和证书透明度来锁定CA,但这些举措并不是对这些问题的有效对策。
我们怎样才能在域名PKI框架中解决这些问题?怎样才能提高现有PKI的稳健性?正是在这种情况下,DNS重新进入了视野,DNSSEC也随之成为解决方案。通过使用DANE,DNS可以让客户端只加载受信任CA发布的证书,解决CA固定的问题。或者DNS可以让TLS只加载应该使用的终端实体证书(或其公钥),以解决CA固定和证书撤销的问题。
或者,DNS可以提供TLS应该使用的自签名证书或公钥,这样就绕过所有现有的域名PKI验证检查。虽然DANE选项可以解决TLS的缺点,但它们也存在一些新的问题。为了信任这些DANE记录,当务之急是使用DNSSEC签名DNS中的这些DANE记录,并要求TLS客户端直接执行DNSSEC验证。
但考虑到在TLS握手中加入任何形式的DNS查询都是完全不现实的,我们需要使用OCSP所使用的信息“装订(stapling)”方法。在这种方法中,额外的信息和所有应该用来验证这些信息的数据都被加载到TLS握手中。我们需要考虑如何应对从TLS服务器握手数据包中删除这些信息的降级攻击,目前提议的方法是,要求在签署的终端实体证书中用一个标志位来进行DANE验证。
如果这是DNSSEC的唯一用途,并且我们改变了DNS客户端的默认查询设置,不在传统DNS查询中继续使用DNSSEC,那么情况就会好得多。如果DNSSEC仅被用于传统DNS查询/响应交易之外的证书相关装订记录查询,那么DNSSEC的缺陷将被避免,而TLS握手过程中的证书验证性能将不会受到任何重大影响。
因此,有了DANE,我们知道需要做什么来解决TLS现有域名证书框架的漏洞问题,而这种DANE方法必然包括在非查询模式下使用DNSSEC。但是,我们会往那个方向前进吗?我们会看到集成了DANE和DNSSEC装订信息的TLS实现吗?或者我们愿意继续容忍现有PKI框架的漏洞,因为利用这些漏洞的成本比在TLS中加入新的验证框架和在DNS空间中加入DNSSEC更容易?
我认为,这个问题是DNSSEC未来前景背后的关键问题。
作者:Geoff Huston(APNIC首席科学家)
来源:APNIC
节译:杨望
责编:项阳