组合翻墙方法——细节

   中国这网络,越来越没法上了。现在你访问国外禁网,就会中断连接10分钟。问题是我也不知道哪个网是禁止的…
   现在教大家一招,基本能够永久套上翻墙。理论上你就没有中招的可能,尤其适用于公司使用。
   首先是squid,这个是流量分离和缓存的关键部件。你可以用pac替代,但是这只局限于某台具体的机器,并且代理用户支持pac。squid的好处是,任何http访问都可以分流,而且无须客户端支持。甚至如果你精通squid配置,你可以配置成透明代理(cache拦截),从而避免在每台机器上修改代理配置。当然,cache拦截是有技术问题的,具体请参考这篇(http://home.arcor.de/pangj/squid/chap09.html#a6)。

   squid的配置如下:
include /etc/squid3/gfw.conf
acl localnet src 192.168.0.0/16
http_access allow localnet
http_access allow localhost
cache_peer 127.0.0.1 parent 8123 0 no-delay no-query

cache_peer_access 127.0.0.1 allow gfw
always_direct deny gfw
never_direct allow gfw
   以上配置是允许192.168.0.0的C类内部子网访问本机,所有gfw规则的域名必须通过8123端口的上层代理,而其他的直接访问。注意以上不是完整配置,不保证可以独立运行,只保证在debian的标准配置文件的基础上,修改以上内容就可以工作。独立配置你可能还需要加入以下两句。

http_access deny all
http_port 3128
    配置中的gfw.conf是gfw这个规则的定义文件,这个文件是由程序生成的,程序如下。注意,你系统上的python版本应当在2.5以上。
#!/usr/bin/python
from __future__ import with_statement
with open('gfw', 'r') as fi:

   for line in fi: print 'acl gfw dstdomain .%s' % line.strip()
   以上内容,保存为平文本,赋予执行权限后,直接执行即可。同目录下必须有一个gfw文件,平文本,里面一行保存一个域名。域名不以.开头,可以使用泛域名(例如google.com匹配www.google.com)。执行后打印出内容,所以你还需要重定向。./gfw2squid > /etc/squid3/gfw.conf。当每次gfw文件升级时,你都需要重新生成,并且迫使squid加载。方法是squid -k reconfigure。

   OK,现在你有一台配置了分流的squid,然后你需要一个可以翻墙的代理。由于我的目标是看youtube,所以我采取了一个非常复杂而高性能高可靠的方案。
   我配置了一台polipo作为http socks5协议转换。由于squid的特性,不能直接使用socks5,因此还是做了一重转换的。polipo这个代理的性能和稳定性也相当不错,用来做缓存代理也是可以的。不过我们用了更强大的squid,就没必要用polipo了。因此启用以下几句来减少polipo的性能消耗,同时,将本地8123端口的http代理服务转向到7777端口的socks5代理。

socksParentProxy = "localhost:7777"
socksProxyType = socks5
chunkHighMark = 819200
objectHighMark = 128
diskCacheRoot = ""
    在polipo之后的,是一个负载均衡系统。http是一种无状态协议,对不对?所以同一个session可以分布在不同的服务器上处理。也是同样理由,我们可以把后端的socks5连接分布到多个socks5服务器上。以下是haproxy.cfg的简单配置,由于提取出时做了部分删节,我不保证一定能在所有系统上跑通,但是同样的,debian问题应当不大。

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 4096
        user haproxy
        group haproxy
        daemon
frontend socks5
        bind    0.0.0.0:7777

        default_backend ssh-balance
backend ssh-balance
        balance roundrobin
        server  ssh1 0.0.0.0:7778 maxconn 20 weight 20
        server  ssh2 0.0.0.0:7779 maxconn 10 weight 10

        srvtimeout      20000
    最后是一个核心问题,7778和7779是真实的socks5翻墙代理服务器,具体是什么呢?很简单,多台ssh服务器。当然,如果你用别的方案,只要是提供socks5的,都可以混用。
    整个系统运转起来后,一个公司内十多号人的访问可以全部通过这个系统。具体需要多少个ssh,多少性能够用要看翻墙的频率。但是由于做了负载均衡和本地缓存,所以性能是相当可以的。单人使用的时候可以看youtube,十多人同时使用的时候还能正常的访问google搜索,邮箱服务等。而且不翻墙没有ssh压力,节约流量,也方便使用。后端的方案可以做其他变化,例如如果你是多台vps,你可以在上面部署polipo,然后用ssh做端口转发,本地用haproxy做负载均衡。同理,如果你使用别的方案,只要是提供http代理的,也可以省去polipo,用haproxy群集。

    至于另一个核心问题,gfwlist的获得,你可以从autoproxy中提取一个,自己处理,过程很是繁琐哦。贝壳已经处理好了一个,做了签名压缩,你可以找我要。

gfw升级了?

    今天使用的主机上有个朋友发来消息,api用不了了。贝壳检查了一下,主机正常阿。

    最终,发现问题是这样的。
shell@shell-deb:~/tmp$ wget http://shell909090.com/apis/
–2011-02-23 10:08:39–  http://shell909090.com/apis/
正在解析主机 shell909090.com… 74.86.182.175
正在连接 shell909090.com|74.86.182.175|:80… 已连接。
已发出 HTTP 请求,正在等待回应… 读取文件头错误 (Connection reset by peer)。
重试中。
–2011-02-23 10:08:41–  (尝试次数: 2)  http://shell909090.com/apis/
正在连接 shell909090.com|74.86.182.175|:80… ^C
shell@shell-deb:~/tmp$ wget http://shell909090.com/
–2011-02-23 10:13:36–  http://shell909090.com/
正在解析主机 shell909090.com… 74.86.182.175
正在连接 shell909090.com|74.86.182.175|:80… 已连接。
已发出 HTTP 请求,正在等待回应… 200 OK
长度:1156 (1.1K) [text/html]
正在保存至: “index.html”
100%[======================================>] 1,156       –.-K/s 花时 0s      
2011-02-23 10:13:37 (277 MB/s) – 已保存 “index.html” [1156/1156])

CNNIC的证书

最近,技术圈里面在争论CNNIC的证书被加入到信任根证书里面的问题。本文章试图和专业人士探讨这一变化的过程,以及向非专业人士说明会造成的影响。所有段落前会标明针对的群体。
事情的起源,是有人发现CNNIC的证书被加入了Mozilla和系统的信任根证书链里。这引发了大家对早年CNNIC所做的流氓软件的回忆,因此大量技术人士强烈反对。所做的反应包括发起BUG讨论提请Mozilla删除CNNIC的证书,发起投票,写信给Entrust阐述问题等。下面会简述一下信任根证书链,还有CNNIC的背景和历史。
本段适合非专业人士阅读。我们在访问一个网页的时候,通常有两种常见的通讯方式。http和https。区别在于,https会使用网站证书加密通讯过程。证书加密包含了几重的意义,首先,证书保证了你们的通讯没有第三者能截获。其次,证书验证了你访问的网站,是否是他号称的那个网站。也许很多人无法理解,这两种攻击怎么可能发生。要理解一点,中国电信也不是铁板一块,你完全无法指望他们的员工也绝对安全。否则的话,为什么所有银行都使用https来加密访问过程呢?
本段适合专业人士阅读。那么,不使用证书会发生如何的攻击呢?一旦有某个人更改DNS(这东西让百度都吃了亏),以某个服务器替换了你的银行(或者gmail)。那么,你访问你的目标域名的时候,就会被定位到他的中间机器上,他再使用代理技术,通过ssl访问目标服务器。整个过程如同走代理一样,唯一的问题就是你的密码泄露了。那么证书是如何防御这个攻击的呢?如果你访问目标机器,目标机器会让你验证一份证书,标明他的域名(用于防止域名劫持的),签署者。一旦域名不符合,或者你不信任证书,就会报警。那么攻击者如何复制这个证书呢?首先他无法通过访问的方式获得证书原文,因为证书给你的其实只有公钥部分。其次他无法将这个过程也代理下来,因为如果这么做,下面的内容就全是不可解的了,那他就纯粹花钱把自己弄成代理服务器了。最后,他也无法生成,因为按照规定,只有域名的拥有者可以向特定的单位申请证书。于是,他无法复制证书,攻击就会失败。
本段适合非专业人士阅读。然而,你需要信任什么证书呢?如果你要一家一家的信任证书,会发生什么?你见到是否信任就会习惯的去点,这对安全于事无补。因此,这里引申出一个证书链的问题。通常系统内内置了一些证书,这些证书叫做信任根证书。这些证书的权限是,可以让你信任其他证书。而被他们授权的证书,则分为可以继续授权和不可以继续授权两种。一旦被他们签署授权的证书,最起码你访问的时候不会有警告了。现在,CNNIC加入了这个根证书链。那CNNIC是个什么公司呢?他自称是中国科学院下属的中国互联网络信息中心,服务于科学和研究的机构,但很多人指出CNNIC的直接主管是工信部。当年,CNNIC推出中文域名服务,这项服务需要在几乎所有人的电脑内安装插件。他为了提高安装率,使用了不可删除的保护技术。这导致很多人的电脑安装后,无法卸载程序。至于安装呢?也不全是自愿安装(我不排除自愿者,绿霸还有自愿的呢)。他们曾经利用系统漏洞,向大量电脑上强行安装插件。而且CNNIC还借助官方身份,大量推行中文域名——其实他们根本就不是政府机构,而是非营利机构。并且,在前两年拼命忽悠CN域名,最近又突然停止域名解析(虽然是国家规定的),道歉赔偿啥都没有。大家自己想,真的可以信任这种公司么?
本段适合所有人阅读。现在CNNIC已经进入了信任根证书链,如果配合国家级的DNS劫持技术,理论上可以构造一个假的mail.google.com,或者www.hotmail.com。走代理,自己给自己签署一个证书。从而获得你的完整会话。这里(http://autoproxy.org/zh-CN/node/66)有比较大的说明和讨论。
我对这个事情的观点是。作为Mozilla或者任何根证书的发行机构,在没有直接证据的情况下,不大可能拒绝一个国家级机构的要求。然而,无论任何原因,信任一个机构,就代表你要为他的行为负责。如果CNNIC做出任何危害用户安全的行为,Moziila,微软,Debian.org会被我作为同罪者考虑和抵制。同时,系统发行的根证书系统,是否要去信任,是我们每个人的问题。如果你觉得CNNIC根本不值得信任,那么你可以删除他的所有证书,以及签署了他的所有证书。目前而言,我删除了CNNIC和Entrust的所有证书。

组合翻墙方案

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.远景目标
上述系统安装的细节并未详述,同时,对于新手也太过复杂。因此,考虑实现一套完整的最小虚拟机,提供完整的上述功能。并且给出一套界面,使得用户可以方便的配置和操作整个代理系统。

ssh翻墙服务

不多说了,上脚本。
———–/etc/init.d/sshtunnel————
#!/bin/bash

PATH=/bin:/sbin:/usr/bin:/usr/sbin
CONF=”/etc/default/sshtunnel”
source $CONF

if ! [ -x /usr/bin/ssh ]; then
exit 0
fi

start ()
{
echo -n “Starting tunnel..”
ssh -CNq -D “$PROXYPORT” “$USERNAME@$SSHHOST” -p $SSHPORT -o ServerAliveInterval=30 &
echo “done.”
}

stop ()
{
echo -n “Stopping tunnel..”
PID=$(netstat -nlp -4 | grep “:$PROXYPORT”)
PID=$(echo $PID | sed “s/.*LISTEN\s*\(.*\)/\1/” | cut -f1 -d/)
kill -9 $PID
echo “done.”
}

case “$1″ in
start|restart)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo “Usage: $0 {start|stop|restart|clear}”
exit 1
;;
esac
exit 0
—————–end of file——————
———/etc/default/sshtunnel———-
PROXYPORT=7777
USERNAME=abc
SSHHOST=abc
SSHPORT=22
—————–end of file——————
首先准备一个远程服务器,获得域名端口,用户名密码。而后将上述脚本放置于指定位置,修改/etc/default/sshtunnel的值,即完成配置。但是上述脚本并没有解决自动登录问题,因此,请生成一个没有密码的密钥,将公钥导入远程服务器。
在完成配置后,可用update-rc.d sshtunnel start 90 2 .进行自动启动服务的安装,其中的2请替换成服务器的默认启动级别。如果不知道可以用以下方法查询。
# cat inittab | grep ^id
id:2:initdefault: