2009年7月28日星期二

组合翻墙方案

1.墙的存在和原理简述
1.1.墙的存在
    在您访问某些网站的时候,经常会发现无法访问。通常来说,这是服务器挂了。但是现在,越来越多正常的服务器出现了无法访问的情况。这些服务器中有一些是因为色情和暴力问题,但是更多则是政治层面的因素,例如google和twitter。对于用户来说,可能不关心政治层面的因素。但是政治自然的关心了你,所以我们需要找一种方法,让我们依然能够使用网络上一些很重要的服务。例如gmail(本文即是在gmail中写成的)。本节中,我将简述国家网络防护工程(简称GFW, Great FireWall)的工作原理,并在下一节给出一些比较成熟的翻墙方案。
1.2.DNS污染
    我们通过DNS(Domain Name Service)将域名转换为IP地址。通常而言,我们不会怀疑ISP的DNS服务器的可信性。然而在某些地方,DNS服务器被用来欺骗客户端,达到屏蔽的作用。例如,在上海的某些地方,fanfou.com曾经被指向127.0.0.1。如果机器按照这个地址访问,那么肯定无法获得预想的数据。
    这个方案如果控制不当,可能造成全球性的后果。曾经有报道,伊朗将youtube的域名指向了自己的一台蜜罐(Honeypot)服务器。但是由于配置不良,因此DNS错误被扩散到了伊朗以外,导致全世界的youtube访问都被定向到了这台蜜罐。整个过程造成了youtube6小时以上的服务中断。
1.3.DNS替换欺骗
    由于DNS污染会被下面2.1节的方法绕过,因此在某些地方针对OpenDNS的数据被进行了替换欺骗。UDP53端口的查询数据包被拦截和替换,其造成的结果就是即使使用了OpenDNS,返回结果和电信服务器的结果仍然一致。
1.4.IP禁止
    对于某些IP,防护系统直接禁止了该IP的访问。这种手法一般见于早期,由于经常导致误杀和株连,同时对最普通的proxy都无效,因此现在已经不常使用。
1.5.关键词过滤
    防护工程在中国网络的核心路由器上,都放置了一些探头。具体的方法为配置一个核心路由器的镜像端口,将所有通讯数据全部向端口转发一份。该端口指向一套深度包检测集群。如果数据没有异常,则不对通讯进行干扰。如果数据异常,则发送RST包拦截通讯。同时记录双方IP,拦截其后5分钟内的所有TCP SYN包。
    这种方法的优势在于,无论多复杂的网络拓扑结构。只要能够开镜像端口,就可以工作。无论多大的规模和多高的流量,只要能添加服务器,就可以支持。同时由于屏蔽效果好,对普通访问的干扰小,因此目前已经成为最主要的屏蔽方式。
    这种手法无法针对UDP工作,因为UDP不存在链接断开状态。同时如果双方都屏蔽RST包,则连接不会被中断。然而如果双方都屏蔽RST包,会导致一些主动断线在对方那里变成死连接,因此无法通过拦截RST包来防御。同时,按照当前的测试结果,IPv6的包并没有被拦截。相信这是因为核心路由器支持了IPv6,但包检测集群尚未支持IPv6包检测。
1.6.热点屏蔽
    近来发现一种趋势,当某个链接的热度非常高的时候,通向此链接的访问会被屏蔽。由于是接受到RST包,因此不像是服务器超载。这是当前防护系统的新方向,尚没有更多资料。
2.翻墙方法简述
2.1.OpenDNS
    DNS污染可以通过修改自己的DNS服务器来屏蔽。以Linux为例,当前你的DNS服务器配置可以在/etc/resolv.conf中查看。你可以将其替换为OpenDNS的DNS服务器,而非电信的服务器。OpenDNS是一家商业公司,通过提供DNS服务来收费(不具体解释商业运作)。一般来说,他们的DNS服务还是比较准确的。
    通过OpenDNS可以防御DNS污染,但是无法防御其余方式,而且会被DNS替换所干扰。因此建议一般作为常规网络配置,而非专门的翻墙方案。
2.2.hosts
    hosts的目地和OpenDNS一致,但可以防御DNS替换。其原理是通过将正确的DNS结果写入/etc/hosts文件,在绕过网络解析过程。从而避免DNS出错。
    该方式无法防御1.4-1.6的屏蔽。
2.3.proxy和变形
    针对DNS欺骗和IIP屏蔽,我们可以通过指定一个国外的代理来访问。由于DNS解析在代理商进行,因此一般不会被欺骗。由于不直接访问IP,因此IP屏蔽也失效。
    一般而言,该方法无法屏蔽1.5的屏蔽,但是有一些变形产品(例如Firefox的gladder插件),通过变形URL请求,使用特殊代理的方式对1.5进行了部分绕过。但此种方式不保证100%成功。
2.4.ssh -D
    ssh是一种安全的远程命令行工具,具有很多端口转发选项。其中有一种动态端口转发选项,在服务器端开启后,使得ssh可以被作为一个socks5代理服务器使用。
    此种方式需要有一个墙外的ssh服务器,一般可以购买墙外的空间,他们会附送一个。此种方式可以绕过全部屏蔽方式,但是由于ssh本身的稳定性,因此经常有掉线的问题。而且有的服务器关闭了动态性转发选项,或者对长期连入的ssh连接进行断线处理。同时,由于很多人接入同一个IP进行翻墙,因此很多网站(例如google)会认为你的访问不可信。
2.5.tor
    tor是一种分布式代理工具,可以在隐蔽源和目标的情况下访问服务器。该方法可以绕过所有屏蔽方式,但是通常而言,该方法的访问会比较慢。同时也存在访问不可信的问题。
2.6.gae
    gae是google的个人引擎服务,一般由很多服务器构成,而这些服务器一般位于国外。有人针对这个特点,制作了特殊的python程序,能够将客户的访问转换成特殊的加密包,在服务器上访问目标服务器。因此可以被视为一种特殊的代理协议。该方法可以绕过所有屏蔽方式,但是由于众所周知的原因,gae服务器本身有的时候也会被屏蔽,导致该方法无法工作。而且由于google本身的屏蔽,该方式对于某些网站也是无法访问的。该方式也存在访问不可信的问题。
2.7.vpn
    vpn是唯一一种能够快速有效,一劳永逸的翻墙方式。使用vpn后,等同于你的机器拉了根线接在国外的网络端口上。因此该方法可以穿越所有屏蔽方式,同时很少有访问不可信的问题。唯一的问题是vpn,尤其是快速的vpn很难得,而且通常很贵。
3.组合翻墙
3.1.问题
    纵观全部翻墙方式,每种方式都有一定的缺陷。2.1-2.3并不总有效,ssh不稳定,tor慢,gae看运气,vpn又贵。同时,我们还要借助终端的客户端组件(foxyproxy之类)来区分被屏蔽的网站和普通网站(使得普通网站的访问不使用特殊的方式)。
3.2.目标
    本文试图通过某种方法,同时使用2.4-2.6的一种或多种方法。达到访问透明,使用稳定,速度尽量快,流量尽量小的目标。
3.3.架构
    我们使用squid和haproxy进行代理调度,达到上述目标。squid是一种老牌的开源代理服务器,其特征是会对代理内容进行缓存,减小访问流量。同时,可以将请求转发到其他代理上。从而会自动检测和管理多种代理服务器。haproxy是一种基于tcp和http的反向代理程序,在此我们需要使用它的TCP代理能力,将多种socks5代理集成为一个。
基本架构图如下:
                                                      /       -> tor
web brower -> squid -> privoxy -> haproxy -> sshtunnel
                        \     -> gappproxy
3.4.优势
    相对单层代理,组合方式具有多个优势。
    使用squid分离访问线路,并缓存访问数据。对大规模密集访问,可以有效的减小流量。而且对除Firefox外的浏览器,可以根据其访问范围控制代理线路,进一步减小代理流量。(Firefox可以使用AutoProxy或FoxyProxy)
    使用haproxy反向代理了socks5服务,因此可以并行使用多个sshtunnel的带宽。同时自动检测这些ssh是否可用,保证了访问的连续,同时也非常容易添加和减少代理。
3.5.劣势
    本方法有一个比较明显的问题,即squid无法直接使用socks5代理,因此需要通过privoxy进行转换和保密。但是此时squid只测试privoxy的存活,而不理会socks5的存活。因此当haproxy的后端全部失效的时候,squid仍旧会认为privoxy有效,进而导致出现privoxy的错误页面。
    同时,由于haproxy只检测ssh端口是否相应。因此当远程服务器几乎不响应代理请求时,haproxy并不会将这一代理移除出列表。从而导致某些请求需要非常长的时间完成。
3.6.适用范围
    本方式在完成设置后,可以稳定,快速,小流量的访问所有网站。客户端无需过多的设置。但是服务设置过于复杂,系统庞大,多数时候还需要一台专门的Linux。相对而言,这种方法更适合于3-5人以上,同时需要翻墙的情况。通过一台专门的虚拟服务器作为代理,可以顺利的让多人同时使用国际网络。
4.一个实现
4.1.基本系统
    debian stable,aptitude install squid3 squid3-cgi lighttpd tor privoxy haproxy。
4.2.gappproxy
    针对gappproxy项目,请自行去其主页上查看服务器组建方式。作为本次成果之一,贝壳封装了一个gappproxy的deb包。修改了部分源码,并形成了服务。需要的用户可以下载gappproxy-1.0.0beta_all.deb包,安装并修改配置文件即可直接使用。
4.3.sshtunnel的封装
    一般而言,我们使用ssh -D来开启sshtunnel。但是这样做有几个缺陷。首先是tunnel无法跟随系统启动,其次是由于tty关闭后程序一同关闭,因此往往需要screen或nohug来保持连接,最后是ssh往往容易意外关闭,导致需要手工重启。
    贝壳针对这种情况,包装了一套脚本,并形成sshtunnel_1.0.0beta_all.deb包。需要的用户可以下载并修改配置。服务启动后即一直运行,关闭后会自动重启。
5.远景目标
    上述系统安装的细节并未详述,同时,对于新手也太过复杂。因此,考虑实现一套完整的最小虚拟机,提供完整的上述功能。并且给出一套界面,使得用户可以方便的配置和操作整个代理系统。

3 条评论:

流水弦歌 说...

这篇写得很不错,尤其是最后的系统架构,你认为这套能够装入一个嵌入式系统中么?

brite 说...

hi.有人根据此帖,搞了个squid+pac翻墙方案:www.jayproxy.com/jayproxy.pac,他说是根据你这帖子的第4部分实现的,再问他更多,他就不愿说了。
我在自己的vps上安装了squid,然后在浏览器中设置http代理-自己的vps服务器的ip:端口号(即,在squid.conf的 http_port 后面所设置的端口号),之后可以浏览youporn.com网站,但是浏览不了海外一些敏#@#感的政@#¥治网站,估计是这些网站的url里有“关键字 ”。看到他搞的squid+pac文件,在浏览器的自动代理配置栏输入该pac文件的链接地址,然后就可浏览这些敏@¥%感的网站了。不知他是如何实现的,博主可详细说说吗?

Shell Xu 说...

流水弦歌:嵌入系统中我刚刚做过,不稳定。使用的是openwrt的方案,ssh的稳定性是个大问题。
brite:我需要知道细节。