翻墙的方法有很多,譬如PPTP,SSH-D,SOCK5,但是终究需要在客户端安装一些软件,而且如果提供给其他人使用又会有安全问题,比如暴露密码。有一种翻墙的方法最容易,那就是Host,通过修改客户端的Host文件、路由的自定义Host或者局域网DNS服务,来达到翻墙的目的。
譬如我想翻 www.google.com 那么只需要配置
x.x.x.x www.google.com
甚至如果你在路由设置好这个,访问该路由的人都自然而然的翻墙了。
思路是这样的:通过Host的改变,将所有请求发到一台Server上,然后Server将内容封包发给VPS或者其他可以翻墙的服务,来达到翻墙的效果。
所以问题来了,首先,这不可能在应用层做手脚,因为转发的服务有可能是https,所以就请求的包而言,我们是不能对其做任何改变,否则证书的验证就无法通过,所以通过nginx或者其他简单的服务是无法达到目的的。
所以最简单的架子是这样的
其中Client选用的是Redsocks,Server选用的是Dante,Server搭在国外的VPS上。
然后问题又来了,Redsocks对目的地址是用SO_ORIGINAL_DST来获取的(如果用iptables转发的话),譬如我提供Host的地址是10.11.1.101,我把 www.google.com host到这个地址,那么socks封包的目的地址则为10.11.1.101,将此包发送到Server,那么Server依然会请求这个内网地址,达不到转发的目的。
没辙了,最后没找到太好的解决方案,所以fork了一个redsocks工程,使redsock可以自定义目的地址,源码为 https://github.com/henry42/redsocks/
好了,Client端解决了,那么Server也没大问题。按照这个搭建起来一切正常,但是会发现偶尔无法访问,断掉若干分钟,然后又奇迹的好了。其实原因很简单,那就是Socks5协议只不过加入了身份验证和Socks5的一些协议内容,传输的内容其实对GFW来说一览无余,所以如果你Host的是http服务,那么GFW依然会发现,然后发一堆RST让你无法正常链接,随后再给你丢小黑屋里关禁闭几分钟。知道了这个,那么解决起来就简单了,加一层 stunnel吧,最终的结构就是
简单的过程就是
- 请求因为Host的原因发送到Client服务器
- 用譬如iptables将请求转发给Socks5 Client
- Client将请求打成Socks5封包并修改目的地址到真实的地址,发送给Stunnel服务
- Stunnel服务对国外的Stunnel的server进行一系列balabala证书验证,然后解包给Socks server
- Socks server真正相应请求,然后再将结果返回
因为整个过程没有对请求包有任何干扰,所以什么协议都适用,不只http,https。从这个可以看出这种方式的好处
- 不暴露你的任何环境的用户名密码,将这个Host分享出去也没什么问题
- 客户端不需要安装任何软件,配个Host即可
- 配合路由或者DNS可以达到局域网透明翻墙,愿意的话可以加入PAC
- 通过对Client修改,可以对流量(tc)或者来源(iptables)进行限制。
- 没有协议要求
缺点也很明显
- 因为对包不识别,所以只能一个ip对应翻一个墙外ip,对大量域名配置起来是灾难
- 还是需要配置Host,这个算优点也算缺点了
- 累你一个人,搭起来还是稍微有点儿麻烦的
okay了,简单来说,这个有什么用呢……
如果是你一个人想翻墙那么就不用这么折腾了,来说说我这边的使用场景:
因为公司内部有自己的DNS(你自己搭个Dnsmasq也未尝不可),所以我把一些常用的地址做了处理,方便公司内部的人访问,这样他们访问这些地址就像没有墙一个感觉
譬如 www.google.com
譬如 chrome-devtools-frontend.appspot.com
譬如 …
没了,抛砖引玉,剩下的自由发挥吧。