在上一篇文章中,咱们详细解释了 DNS 进行域名解析的过程:算法
全部这些请求都是经过无链接的 UDP 协议进行通讯,DNS 服务器识别是本身发出的数据包的惟一标准就是随机的源端口号,若是端口号匹配则认为是正确回复。这样一种简单的方式在日益复杂的网络结构下,可能会出现各类说不清道不明的问题。数据库
既然 DNS 响应数据包的源 IP 地址很容易仿冒或伪造,天然就有不少人开始利用这一漏洞,伪造权威域名服务器的应答,把目标网站域名解析到错误的地址,从而达到让用户没法访问目标网站的目的,这就是「域名劫持」。api
这里颇有表明性的例子就是防火长城(GFW)。咱们国家依法对互联网进行管理和监控,为了封堵国外的非法内容,GFW 会对 UDP 53 端口上的全部请求进行检测,一经发现与黑名单关键词相匹配的域名查询请求,会立刻假装成目标域名的解析服务器返回虚假的查询结果。因为一般的域名查询没有任何认证机制,并且基于无链接不可靠的 UDP 协议,查询者只能接受最早到达的格式正确结果,并丢弃以后的结果。这样一来,若是咱们直接访问一些国外的「非法」网站,拿到的就会是一个假的 IP 地址。缓存
固然,也有一些黑客入侵致使的域名被劫持事件。黑客经过非法手段控制了域名管理密码和域名管理邮箱,而后将该域名的 NS 记录指向到黑客能够控制的 DNS 服务器,而后经过在该 DNS 服务器上添加虚假域名记录,从而全部到目标网站的流量所有导向黑客所指向的内容。2010 年 1 月 12 日针对百度的一次域名劫持事件在历史上影响巨大。当天,百度被自称是伊朗网军(Iranian Cyber Army)的黑客组织入侵,致使其首页瘫痪长达 8 小时,并随后引起中国黑客对多个伊朗政府网站以及伊朗广播大学网站的报复行为。安全
其实相似的事件还发生过不少次,不光百度,谷歌和微软他们的域名也曾经被劫持过,能够说互联网的背后一点都不像看起来风平浪静的样子。bash
若是没有上游的欺骗和黑客的破坏,LocalDNS 拿到正确的结果以后,大致上是能够正常服务的,但这里也仅仅只能说是「大致」上。LocalDNS 会把从权威域名服务器接收到的结果数据进行缓存,以便加速后续的解析流程。例如在有效期内再有人问门卫王大爷「北海公园」的地址,王大爷只须要查一眼本身的笔记本,就能够立刻给出回答。这一设计看似 feature,可是在现实生活中有时候它会失效,反而带来危害。服务器
首先不少时候运营商的缓存时间都不太靠谱,他们不会遵照权威 DNS 提供的 ttl(存活时间),而是统一设置一个固定的时间,因此一般咱们改了一个域名的解析 IP 以后,会须要 0-48 小时(甚至更多)的时间才能让全部的客户端同步过来。并且但凡程序都会有 Bug,各运营商的运维水平也良莠不齐,有时候还会由于缓存故障影响大面积的用户访问。例如门卫王大爷在查找地址的时候也可能会看走眼,对此咱们也不能苛责;而更多的时候,在中国特点的互联网环境中,王大爷还有本身的一些「小算盘」。网络
咱们的互联网看似四通八达,其实底层仍是几个平行网络在有限的几个点铰接而成的,运营商老是喜欢缓存 DNS 结果,还有一些经济方面的考虑:运维
保证用户访问流量在本网内消化。国内的各互联网接入运营商,他们的带宽资源、网间结算费用、IDC 机房分布、网内 ICP 资源分布等存在较大差别,为了保证网内用户的访问质量,同时减小跨网结算,运营商在网内搭建了内容缓存服务器,经过把域名强行指向内容缓存服务器的 IP 地址,就实现了把本地本网流量彻底留在了本地的目的;dom
推送广告。有部分区域运营商会把某些域名解析结果指向本身的内容缓存,并替换或者插入第三方广告联盟的广告,以此增长收入。。。
以上就是咱们常说的「域名缓存污染」,它会致使终端用户访问目标网站时产生各类访问异常,或者夹杂莫名其妙的广告,这种异常在无线网络上更为常见。
域名缓存是运营商「积极做为」带来的副问题,而运营商不做为有时也会引来麻烦。运营商的 LocalDNS 有时候还会偷懒,自身不进行域名递归解析,而简单把域名解析请求转发到其它运营商的递归 DNS 上去。
例如北京市「道路咨询局」有东西两个大门(相隔较远),分别由门卫王大爷和刘大爷把守,从道路咨询局去北海公园也有东西两条路。从东门进来的游客,他们会咨询王大爷,王大爷就会选择便捷一点的东边的路回复游客;从西门进来的游客,他们会咨询刘大爷,刘大爷会选择西边的路来回复游客。可是忽然有一天,王大爷不想解答游客的问题了,他找到了一个便捷的办法,把全部问题都转到刘大爷那里去了,最后全部的游客都会选择从西边的路去北海公园。对于本来在东门的游客来讲,可能就多走了一大段冤枉路。
实际的网络拓扑结构是很复杂的,为了尽量覆盖更多用户,一个网站会接入多条运营商线路,DNS 那里则会根据请求者的特征为用户来选择最短访问路径(详见前一篇文章里的「DNS 智能解析」一节)。对这种转发的状况,可能最终的 DNS 会把转发 DNS 的 IP 当成访问者的来源 IP,这样极有可能一个电信用户最终访问到了联通的 IP,那么终端的访问速度可能就变慢了许多。还有一种解析错误是因为 LocalDNS 本地出口 NAT 配置错误致使的,这里再也不赘述。
以 LeanCloud 为例,咱们以前使用的域名是 avoscloud.com,因为这个域名存在敏感字符,因此某些区域解析常常出现问题,究其缘由基本上都是运营商的 LocalDNS 致使的,而要解决好这些问题,则须要不断与运营商深度沟通或者找工信部投诉来解决,其流程之长和效率之低可想而知。这也就是咱们后来切换到 leancloud.cn 这一域名的缘由。换了域名以后,终端用户的连通性好了不少,可是仍是不能 100% 解决全部网络问题,这时候怎么办呢?
DNS 欺骗和污染的根本缘由就是缺少安全机制,因此自上世纪 90 年代起,人们就开始寻求这一问题的解决方案,最终 DNS 安全扩展 (DNS Security Extensions,DNSSEC) 应运而生。
DNSSEC 采用非对称加密的方式对 DNS 数据进行加密,加解密算法与 HTTPS 相似,可是与 HTTPS 协议不一样的是,DNSSEC 并不是对 DNS 查询和响应的数据包进行加密,而仅仅只对 DNS 数据(A 记录,CNAME 等等,统称为 Resource Record,缩写为 RR)进行签名,因此 DNSSEC 能够彻底兼容 DNS。
为了支持非对称加密算法,DNSSEC 中增长了一个区(zone)的概念。域名系统每一级的权威域名服务器就是一个 zone,他们都配置有一个公私密钥对,这一点与 HTTPS 网站的 SSL 证书相似。权威域名服务器在返回应答数据的时候,除了一般的 Resource Record 以外,还会增长新的数据类型:
如此一来,DNSSEC 就能够额外提供三层安全保护:
有兴趣的读者能够参考这篇文章,以了解更多细节。
dig 是一个很是强大的 DNS 查询工具,经过+dnssec
参数能够验证域名服务器和域名是否支持 DNSSec。例如,咱们使用国外的 DNS 解析,如8.8.8.8
,查询域名 paypal.com
是否支持 DNSSec,能够获得以下结果:
$ dig @8.8.8.8 paypal.com +dnssec
; <<>> DiG 9.10.6 <<>> @8.8.8.8 paypal.com +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6628
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;paypal.com. IN A
;; ANSWER SECTION:
paypal.com. 9 IN A 64.4.250.36
paypal.com. 9 IN A 64.4.250.37
paypal.com. 9 IN RRSIG A 5 2 300 20190923004132 20190824003218 11811 paypal.com. E21d1Jc/fCdZneT9oC3xWgQ1gPBdO1v29LPNJw7CtydJVhsy3z3bs4U8 7vBSGScEIpmCkmbZxChW1h3UlZ++hAmCCRx+eZV7VvhynpPW30mvwjrk wx5PVxWhPAKiTs07i5h4ZgTcWwp/ZEQbvU0DEkTKlBs2SuGU6AWNgmgL jgU=
复制代码
这里咱们能够看到多出来的一条 RRSIG 记录,就是 DNSSEC 的签名数据。咱们换到 114.114.114.114
的 DNS 服务器来查询 paypal.com
的域名,则获得以下结果:
$ dig @114.114.114.114 paypal.com +dnssec
; <<>> DiG 9.10.6 <<>> @114.114.114.114 paypal.com +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17708
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;paypal.com. IN A
;; ANSWER SECTION:
paypal.com. 36 IN A 64.4.250.37
paypal.com. 36 IN A 64.4.250.36
复制代码
能够看到 114 的 DNS 服务器并不支持 DNSSEC,并且咱们使用一样的命令,来查询 baidu.com
、taobao.com
和 qq.com
,就会发现他们都不支持 DNSSEC。为何国内的大厂都不跟进这一功能呢?
DNSSEC 从原理上来讲,可以比较理想的解决 DNS 上的安全问题,可是签名和校验 DNS 数据显然会产生额外的开销,从而影响网络和服务器的性能:1)签名和校验的计算量很大,会对域名服务器的计算能力提出更高要求;2)签名数据量比普通的 RR 大得多,会加剧网络传输负担;3)签名和密钥数据占用的存储空间也会比以前大一个数量级,会致使域名服务器的数据库和管理系统都不得不进行升级和扩容。并且更重要的一点是,要想使用 DNSSEC,必须知足权威域名服务器和 LocalDNS 同时支持 DNSSec,这就须要现有的大量 DNS 解析服务的提供商对已有设备进行大范围修改,这在异构且复杂的现实环境中实施的难度较大,因此整体推动很是缓慢。
那么除了 DNSSEC 以外,咱们还有其余办法来解决 DNS 问题吗?
2016 年,RFC 添加了 DNS-over-TLS 的标准,它相似于 HTTP-over-TLS(HTTPS),就是基于 TLS 来进行报文加密的 DNS 请求交互。区别于 DNSSEC,DNS-over-TLS 更侧重于 DNS 交互报文的加密性,而 DNSSEC 更侧重于 DNS 交互报文的完整一致性。阿里云有作过 DNS over TLS 的尝试,详见这里的介绍,最终也由于 DNS Server 的性能问题而束之高阁,取而代之的是 DNS-over-HTTP(S) 方案。
DNS over HTTP(S),顾名思义就是利用 HTTP(S) 协议与 DNS 服务器交互,绕开运营商的 LocalDNS,来防止域名劫持,提升域名解析效率。另外,因为 DNS 服务器端获取的是真实客户端 IP 而非 LocalDNS IP,可以精肯定位客户端地理位置和运营商信息,从而也能有效改进路由选择的精确性。DNS over HTTP(S) 这一方案基于已经成熟并已普遍部署的 HTTP(S) 协议,客户端调用也很是方便,没有额外的成本负担。
到目前为止,有很多公共 DNS 已经支持 DNS over HTTPS,例如国外的 Cloudflare、Google Public DNS 支持 DNS over HTTPS,国内的 DNSPod 支持 DNS over HTTP,等等。如下即是 DNSPod 的 HttpDNS 请求流程图:
LeanCloud 的 Java / Android SDK 扩展了 DNS 解析模块,经过公共 DNS 的 http 请求获取到域名解析结果,而后更新本地 DNS 缓存,这样来避免客户端的 LocalDNS 污染,效果仍是很明显的。
从今年七月份开始,LeanCloud 已经开始支持应用绑定本身的访问域名,以确保能长期稳定提供服务,这里将咱们实践中遇到的一些域名问题和解决办法总结出来,但愿对广大开发者有所帮助。