OWSS (OpenWrt + ShadowSocks) FQ完全手册 (GFW的工作方式)
本文所写的环境基于 NETGEAR WNDR3800 路由器和 OpenWrt Barrier Breaker 14.07 ,其中 ShadowSocks-libev-polarssl 版本为 1.4.8-1
在有了一些基本的网络知识之后, 我们现在讲讲 GFW 的工作方式, 所谓知己知彼百战不殆嘛。不过 GFW 本身是一个人人都知道它存在, 却从来不会被官方承认的机构, 好像秘密警察部门一样。所以对于它的工作方式, 各方也都只能是通过分析和模拟来大致猜测, 也许已经接近真相, 但永远都不等于真相。
首先你要明白 GFW 的目的是什么, 它不是要阻止你访问所有的境外网站, 也不是允许你访问所有的境内网站。如果一个国内网站出现它不想看到的东西, 基于现在中国宽带网络的现状, 网警要动手清理一个境内网站实在太容易了, 不过这就不在我们的关心范围里了。话说回来, 在国内开反动网站的话, 这种智商的确令人心痛。
对于境外的网站, GFW 的封锁重点是: 新闻, 社交, 政治, 色情, 文件共享类网站。其他几种很好理解, 社交类的原因是因为阿拉伯之春的很多串联都是通过 facebook 完成的, 而 twitter 又是实际上的最大的即时新闻发布站点, 文件共享类网站可以让人们很方便的传播一些它不想看到的东西。
DNS 劫持和污染
如果从技术实现上来说, GFW 做有效的方式当然是 DNS 劫持和污染了,也许你对这个东西完全没概念,但实际上你这么多年来可能一直在被这东西祸害着。在这里先教你一个简单的命令: nslookup。
开始菜单,运行 (win8 用户 win+R 键),输入 “cmd”,回车。
分别用 nslookup 查一下 facebook.com(nslookup facebook.com) 和 twitter.com(nslookup twitter.com) 的域名,重复几次。是不是发现点问题? 这两个网站怎么 IP 是一样的?facebook 准备收购 twitter 了? 你再试试 youtube.com, 嗯,你总不会觉得 Google 要把 youtube 卖给 facebook 吧。之所以会看到这种奇怪的景象,就是 GFW 的 DNS 污染在作怪。
我们前面已经说了,要访问一个网站,首先的步骤是通过 DNS 服务器解析这个网站域名对应的 IP,可是如果 DNS 服务器返回给你的 IP 都是错的,你又怎么可能访问到网站呢? 好比你想从广州去北京,阻止你的最好办法不是半路截杀你,而是告诉你上船一路往南走。GFW 的 DNS 劫持是造成劫持和污染的根源!
很多人可能对 GFW 的 DNS 污染的概念始终停留在 DNS 缓存投毒这个概念上,什么叫缓存投毒? 首先要了解什么是 DNS 缓存。因为 DNS 系统设计的时候,就考虑到这是一个需要频繁响应的系统,所以一条域名记录被查询到之后,都会在 DNS 服务器的缓存中驻留一段时间,这样下次查询的时候就直接从缓存中读取记录而不需要再次进行递归查询了。
如果错误的记录进入了 DNS 服务器, 这个错误的记录就会被保持一段时间, 如果在缓存过期后又有一次错误的信息进入, 那么还是继续保留这错误的记录, 这个过程如果一直重复, 服务器就永远无法返回正确的记录了, 这就成了缓存中毒。而一般意义上的黑客的缓存投毒, 是通过生日攻击这种方式进行的, GFW 需要用这么低级的手段吗?
黑客需要发送生日攻击, 目的是通过两边大量的数据碰撞猜到查询者发起的查询的 Transaction ID, 因为只有响应包的 Transaction ID 和请求包的一样才会被查询者接受。但是 GFW 完全控制了中国网络的对外出口网关, 他还需要猜你的 Transaction ID 吗? 他只要直接嗅探就行了, 就好像你在自己的路由上用 TcpDump 抓取所有通过路由的网路数据一样,既然可以嗅探到你全部的 DNS 查询数据, GFW 想要伪造一个响应包也就完全没有困难了。除了嗅探 DNS 查询数据,其实所有的明文传输的密码(FTP,SMTP 等)都是可以轻松被嗅探到的。
我们前面已经说了,DNS 是基于 UDP 协议的,而 UDP 这种不面向连接的协议是极度缺乏安全性的, 你完全不能保证当你向一个服务器查询 DNS 记录后,返回记录给你的真的就是那台 DNS 服务器。我们知道,13 套根域名服务器系统没有一套是在中国的,中国只有镜像, 而.com,.net 这些顶级域名称服务器在中国连镜像都没有, 而 twitter、facebook、youtube 这些域名的权威名称服务器更是毫无疑问的全部在国外, 所以 DNS 服务器在递归查询这些网站域名的 A 记录的时候, 信息一定会经过 GFW 到国外。现在 GFW 知道了你 (某台 DNS 服务器) 要向国外的某个服务器查询 twitter.com 的 A 记录,在国外服务器返回正确的信息给你之前,GFW 就伪造一个响应包给你,告诉你 twitter.com 的服务器在新疆某个山沟里,IP 是什么什么。再强调一次,UDP 包是无法判断来源的真实性的,而 GFW 伪造的包里所有信息都符合 DNS 协议规范,DNS 服务器就接受了这个错误的记录。
那么国外的服务器就不会返回正确的信息过来了吗? 会,一定会,因为 UDP 虽然不安全,但基本上还是可以送达的。但是你别忘了, 错误的信息已经抢先进入了 DNS 服务器的缓存,后面再过来的数据DNS 服务器已经完全当它不存在了。谁先到谁就是对的, 这就是扯淡的 DNS 逻辑, 而国外服务器再快, 也不可能快过守在边境的 GFW 网关, 所以你在用 8.8.8.8 配合 dig 这些工具查询域名的时候会发现, 也许解析 taobao.com 花了 200 毫秒, 而解析 twitter.com 只花了 30 毫秒, 那是因为这个根本就是 GFW 在国内
发回给你的。
以上所描述的,GFW 抢先于境外服务器返回给你一个错误结果的行为,就叫做 DNS 劫持。根据我的观察分析,GFW 这个劫持行为是发生在所有对国外 IP 进行敏感域名查询的时候,不是说只有你在往 8.8.8.8 这些知名国外 DNS 查询的时候才会发生劫持, 你也不要指望说能不能找到个比较低调没被 GFW 发现的 DNS 服务器 IP 可以不被劫持, 没用的。GFW 甚至都不用判断目标 IP 是什么, 只要是通过出口网关往外面跑的,查询敏感域名的全部劫持。
虚假 IP 劫持
那么,GFW 会返回一些什么样的错误信息给你呢? 就目前各方面统计的信息来看,GFW 返回给你的虚假信息,其实就是篡改了域名的 A 记录部分,把你指引导错误的 IP 就行了。准确的说,不只是 A 记录,对于记录 IPV6 地址的 AAAA 记录他们也是一样会劫持的,目前还值的庆幸的是,GFW 返回的虚假记录只用了一些特定的 IP,我们可以通过一些手段来过滤掉这些信息,从而获得正确的解析结果。
目前已知的,GFW 用于 DNS 劫持污染的 IP 有 48 个,如下表:
118.5.49.6 | 209.220.30.174 | 64.33.99.47 |
128.121.126.139 | 209.36.73.33 | 64.66.163.251 |
159.106.121.75 | 209.85.229.138 | 65.104.202.252 |
169.132.13.103 | 211.94.66.147 | 249.129.46.48 |
188.5.4.96 | 213.169.251.35 | 65.160.219.113 |
189.163.17.5 | 216.221.188.182 | 66.45.252.237 |
192.67.198.6 | 216.234.179.13 | 72.14.205.104 |
197.4.4.12 | 23.89.5.60 | 72.14.205.99 |
202.106.1.2 | 253.157.14.165 | 74.125.127.102 |
202.181.7.85 | 37.61.54.158 | 74.125.155.102 |
203.161.230.171 | 4.36.66.178 | 74.125.39.102 |
243.185.187.39 | 46.82.174.68 | 74.125.39.113 |
203.98.7.65 | 49.2.123.56 | 77.4.7.92 |
207.12.88.98 | 54.76.135.1 | 78.16.49.15 |
208.56.31.43 | 59.24.3.173 | 8.7.198.45 |
209.145.54.50 | 64.33.88.161 | 93.46.8.89 |
1. 因为劫持工作量巨大,如果使用随机数的话,生成随机数的计算负担会更重关于为什么使用特定 IP 而不是随机 IP,可能的原因有以下几点:
2. 随机 IP 可能指向正常工作的网站,加上这种解析请求的数量巨大,会破坏全球网络的稳定性
3. 部分 IP 指向的是制作自由门等翻墙软件的公司,通过这种方式实际上是对他们发起 DDOS 攻击
空包劫持
除了返回错误的信息之外,我还观察到一次很特殊的 GFW 对境内 DNS 的空包劫持。没错,境内,这也在提醒我们 GFW 不是简单的只工作在出国网关上,而是同时也分部在全国各个骨干网络上的。这次劫持发生在我用114DNS 查询instagram 的一个 CDN 节点域名 “scontent-a.cdninstagram.com” 的时候。我们的查询包默认是要求服务器做递归查询的,按标准服务器在返回包中也应该注明它知道了你发出了递归的请求,可是 GFW 劫持了我向 114 的这个请求,返回了一个不需要递归请求的响应包,同时没有任何 A记录,而 Reply Code 中的错误代码是没有错误。
和不检查返回源的真实性一样,DNS 甚至都不会检查应答包中关于递归请求的部分是否发生了变化,这样一个不需递归请求,没有 A 记录,没有无错误代码的结果就被 DNS 的解析器 (客户端,我们的路由或者电脑) 接受了,因为格式完全符合协议规范啊,然后一个明明存在的域名就成了找不到 IP 的域名了。
关于这个问题,具体细节参考文章GFW 的 DNS 劫持中的空包污染问题。空包劫持的问题,因 DNS、ISP 不同有很大的区别,且针对的域名很少,总的来说这种行为是 GFW 的 DNS 劫持中的少数派。而对于空包污染的过滤,规则很容易和迭代查询的数据包匹配上,所以会阻止本地发起的迭代查询的结果。但我们的 OS 所发出的 DNS 请求默认都是递归请求,基本上不用担心这个问题, 如果你在使用某些调试工具 (例如 Dig+trace 选项) 的时候发现没有数据返回, 请先禁用这个空包过滤规则 。
轻松的扩散污染
GFW 劫持搞定了所有对境外服务器发起的 DNS 解析请求的,就从源头上保证了我们的递归 DNS 服务器只可能获得敏感域名的错误 IP。那剩下的工作就是扩散污染了。我们前面说过,DNS 服务器有两种工作方式1.6,分别是递归和迭代,迭代是一种很蛋疼的工作方式,但现实中总还是有部分 DNS 服务器是在以迭代的方式工作的。按理说,这些 DNS 服务器几乎是没有什么解析能力的。可实际上呢,大部分情况下他们又可以对几乎所有域名的解析请求都做出响应。
那么他们自己不能做递归查询去获取域名的各种记录,这些记录是哪里来的呢?DNS 体系里,还有一个东西叫做 Zone Transfer。普通的 DNS 查询,一般只是查询域名的 A 记录,DNS 服务器也只是响应一条 A 记录。但是 DNS 中还有一种特殊的记录查询,叫做 AXFR 记录。当一个 DNS 服务器接收到这种记录查询的时候,如果系统的配置没有禁止这条命令的查询,他就会把自己服务器内所存储的全部域名的全部记录都传输给请求者,这个过程因为数据量庞大需要进行持久的连续传输,且安全性要求高,一般是通过 TCP 协议传输的,如果走 UDP 的话可以被黑客用于实现能量恐怖的 DNS 放大攻击。这样一个查询 AXFR 记录,并取得另一台 DNS 服务器上所有记录的过程,就叫
做 Zone Transfer。
不过一般来说 DNS 服务器都不会支持或允许你任意查询 AXFR 记录,否则负担会大的不可思议,一般他们会有防火墙策略只允许特定的主机查询 AXFR 记录进行 Zone Transfer。对于那些不支持递归的 ISP的 DNS 服务器,只可能是以这样的形式取得域名记录的 (别跟我说拿 U 盘拷啊)。那么好了,支持递归解析的 DNS 服务器已经被劫持了,而只能迭代的 DNS 服务器又只能从递归服务器那里通过 Zone Transfer 复制记录,毫无疑问复制到的也是被污染的数据,那么全国的 DNS 就已经被GFW 搞定了。你也许会说,万一我从国外的 DNS 服务器进行 Zone Transfer 呢,你不是说 Zone Transfer还是走 TCP 的吗,这一般不会被劫持了吧。
这的确是个办法 (其实我也是临时想到的)。但是我们也说了,绝大部分DNS 主机不会允许你做 Zone Transfer,这个负担太重了,基本上你只能自己去国外架设服务器,搜集递归数据,然后 Zone Transfer 到国内了,所以国内确实有些私人的 DNS 是没被污染的啊。当然我觉得他们更可能的是在服务器上用写死 hosts 的方式实现的,这种方式怎么说呢,事实正义,而程序不正义,任何人为干预修改域名记录的行为我觉得本质都是劫持。而对于各大 ISP 的 DNS 来说,你觉得国营企业,有这可能吗?
敏感词过滤
我对这种技术的研究比较少,只能大概的介绍一下,如果需要具体的细节,可以在你能翻墙之后参考这篇文章,还有这篇文章,或者 wikipedia 上关于TCP 重置攻击的描述。
我们平常浏览网页所用的协议叫做 HTTP 协议,基本上你在每个网页的开头都可以看到 “http://” 的字样。HTTP 协议本身是一个比 TCP,UDP 更高一层的 (更贴近用户) 的应用层协议,但上层协议最终都是要以封包后以更底层传输层的方式进行传输。例如 DNS 协议是用 UDP 协议传输,HTTP 协议使用的就是TCP 协议。
我们说 TCP 相对 UDP 来说是更为安全的,但这只是相对的,TCP 数据依然是可以被中间人修改的最简单的例子,就是你们可能用过的一些屏蔽优酷,土豆视频广告的插件和脚本,这些东西的原理就是拦截并修改 HTTP 数据流,将涉及广告的部分代码进行替换。这说明了两点,TCP 协议的内容是可以被感知和识别的 (比如找到广告代码的部分),也是可以被修改的 (替换成无广告的代码)。虽然 TCP 协议不会像 UDP 那么容易让第三方伪造和修改数据,但肯定位于你和境外服务器中间的 GFW 还是可以做到的,没见过圣旨的情况下伪造圣旨有困难,可是让传旨太监拿着现成的圣旨改个字还是很容易的。
HTTP 连接的建立,有一个著名的三次握手过程: 客户端先向服务器发出连接请求,服务器返回一个连接许可,客户端再发起连接确认。如果 GFW 检测到你要访问的某个地址中包含了敏感信息 (域名本身可能就是敏感信息),他就修改或冒充服务器返回的连接许可,告诉你服务器拒绝连接,这样客户端就会自己放弃连接,你们平常上网经常看到的大部分 “网络连接被重置” 就是这个的结果,当然,少数情况下可能服务器真的出问题也会拒绝连接。
你也许会问我们能不能忽略这个重置 (RST) 消息? 当然可以,可是 GFW 比你想得更多,他不光发送RST 给你,还发送 RST 给服务器,这样服务器也会认为你已经断开连接了,就不再发送数据给你了。GFW 这种做法的优势很明显: 不需要对完整的 HTTP 页面数据进行检测,只要发现 URL(网页地址)中有敏感信息,就直接断开了你和服务器之间的连接,大大减轻了他自己系统的负担。但这种做法的缺点也很明显,检测力度太弱了。大家最熟悉的例子莫过于 SexInSex 和草榴这些色情网站,你直接输入他们的主站域名一般都是连接被重置,但只要找个其他的 IP 替代域名,一点问题都没有,因为 GFW 对这些网站检测的敏感信息仅仅是 URL 中的域名,在你把域名替换为不敏感的 IP 之后,你查看的页面里面有100 个 “无码”200 个 “3P” 它也完全不在乎。
但不是说 GFW 对敏感信息的检测仅限于域名,对于一些数据量很大,内容庞杂的网站,GFW 的URL 检测会精确到页面。例如你在 wikipedia 上查 “种猪饲养技术”,党和国家会为多了一个纳税人感到高兴而绝对不拦你,可是如果你要查 “八九年天安门学运”,那 90 秒内你就别想访问 wikipedia 了。
我们也经常碰到另一种情况,就是某些网站使用的是 HTTPS 协议,似乎在使用这些网站的时候我们从来不会碰到页面连接被重置的问题,这是为什么呢? 这是因为 HTTPS 采用了公钥 + 私钥 8 加密技术,数据在封包成 TCP 包之前就已经被加密过,敏感的信息被加密之后就是一堆无法解读的乱码,这些信息对于 GFW 来说是无法解读的,或者说解读成本是巨大的,这就使得一直到今天,我们也没有看到哪个 HTTPS 页面被 GFW 连接重置。
IP 阻断
这应该是我所知道的 GFW 的最后绝招了。
我们前面说了 GFW 的手段有 DNS 污染,敏感词检测重置,如果一个网站不用域名直接用 IP,或者有很多方法可以让别人知道它域名的真实 IP(草榴在这方面就很出色嘛),同时页面还都是 HTTPS 形式加密过的,GFW 就没办法了?Naive! 没办法骗你去南半球看兵马俑了,骗你说紫禁城被拆迁了你也不相信了,老子就把你要走的路直接给断了。其实我觉得我应该在第一章补充一个路由概念的,好吧,就在这里说吧。
首先我们要知道,网络上的任意两个 IP,他们之间建立连接几乎都不可能是直连的,如果任意两个IP 都可以直连,GFW 就只能裁掉全部技术人员改建爆破大队直接破门了,就好像如果你从广州到北京是通过一条直通的封闭管道进行的,那车匪路霸早饿死了。无论是面向连接的 TCP,还是不面向连接的UDP,数据在网络上的两个 IP 之间的传送,都是通过一级一级的路由中继完成的,只不过 TCP 的中继路径在连接建立之后是固定的,而 UDP 的中继路径每次都不同。
例如你要从国内的 A 到国外的 B,数据传送的实际路径可能是这样的:
别的节点都可能会变,但 GFW 肯定会在这条路的中间出现是不用怀疑的。你看,GFW 这个位置不当车匪路霸都可惜了。一个数据到达一个节点后,下一个节点发往哪里是由一个叫路由表的东西控制的,动态路由表是由一套路由算法得出的,而静态路由表则是可以人为指定的。GFW 觉得静态路由表是个好东西,就充分发挥了它的错误利用。
假定 GFW 发现某个境外反动网站,并且知道了他的 IP 是 “1.2.3.4”。我们已经知道 GFW 是控制了中国的网络出口网关的,也就是说不管你怎么访问,不管前面后面的节点是什么,最终都要通过 GFW 这个节点。那么一个对 “1.2.3.4” 发起的网络请求,在数据到达 GFW 节点之后,根据路由表下一个节点应该发往哪里呢?GFW 猥琐地猛吸一口烟屁股,嗯,发往达美克星!
达美克星? 没错! 那是什么鬼地方? 不知道! 那怎么办? 爱咋办咋办! 反正这个网络请求最终的命运我是不知道,只知道它被发送到了一个黑洞地址。同样的,所有发往 “1.2.3.4” 的请求全部要被发往这个根本不存在的黑洞地址。当然你要觉得达美克星太残忍,撒哈拉沙漠正中央也是可以考虑的选项,总之是一个让你进得去就出不来的地址。那么,毫无疑问的,国内网络通往 “1.2.3.4” 的路径就被切断了,你知道IP 有什么用,部署了 HTTPS 加密又有什么用?
近期评论