简单理解DNSSEC与DNSCurve/DNSCrypt

本文基于署名-非商业性使用 4.0 国际 (CC BY-NC 4.0)发布,转载请注明出处。

以下内容是我个人的理解,为了通俗我尽可能把专业名词用通俗的话解释出来。
如有错误还请大佬指正,非常感谢。

我曾经有过这样的疑惑,不是说DNSSEC(域名系统安全扩展)可以确保数据的完整性么..

那为什么即便域名正确配置了DNSSEC后还能被墙污染呢?

还有既然已经有了DNSSEC那我们还需要DNSCurve/DNSCrypt干嘛呢?吃饱了撑的么?

太长不看版:

DNSSEC有点像使用PGP去签名文件(注意我这里用的是签名不是加密)或者更通俗一点的说法就是给软件安装包加上数字签名。
而DNSCurve/DNSCrypt则相当于用https去传输未签名的软件安装包。

解释:

打一个简单的比方,如果我们把下载软件安装包的过程比作DNS查询的过程

那么使用DNSCurve/DNSCrypt技术去查询DNS就相当于通过https去下载软件安装包,这个过程中间人能看到的只是一堆经过加密的乱码。无法得知用户在下什么软件,但只要他乐意即使中间人并不知道会话的加密密钥也可以瞎J8改加密后的数据流,虽然中间人并不能随心所欲控制用户解密后得到的结果,但是这样可以破坏掉发送者发出的原有数据的完整性。而用户并不知道他所接受到的数据是不是就是发送者所发送的数据。

而DNSSEC相当于给这个软件的安装包加上了一个数字签名。但是如果只有DNSSEC本身的话那么这个软件包就是通过http来传输的。中间人知道用户在下什么东西,也可以随便修改这个软件包。但是用户收到数据之后一校验数字签名就能知道他收到的数据不是发送者发出的原始数据,是被改过的。但由于数据是明文传输的,中间人可以伪造出一个修改过并且不带数字签名的软件安装包完全替换掉发送者发出的那个。或者干脆阻止这个连接,破坏可用性。

其实DNSSEC和现在的证书机制很相似,都是PKI的一种应用。

所以说最好的方案还是通过https去下载一个经过数字签名的软件安装包。这样可以保证下载到的东西就是纯天然无污染的qwq 对应到DNS的话就是DNSSEC和DNSCurve/DNSCrypt配合起来一起用。

墙污染DNS(假设域名正确配置了DNSSEC)的原理:

先不考虑国内公共DNS有几家是支持DNSSEC的,假设都支持DNSSEC好了。

下面我们来模拟一下DNS查询的过程

正常情况(未被污染的域名):
root@xxx:~# dig paypal.com  @8.8.8.8 +dnssec +trace

; <<>> DiG 9.9.5-9+deb8u13-Debian <<>> paypal.com @8.8.8.8 +dnssec +trace
;; global options: +cmd
.            39575   IN  NS  a.root-servers.net.
.            39575   IN  NS  b.root-servers.net.
.            39575   IN  NS  c.root-servers.net.
.            39575   IN  NS  d.root-servers.net.
.            39575   IN  NS  e.root-servers.net.
.            39575   IN  NS  f.root-servers.net.
.            39575   IN  NS  g.root-servers.net.
.            39575   IN  NS  h.root-servers.net.
.            39575   IN  NS  i.root-servers.net.
.            39575   IN  NS  j.root-servers.net.
.            39575   IN  NS  k.root-servers.net.
.            39575   IN  NS  l.root-servers.net.
.            39575   IN  NS  m.root-servers.net.
.            39575   IN  RRSIG   NS 8 0 518400 20170823170000 20170810160000 15768 . GTkQYZZf/MnllTvZFy6y0GTd516lSYJUvNP/oyL4TWDiKcPUy7q8Wn9A yaz6RmnnrB/qx+pEAH9Mg+OHOKRizBc8GRNSEK8YiNotoN3RwO3wAfhb uAkfc60TvM82vav+VERAnICi9UA8kn1J63+/8Av1zoU1gnLqs+c400Y8 fg5qIoBuwdhcNRgvW8acHFQ1HXiAno9OSqmftb1jYL5AyXhmj1k8h6Ec /+1bmPobSBe8n6CrdBLYz80i3KNO1CJIHunETQKopj+YAiQTLqkZRguw 0FYWbD0y9EercWimNHTqyRa/PrU126Jr7IIT9BEcUjX0qE2XMrX4mOPJ 7gFr0A==
;; Received 525 bytes from 8.8.8.8#53(8.8.8.8) in 392 ms

com.            172800  IN  NS  a.gtld-servers.net.  
com.            172800  IN  NS  b.gtld-servers.net.  
com.            172800  IN  NS  c.gtld-servers.net.  
com.            172800  IN  NS  d.gtld-servers.net.  
com.            172800  IN  NS  e.gtld-servers.net.  
com.            172800  IN  NS  f.gtld-servers.net.  
com.            172800  IN  NS  g.gtld-servers.net.  
com.            172800  IN  NS  h.gtld-servers.net.  
com.            172800  IN  NS  i.gtld-servers.net.  
com.            172800  IN  NS  j.gtld-servers.net.  
com.            172800  IN  NS  k.gtld-servers.net.  
com.            172800  IN  NS  l.gtld-servers.net.  
com.            172800  IN  NS  m.gtld-servers.net.  
com.            86400   IN  DS  30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766  
com.            86400   IN  RRSIG   DS 8 1 86400 20170826050000 20170813040000 15768 . USlIstszud1aon+oclR6Pa8hZ5evhy3giQwiPpqK+Rm61+e2hJb3g9xT hRV37bLez4S1LBT1sBUFSDN65AaorB12Muq/J0bnpt9J4oyTooUQhmbi aP+bUJtLpiw14OKyydvgwEJQc5qXz6E9nsNT9GRNGwMNp7yIkY8laqql 4pwaPnbGn3x4hKN/VWWJ5sf4q5TOL2BxG5PRIxKoiGRYmC1xJvzORyca vbf17BGDQdYM7MUcohHiRrwz8YZHqV8Guyhwcf2MJK06rCePBZLskfah Lde953aHAvEZxw47Tt7J7FAKNRR6brN2zFKNf5NBQ8r2KPUO2qd9eDxp EoBfOQ==  
;; Received 1170 bytes from 193.0.14.129#53(k.root-servers.net) in 459 ms

paypal.com.        172800  IN  NS  pdns100.ultradns.net.  
paypal.com.        172800  IN  NS  pdns100.ultradns.com.  
paypal.com.        172800  IN  NS  ns1.p57.dynect.net.  
paypal.com.        172800  IN  NS  ns2.p57.dynect.net.  
paypal.com.        86400   IN  DS  21037 5 2 0DF17B28554954D819E0CEEAB98FCFCD56572A4CF4F551F0A9BE6D04 DB2F65C3  
paypal.com.        86400   IN  RRSIG   DS 8 2 86400 20170817041651 20170810030651 5528 com. Jrg6iI+9lcBwHdLlMH5O8SS6AMR8lVfm8JUszO5d73R+h6T6Ist7TQz5 iCFPRANi+b7Jmt8AimdGINWie+VUHOfR7fyU91kyi+aOVeITTcv55JEH fWSEzatoXrEzx9r8JgosBQr4fJnzc/OxmyrzNky5krJGRfwkcgmW0Anq Qtk=  
;; Received 482 bytes from 192.43.172.30#53(i.gtld-servers.net) in 794 ms

paypal.com.        300 IN  A   64.4.250.33  
paypal.com.        300 IN  A   64.4.250.32  
paypal.com.        300 IN  RRSIG   A 5 2 300 20170827105805 20170728101420 11811 paypal.com. t+cm9NJYN77Qyci2Vij6Bez/8NY1WLHV51jhBDPPP4gk9w2m+3YB8XID XLXlrUt3X96af27sUrWfNkEIo68nO8/c5A04ubRTXlLfcHfyaTov5hPv 71Zwo0Yau8gu8Qdww1x61LLvGoTqxXuaQwYSRf09pjO36UVzxa5Fj84p Tz4=  
paypal.com.        300 IN  NS  pdns100.ultradns.net.  
paypal.com.        300 IN  NS  ns2.p57.dynect.net.  
paypal.com.        300 IN  NS  ns1.p57.dynect.net.  
paypal.com.        300 IN  NS  pdns100.ultradns.com.  
paypal.com.        300 IN  RRSIG   NS 5 2 300 20170910052028 20170811051656 11811 paypal.com. sdyQ3dPuWld6WVgFUst8NoeTRzxZgx1GhM/lKTOdkB9oDqrNkHDw4K2w q2LonMSwNi+Q/UE7r33+lKxa5YbFTMWUaT5lAI9VzTNwJ4FOXFdRBb3A CN1oaadDND0oHBAWxm5dMCRozf6zycpEpat6QJmk+AzdhhuYGRqTNboB JHE=  
;; Received 523 bytes from 204.13.250.57#53(ns2.p57.dynect.net) in 5 ms

可以看到开启DNSSEC之后响应信息里多出了RRSIG记录和DS记录,简单的说RRSIG记录里保存了其他记录(RRset)的签名信息,而父区域的DS记录保存了子区域DNSKEY的哈希值用来维持信任链。

以上面这个解析paypal.com的流程为例的话,简化的信任链如下:

受信的根的DS记录 =验证=> .com的公钥(DNSKEY) =验证=> RRSIG =验证=> paypal.com的NS记录 + DS记录 =验证=> paypal.com的公钥(DNSKEY) =验证=> RRSIG =验证=> paypal.com的A记录

更具体的实现细节比较复杂,比如DNSKEY还分为KSK和ZSK,Root Zone是如何签名的等等...

这里就不展开了。

中国特色的情况:

墙的DNS污染大致采取了两套策略:

1.对于墙内的递归服务器,伪装成根服务器进行缓存投毒

2.对于用户则通过部署在省级骨干网(大概)上的节点伪装成递归服务器给出错误的响应
; <<>> DiG 9.11.2 <<>> fuckgfw.org @8.8.8.8 +dnssec +trace
;; global options: +cmd
.                       220397  IN      NS      a.root-servers.net.
.                       220397  IN      NS      b.root-servers.net.
.                       220397  IN      NS      c.root-servers.net.
.                       220397  IN      NS      d.root-servers.net.
.                       220397  IN      NS      e.root-servers.net.
.                       220397  IN      NS      f.root-servers.net.
.                       220397  IN      NS      g.root-servers.net.
.                       220397  IN      NS      h.root-servers.net.
.                       220397  IN      NS      i.root-servers.net.
.                       220397  IN      NS      j.root-servers.net.
.                       220397  IN      NS      k.root-servers.net.
.                       220397  IN      NS      l.root-servers.net.
.                       220397  IN      NS      m.root-servers.net.
.                       220397  IN      RRSIG   NS 8 0 518400 20170825170000 201
70812160000 15768 . Ryet1o4jMlZyGwwwUo7HQ/hxnhm2PlLhAyMhHEWyo89M9ZfbModSEVYs WMn  
epoIcuU/Ng5VL+TxdrxiSYeE065u69xsQmFy6kT8ozKCcWmyOkq4d udKLZCc+RA6JuUxpZE5in/fgJp  
I03r8/YkkUOZP4lDqhyiDKnJm5fyAP h6912m5YAOM5Rx2hz0lYh2BjLO9vJ74h/6Y4bGoOvHG+etkYs  
NFq4tE/ praTqBschffzR7++kNYdSXvY2OI/gwNMofJAJP8HUPRlgnmF845WKp8q Fo7+uwpZvBK8Suk  
gVxlrAgZspR6AbLRKYMcDNigo3Ycw66FKjGuUklUX b5ZZ+A==  
;; Received 525 bytes from 8.8.8.8#53(8.8.8.8) in 105 ms

fuckgfw.org.            3413    IN      A       93.46.8.89  
;; Received 56 bytes from 192.203.230.10#53(e.root-servers.net) in 28 ms

上面就是下文提到的墙对于递归服务器伪装成根服务器

对于递归服务器本身而言,墙会伪装成根服务器或者顶级域(TLD)的服务器直接给出被污染域名的响应,让稍后到达的正确响应被丢弃,这样就实现了DNS缓存投毒。当然,攻击者也只能伪造出未签名的响应,所以如果客户端或者递归服务器强制校验签名(要么得到正确结果,要么直接查询失败)的话就会拒绝掉这个伪造的响应。但如果客户端或者递归服务器要这么配置,那所有未签名未配置DNSSEC的域都无法解析。考虑到DNSSEC的普及程度,这样做和自残没啥区别=。= 而且只是拒绝了错误结果,并不能获得正确的结果。所以在这种中国特色的环境下DNSSEC显得比较鸡肋。

而对于客户端而言,不难发现还有一个致命的弱点。即如果客户端要查询paypal.com的A记录,正常情况下递归DNS服务器(比如这里的8.8.8.8)先向根域名服务器发出一个查询请求,根域名服务器会返回.com顶级域的NS服务器相关信息。然后再向.com请求paypal.com区域的NS服务器信息,之后向paypal.com的NS服务器(又叫权威DNS)请求paypal.com的A记录.最后递归服务器拿到了A记录才会把这个记录缓存下来然后发给DNS客户端.

但是如果有傻逼控制了骨干网,并在你向递归服务器发送了查询请求服务器还没来得及把结果返回给你的时候马上把自己伪装成递归服务器抢答一个错误的paypal.com的A记录,由于DNS协议是基于UDP的,客户端无法判断这个宣称自己是递归服务器的傻逼是不是真的就是递归服务器,那么客户端就会把这个A记录当成正确结果而忽略掉之后到达的真正的递归服务器的响应.这就是为什么即使用户使用的是8.8.8.8这样墙外无污染的DNS还是会得到错误的结果.而且响应非常快大概就20ms左右.

还有就是即使输入一个并不存在的DNS服务器,还是会有响应。就像这样:

C:\Users\Minty>nslookup 1.blog.fuckgfw233.org 8.8.8.9  
DNS request timed out.  
    timeout was 2 seconds.
服务器:  UnKnown
Address:  8.8.8.9

非权威应答:
名称:    1.blog.fuckgfw233.org
Addresses:  200:2:f3b9:bb27::  
          93.46.8.89

C:\Users\Minty>nslookup fuckgfw.org 8.8.8.88  
DNS request timed out.  
    timeout was 2 seconds.
服务器:  UnKnown
Address:  8.8.8.88

非权威应答:
名称:    fuckgfw.org
Addresses:  200:2:253d:369e::  
          243.185.187.39

这就证明了上文提到的第二种情况

总而言之,DNSSEC可以让用户验证查询结果的完整性同时还可以防篡改,就像数字签名一样。但是它没有加密返回的查询结果,所以中间人能把这个带签名的结果用一个普通的结果替换掉.而现实中的递归dns服务器/dns客户端并不会去强制要求返回结果必须是正确配置了DNSSEC的(即使强制要求DNSSEC也很难获取到正确的结果).所以能被墙轻松污染...

参考资料:

https://www.icann.org/resources/pages/dnssec-qaa-2014-01-29-zh

https://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F%E5%AE%89%E5%85%A8%E6%89%A9%E5%B1%95

https://tools.ietf.org/html/rfc4033

https://tools.ietf.org/html/rfc4034

https://tools.ietf.org/html/rfc6840

https://msdn.microsoft.com/zh-cn/library/jj200221.aspx

https://www.cloudflare.com/dns/dnssec/how-dnssec-works/

https://access.redhat.com/documentation/zh-CN/RedHatEnterpriseLinux/7/html/SecurityGuide/sec-SecuringDNSTrafficwithDNSSEC.html

点击右边的按钮加载评论,如果无法加载那估计是被墙啦..你看着办w