如果你还不了解 DNS 的基本工作,请查看 DNS 杂谈(上) ,本篇主要叙述 DNS 现有的问题。

13 个根域

13 这个数字是怎么定下来的?13 个根域的 IP 不代表就只有 13 台服务器在支撑整个 DNS 系统,别忘记了还有任播和服务集群的技术。

在协议上,TCP 协议涉及非常高的开销,因为它包含多个建立 TCP 连接的步骤和过程,可能会减慢整个通信过程,因此 RFC1035 规定 DNS 协议基于 UDP ,但 UDP 属于不可靠的数据报协议,因为当 UDP 数据包的大小超过了最大值,就需要在 IP 层进行分包,意味着接收方需要对接受到的数据包进行重组且 UDP 是无序发送数据的,所以一旦接受方无法重组数据,就会丢弃整个 IP 数据报。另外,分包后的数据包中只有一个包会记录端口信息,非状态型防火墙可能会拦截不包含端口信息的数据包。因此为了避免一系列的麻烦,我们就有 DNS 通信的数据包大小不能超过 UDP 的最大限制 的这一说法。对于 IPv4 而言的 MTU ( maximum transmission unit ) 则是 512 字节,通过计算得出数据包内只能包含 13 台服务器的 IP 信息,因此根域服务器数量为 13 台。

EDNS0 拓展协议

RFC4035 指出,支持 DNSSEC 的服务器必须支持 EDNS0 拓展。RFC5966中要求,DNS 服务器支持 TCP 查询,一次 TCP 应答的最大长度是 65535 字节。

上面一个小节我们提到了 DNS 数据包大小的问题,但随着 IPv6 的普及使用,DNS 数据包中并不能装下 13 个 IPv6 的信息数据,人们急切需要使用超过 MTU 值大小限制的 DNS 数据包,所以出现了 EDNS0 拓展,并且从 BIND9 之后的版本开始启用该拓展。它通过在递归服务器( Recursive Server )和权威服务器( Authoritative Name Server )之间协商和探测能支持的 UDP 分组大小,来增大 UDP 分组的最大限制以容纳整个应答。 权威 DNS 是特定域名记录( 例如“example.com” )在域名注册商处所设置的 DNS 服务器,用于特定域名本身的管理(增加、删除、修改等) 。权威 DNS 服务器只对自己所拥有的域名进行域名解析,对于不是自己的域名则拒绝访问。比如,向 “example.com” 的权威 DNS 服务器查询 “test.com” 的域名肯定会查询失败。递归 DNS(也称本地 DNS 或者缓存 DNS)用于域名查询。递归 DNS 会迭代权威服务器返回的应答,直至最终查询到的 IP 地址,将其返回给客户端,并将请求结果缓存到本地。

在说 DNSSEC 之前,我想讲讲 DNS 欺骗攻击和缓存污染攻击的原理。DNS 欺骗 ( DNS spoofing )是典型的一种中间人攻击( Man-in-the-middle attack,MIMT ),维基百科还称之为 DNS 缓冲投毒 ( DNS cache poisoning )。客户端访问 example.com ,在本地缓存查找不到域名 IP 的时候,客户端向 DNS 发起解析请求。正常情况下应该返回 example.com 的对应 IP 地址是 X.X.X.X,但是由于攻击者潜伏在网络中,他可以对 DNS 应答客户端的数据包进行修改或者直接由攻击者冒充 DNS 服务器向客户端应答解析请求,导致 example.com 的对应 IP 地址变为 Y.Y.Y.Y.,此时用户的浏览器地址栏依然看到是 example.com ,但事实上却访问了 Y.Y.Y.Y 网站。为了提高 DNS 的解析速度,DNS 服务器一般都会将近期的查询记录进行缓存,保留几小时甚至几天的时间不等,这就导致了但 DNS 被污染之后需要一段时间才能完全在网络中更正过来。更可怕的是,普通 DNS 使用 UDP 协议,大大降低了伪造 DNS 响应数据包的难度。 如果 DNS 被劫持,那么攻击者可以实现:

  • 页面内的广告投放,赚钱;
  • 转跳到高仿钓鱼网站,盗号;
  • 转跳到木马网站,抓肉鸡;

DNS 欺骗攻击能成功的关键,就是因为请求者无法验证 DNS 应答信息来源的真实性和完整性,如果利用密码学中的 “ 数字签名 ” 技术就可以解决这个问题,而 DNSSEC 就是这样的一种手段。安全的 DNSSEC 是需要从根区域到最终域名的查找过程中的每一步都部署该项技术 。.com 对 example.com 的密钥进行签名,根区域对 .com 的密钥进行签名。在验证过程中, DNSSEC 沿着该信任链一直追溯到根区域,并自动使用该路径上的 “ 父 ” 密钥验证 “ 子 ” 密钥。因为每个密钥都可以由它上面的一个密钥进行验证,所以验证整个域名所需的唯一密钥是最顶层的父密钥(即根密钥)。因此,DNSSEC 的实现需要面对诸多的挑战,如密钥管理、部署成本、用户体验等等。

DNS 的隐私问题

DNSSEC 技术本质上解决了 DNS 欺骗或 DNS 缓存投毒的攻击的问题,但是 DNS 通信没有加密处理,也不需要对使用者进行身份认证,这就导致了 DNS 很容易就泄露了用户的信息,而谈得上隐私信息的应该是数据包中的网页地址和 IP 地址。随着 IPv6 的普及使用,IP 地址等同于用户的个人标识。通过分析用户访问的网站,我们使用朴素贝叶斯分类器(Naive Bayes Classifier) 对就可以快速推测用户的基本特征,如性格、工作、地理位置和生活习惯等等。

上图是 DNS 服务查询的流程,那么我们是否有必要将每一次查询的信息都完整记录在查询请求中?比如我们只需要告诉根域名服务器我们需要访问 “ .com ” ,那么根域名服务器也可以正常返回对应的应答信息,同理我们也只需要告诉顶级域名服务器我们需要访问 “ example.com ” 即可,尽少的个人信息被 DNS 服务器记录,减少攻击面,因为即便浏览器的查询记录被清除,服务器的查询记录依然存在。另外,用户浏览 Web 页面的时候,可能会请求不同域名下的图片、视频、脚本等资源,而每一次请求必然会发起 DNS 的请求。甚至部分浏览器或开发者为了提高用户体验,使用 DNS 预读取技术加快网页的打开速度,而这里的 DNS 请求往往是用户所不知道的。我们可以通过下面的标签禁止 DNS 的预读取:

DNS Prefetch:<meta http-equiv=”x-dns-prefetch-control” content=”off”>

DNS 的隐私保护

隐私保护一方面是法律问题,比如最近热门话题 GDPR。另一方面是技术问题,下面有部分保护方案的例子,它们都是从不同的角度对隐私问题进行考量,因此不一定应用在实际的生活环境中。

  • DNS-over-TLS,DNS-over-DTLS 或 DNSCurve 。通过在链路上进行加密的手段,保证链路上的用户隐私不被泄露和恶意监听。但是都不可避免的引入了较大的开销,加密和保证可靠通信带来的延迟问题对用户体验影响很大,且不能减少 DNS 服务器上的隐私信息收集问题。
  • 查询最小化。修改递归服务器上的查询策略,根据已知的 DNS 服务器的身份判断是否发送域名的全部信息。部署简单,但是无法匿名,只能降低部分 DNS 服务器对查询请求的记录。
  • 加入混淆。构建一个虚拟查询集,将用户的真实查询隐藏在虚拟查询集之中,然后把数据一并发送给服务器,从而降低被分析出真实访问网站的行为。同样无法匿名,查询开销变大,需要维护虚拟查询集。
  • 广播热门域名。递归服务器定期参与热门域名的广播 ,用户主机本地缓存热门域名,从而使得热门域名的查询不通过递归服务器,理论上没有隐私泄漏分析。同样匿名性较低,需要维护热门域名表。
  • EncDNS。通过特定的服务器做代理,代替用户进行查询,传输过程中使用 DNSCurve 来保护用户隐私,从而隐藏真正的查询发起者。但是存在单服务器有性能瓶颈和单点失效问题 。
  • PPDNS + NameCoin。PPDNS 构建了一个基于 P2P 网络 的 DNS,域名查询结果由网络中的不同节点提供,不存在单一中央的服务器。NameCoin 构建了一个基于比特币技术的 DNS,所有的域名信息记录在一条新的区块链上,用户通过同步区块链来 实现查询完全本地化。但是这种方式需要修改现有架构,部署难度大。

如果就是单纯是一个普通用户而言,我们能做的措施比较被动。首先,不建议使用运营商或非权威机构提供的 DNS 递归解析服务( Trusted Recursive Resolver,TRR ),对于未知安全性的链接,时刻保持你的警惕,尤其是 IE 用户。其次,在确认某个协议之前请认真看一遍有关于隐私信息的条例,不要盲目同意,在提交敏感信息之前确认对方可信任。然后,你需要弄清楚浏览器的一些功能(Javascrip、cookies、定位、同步等)是否是自己需要用到的。最后,请拥抱 HTTPS 。

基于便利和隐私的考量,上述建议酌情采用,比如本页面依然是 http :(

DoH 的应用

在 DNS 的隐私保护中有一个方案是利用 HTTPS 对 DNS 进行通信链路上的保护,也就是常说的 Dns-over-Https( 亦有人简称 DoH)。在本文章的上篇里面,我们讲到了主从 DNS 服务器,TCP 协议一般用于 DNS 服务器之间的通信,而 UDP 协议一般用于客户端和 DNS 服务器之间的通信,那 DNS 怎么支持 HTTPS 了?在 RFC 7858 中指出,所有 DNS 数据都需要通过 TLS 端口传输,意味着在使用 DNS 通信之前,就必须启动 TLS 握手。DNS over HTTPS 利用 HTTP 协议的 GET 命令发出经由 JSON 编码的 DNS 解析请求,Google 及 Mozilla 基金会正在测试这一协议,作为其提高网络安全性的努力的一部分。

DNS 和 CDN

利用 DNS 可以做到对于网站访问的负载均衡。客户端对 DNS 服务器发起域名解析请求的时候,其实就是在询问 DNS 服务器 “ 我应该访问哪个 IP 的服务器 “,那么 DNS 服务器此时就充当了资源调度的角色,DNS 服务器可以根据简单的轮询和权重配置对客户端的请求作出应答,对于解析域名 www.example.com 的应答可能是指向 A 服务器,也可能是指向 B 服务器。因为 DNS 的 A 记录是可以有多条的,比如:主机 www 对应的 A 记录有三条,分别是 1.1.1.1 、2.2.2.2、3.3.3.3,且 1.1.1.1 的权重比其他的高一级,三者的线路均为默认。
CDN( Content Delivery Network )即内容分发网络。它的基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。用户可就近取得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度。

DNS 和 CDN 是两种完全不同的技术,但是两者却有分不开的关系。使用了 CDN 的域名,它的解析过程应该是:

  1. 浏览器输入域名 www.example.com,执行迭代查询和递归查询;
  2. 得到 CDN 事先配置完成 www.example.com 的 CNAME 记录;
  3. 浏览器再次解析 CNAME 记录,得到 CDN 缓存服务器的 IP 地址;
  4. 浏览器向 IP 地址发起请求,缓存服务器收到请求并根据域名执行判断:
    1. 通过 Cache 内部的DNS 解析获得域名对应的真实 IP 地址;
    2. 查看缓存服务器本地是否存在该真实 IP 地址对应的资源,存在则直接发送给用户,不存在进入下一步;
    3. 缓存服务器向真实的 IP 地址发起请求,获取网页内容,本地保持数据并且发送给用户;
  5. 浏览器加载数据,页面渲染完成。

CDN 对比 DNS 的负载均衡,CDN 不需要多个配置相同服务的服务器,网站缓存的数据由 CDN 服务提供商存储,用户通过 DNS 就可以找到最适合自己网络的数据缓存。CDN 是分布式的,具有天生的抵御 DDOS 攻击优势,当用户访问加入 CDN 服务的网站时,域名解析请求将最终交给全局负载均衡 DNS 进行处理 。目前市面上的智能 DNS 是全球负载均衡( Global Server Load Balance,GSLB )的一种应用。GSLB 可以通过 DNS 或者 HTTP redirection 技术等方案实现。

参考资料

根域名服务器数量计算

DNSSEC 部署

dns over https 简介

CDN 与 DNS 的关系

GSLB概要和实现原理

《Research on status of DNS privacy》