Ghost Assassin:不靠谱的DNS总是被钻空子

27号开始Gmail服务遭到了GFW的全面封杀,在墙内彻底无法使用。从技术上来说,GFW采用的是最为原始而且成本很高的手法:IP地址屏蔽,所有的骨干路由器和国际出口的路由器都添加上了和Gmail服务有关的IP黑名单,带有相关IP地址的数据包直接在半路就被丢包了。

说实在的,这种手法会给路由器带来很大负担,成本非常高,所以GFW对于多数网站的封锁并没有采用这种手段,而是采用了一种廉价很多又很有效的手段:DNS欺骗(或者叫DNS污染)。

先从什么是DNS说起吧:DNS是Domain Name System(域名系统)的缩写,是一个分布式的数据库系统[1],负责在通信时把目标网站的域名对应成相应的IP地址(计算机网络中的计算机之间的通信时各自的位置是靠IP地址(还有MAC地址)标明的,但对于人来说IP地址实在是很不好记,所以适合人类记忆的域名就横空出世了)。

当用户在浏览器地址栏中输入一个URL并且按了回车之后,首先启动的就是DNS协议:DNS正常工作的前提是用户已经在网络设置中指定了IP地址和所用的DNS解析服务器(或者叫递归域名服务器),当浏览器发起DNS查询请求之后,首先检查hosts文件,如果文件中有目标网站对应的IP地址,那么就取得这个IP地址并结束查询过程;如果没有,那么就向递归域名服务器发起查询请求,如果递归域名服务器的缓存上有相应的数据,那么就取得IP地址,结束查询过程;如果没有,接下来的过程就比较复杂了,具体看这里[2]吧,我不再重复,简单来说就是如果想要去墙外网站看看,一般情况下都要和墙外的域名服务器通信的(所以想要建立天朝局域网是需要付出很大的代价的)

DNS协议是应用层协议(关于这些层究竟是怎么回事,请看这里[3]),基于UDP工作(也可以基于TCP工作,但绝大部分情况下都是基于UDP工作的,有空时我会聊聊这两个重要的传输层协议究竟是怎样的),标准工作端口是53端口[1]。

“看上去好像很正常啊,不就是一个普通的协议吗!这跟GFW为什么选择进行DNS欺骗又有什么关系呢?”

注意到“基于UDP工作”了这点没有?UDP(用户数据报协议)是一个无连接的不可靠的协议,所谓无连接不可靠主要是指以下两点:1,不保证能将数据包送到目的地,丢失的或损坏的数据包不会被重传(TCP就要求重传,而且有严格的查错机制,有空我会仔细聊聊);2,先发送的数据包不一定先到达(想象一下平时坐车情景就能明白这一点:后出发的公交车如果绕了近路或者成功超车了,反倒会抢在先出发的公交车之前到达目的站点)。特别是第二点,面向连接的可靠协议(例如TCP)就要求先送出的数据包先到达,不能打乱顺序。

基于UDP的DNS协议自然也就变成了一个无连接不可靠的协议了,这就给了GFW钻空子的机会:由于本身不是面向连接的,没有建立一个端到端的连接(面向连接的协议工作时都会逻辑上建立一个端到端的连接通路,就像流水线一样,把一个个数据包严格按顺序传送过去,不允许谁掉队,不允许谁出错),所以GFW只要抢在墙外的域名服务器传回查询结果之前伪造一个查询结果发回来就能成功把相应的网站墙掉了[4]:用户的浏览器收到了伪造的查询结果,就终止了与域名服务器的通信,开始试图连接到一个根本就不对应网站的IP地址上,结果就是无法成功建立连接(一般情况下显示:无法解析某某地址)。如果是基于TCP的,GFW就没有办法玩这招了(不过GFW可以用伪造RST包的方式对付TCP连接),具体怎么回事我在以后讲解TCP的时候再仔细说明一下。

不过我前面也提到了UDP不保证先出发的先到达,也就是说虽然GFW抢先发送了伪造的查询结果,但有可能正确的查询结果反而先到达用户PC上,这样就封锁失败了,所以GFW对于正确的查询结果也进行了注入处理,篡改了查询结果,把真实IP地址替换成了伪造的IP地址[4]

具体来说GFW就是这样一个工作流程:当用户试图连接到被封锁的网站时,相应的查询请求数据包必然会经过国际互联网的出口,此时GFW通过基于正则表达式[5]的黑名单进行匹配[6],一旦发现有关键字匹配上了(不管这个域名实际上是否存在)就马上开始伪造查询结果并发送回去(这一过程由GFW路由器负责,顺便说一句伪造的查询结果中有个假IP地址是中国联通的[4],可想而知这些ISP都是GFW的一部分),再接着篡改从墙外到来的真正的查询结果。这一过程叫做DNS欺骗或DNS污染。

这一过程最主要是部署在互联网旁路上的入侵检测设备负责的(GFW的实质是巨大的分布式入侵检测系统而不是防火墙),路由器只负责伪造查询结果,资源消耗比起基于路由器工作的IP地址屏蔽要低上很多,而且还有额外的好处[4]:对于网站来说,换一个IP地址,用户基本上感觉不到有什么变化;但是换一个域名就不一样了,域名就是给人记的,随便换域名会流失大量用户,尤其是很多主要用户不是天朝用户的网站,根本就不会因为天朝用户看不到自己的网站而更换域名失去其他大量用户的,这样就使得GFW的DNS污染长期有效了。

说到这里,诸位应该就能想到对应的几点解决方法了:

1,加密查询请求和查询结果(GFW至少不敢封根域名服务器的,除非共匪真心想要建立天朝局域网)

2,基于TCP进行查询(加密数据包决不能送丢了,更重要的是GFW迄今为止还是基本上只污染基于UDP的查询结果,GFW一直只监听53端口,也可以试试换个端口查询)

3,添加身份认证机制(免得是个路由器都能装成域名服务器)

4,想办法过滤掉伪造的查询结果(但考虑到GFW对于真正的查询结果也会下手,这方法效果不会好)

5,或者,最简单的:修改hosts,直接在本地PC上完成查询过程,自然就没有后来的事了(这就是hosts翻墙的原理)

事实上现在已经有一些改进DNS协议安全性的手段了(例如DNSSEC),我会在“SSL/TLS的原理以及互联网究竟是如何工作的”系列里进行介绍。

而DNSCrypt[7](注意这个名字,crypt就是加密的意思,直接加密走OPENDNS查询)和DNSforwarder[8](按作者说法是走TCP查询或者过滤伪造的查询结果)还有ChinaDNS[9](走国外DNS服务器,加密查询结果)以及各种hosts文件就是依据前面所说的解决方法来对抗GFW的DNS污染从而规避封锁的。

最后再说一句,天朝流氓ISP很多时候很喜欢玩DNS劫持,这和DNS污染是两个概念:DNS劫持简单来说就是ISP把自己的域名服务器上的记录进行篡改,在用户进行查询时强行塞给用户一堆广告对应的IP地址,而浏览器则把这些当成了目标网站的IP地址从而建立连接,烦人的广告就到处都是了,甚至可以劫持到流氓软件的下载链接,百度DNS就是这样[10]。

解决方法也很简单:不要用天朝ISP的域名服务器,直接打开控制面板的网络和Internet连接,再点击查看网络控制和任务,再点击更改适配器设置,找到本地连接(或者说上网时使用的那个连接),右键属性,找到IPv4,双击点开,把DNS服务器由自动(或者默认的ISP服务器)换成国外的域名服务器:google的8.8.8.8和8.8.4.4 ,OPENDNS[11],台湾中华电讯的DNS 168.95.192.1和168.95.192.2,香港宽频的DNS 203.80.96.9和203.80.96.10,或者自行寻找可用的国外免费DNS服务器

下一篇咱们来聊聊IP屏蔽是怎么一回事吧。

最后照例附上科普文链接集合:

https://plus.google.com/u/0/109790703964908675921/about

参考资料:

1.域名系统https://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F
2.扫盲 DNS 原理,兼谈“域名劫持”和“域名欺骗/域名污染” https://plus.google.com/109790703964908675921/posts/aX22pV3242N
3.SSL/TLS的原理以及互联网究竟是如何工作的(1)
                                                   ————“每个协议生而平等”
https://plus.google.com/109790703964908675921/posts/jew5dx6V2Lt
4.The Great DNS Wall of China
http://www.google.com/url?q=http%3A%2F%2Fcs.nyu.edu%2F~pcw216%2Fwork%2Fnds%2Ffinal.pdf&sa=D&sntz=1&usg=AFQjCNEpY6ZEWK6CsuUY4IKGE27jQ8VPaw
5.正则表达式
https://zh.wikipedia.org/zh/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F
6.翻墙路由器的原理与实现
https://docs.google.com/document/d/1mmMiMYbviMxJ-DhTyIGdK7OOg581LSD1CZV4XY1OMG8/mobilebasic?pli=1
7.https://www.opendns.com/about/innovations/dnscrypt/
8.https://github.com/holmium/dnsforwarder
9.https://github.com/clowwindy/ChinaDNS
10.https://plus.google.com/109790703964908675921/posts/Y6n7hWvUNc1
11.http://www.oschina.net/p/opendns
发表评论