记得是去年某个时候,在一个群里问大家是怎么翻(什么)墙的,发现很多人是用go-(xxoo)agent的,而我当时完全没听说过go-agent,因为我已经N多年不翻(什么)墙了,于是,有人就说:“连go-(xxoo)agent都没用过你还是程序员吗?”说实话,我也不希望我是程序员啊!可我真的没用过go-(xxoo)agent啊!
想起我一位前同事,工作很多年了,却从来没用过linux!(也不知道他说的是真的还是假的,至于你信不信,反正我是信了。)他说这是他第一次用linux!(也难怪啊,他在原来的公司干里好多年,公司是用.net的。自然没必要用linux。)但我不能说他不是程序员,事实上,他工作完成得很出色。i第一次接触linux,很快就熟悉了。
不用linux还可以用windows,不用go-(xxoo)agent却用什么呢,这是个问题。
原因:
首先说一下问什么不用go-(xxoo)agent。
1.用go-(xxoo)agent得用goo(xxoo)gle帐号,还得去注册app,这又得提供一遍自己的信息,鉴于我认为goo(xxoo)gle也是窃取用户隐私的好手,这是我极不愿意做的。(我得出这个结论是因为我的一个网站,明明这互联网上还没有链接,goo(xxoo)glebot却一直在爬,这让我想到是因为我这chrome浏览器里打开过这个链接,所以,goo(xxoo)glebot就开始爬孤岛链接了,这和某数字公司爬链接的方式很像啊。。。。。。)
2.听说很多go-(xxooo)agent的ip被(什么)封了。我想这可能是信息加密没做好,终究被g(xxoo)fw看出来了。这也是用的人多的坏处,gf(xxoo)w更容易发现。
3.感觉不可控,我想自己弄个能翻过去的,并且信息这边加过一次密,中间传输时各个路由完全不知道我发送的是什么,包括dns解析也是加密后代理的。总之,就是g(xxoo)fw看到的就是一堆什么协议都不是的乱码,这样我就高兴了。
实现方式:
因为gfw两种主要手法是:
1.dns(什么)污染,即用户发起域名转ip的dns解析的时候通过中间拦截,故意返回错误的ip,导致用户无法链接。如访问脸(什么)谱网的时候大陆解析到的ip和香港解析到的ip是不一样的。这是通过监听udp53端口实现的。
2.文本关键字识别过滤,即发送的请求与返回的结果中如果有g(xxoo)fw不希望看到的关键字内容的话,就会发送一个错误的返回结果给用户,一般是页面重置。这个监听的端口至少包括80,443,其他端口也有可能被监听。
因此需要:
1.dns解析请求的代理服务器,而且发送dns解析请求时,必须把要解析的url加密,以防止g(xxoo)fw中间拦截;返回时要把返回的ip加密,以防g(xxoo)fw拦截。这也就意味着,我们必须这本地也架设一个dns的代理服务器,来拦截本地的dns请求,并且这这个请求上做些手脚,让g(xxoo)fw认识不出来,传输到境外(或香港)的主机时,再还原这个请求,得到正确的ip。得到ip后,我们又要把这个回应的包加密,安全传输到境内,之后再解开,得到正确的ip。
2.socket级别的请求代理服务器,同样的,本地也需要架设一个socket请求的服务器,用来加密http请求后发送请求,而在远程代理服务器上,解密请求,并得到正确的相应后,又把这个回应加密返回来,到里本地服务器,又解密回应,之后才是浏览器能看到的东西。
要注意到本地的dns请求是向53端口发送的,就我目前所知道的,第一次发送的这个端口53应该是没法改变的,当然,你微调linux代码,重新编译linux当然可以改变这个。
大体来说是这样子的:
dns代理部分: 浏览器->dns请求->本机dns(53端口)服务器-》加密请求,改变端口->g(xxoo)fw-》远程dns服务器-》解密请求,改为53端口-》dns递归请求-》正确ip地址->加密回应,改变端口->g(xxoo)fw-》本机dns服务器->解密回应,返回给浏览器
socket代理部分也是类似的,只不过端口不同而已。
这样子做有明显的好处:
1.能支持所有境(什么)外网站的访问,包括观看某大型视频网站的flash视频。
2.能观看自己有主机地区的有地区性版权的视频。
3.最重要的,数据完全加密,就连g(xxoo)fw都完全认识不了,自然就没有被封禁的后顾之忧。
这样子可能的缺点:
可能被反(什么)墙。目前来看,网易,腾讯两个网站偶尔有可能被反墙,绝大部分网站都很正常。
实际的代码实现:
在这里:https://github.com/jiyanmoyu/proxy_for_gfw
(注意,部署的时候至少要求你有一个没有墙的服务器)
其中dnsproxy是根据开源项目maradns改装而来,抽取了其中的deadwood服务器模块,并且改了一些代码而得。这本机部署dns_proxy_client,服务器端部署dns_proxy_server,这个部署很简单
cdsrc
make
就会生成一个dns服务器Deadwood,复制这个可执行文件到相应的地方,另外找个地方,新建一个.conf配置文件,比如在我机器上,配置文件是这样的:(两个填ip的地方没写上,根据自己的机器补上)
ipv4_bind_addresses= "" #这个地方填本机的ip地址,如192.168.1.3
#tcp_convert_server= "127.0.0.1" # IP of UDP DNS server
recursive_acl= "0.0.0.0/0" # Anyone may do DNS-over-TCP
verbose_level= 100
tcp_listen= 1
log_output= "/usr/local/maradns/log/deadwood.log"
chroot_dir= "/usr/local/maradns/share" # Where zone files are
upstream_servers= {}
upstream_servers["."]= ""#这个地方填远程主机(vps?)的ip地址
而我服务器上的配置文件是这样的
ipv4_bind_addresses= "" #这里填你远程主机实际的外网ip地址
#tcp_convert_server= "127.0.0.1" # IP of UDP DNS server
recursive_acl= "0.0.0.0/0" # Anyone may do DNS-over-TCP
verbose_level= 100
tcp_listen= 1
chroot_dir= "/usr/local/maradns/share" # Where zone files are
log_output= "/usr/local/maradns/log/deadwood.log"
注意到我还配置里一个log输出的地方,可以根据log文件查查问题
之后本机和服务器都可以这样启动
path/to/Deadwood-f path/to/conffile
当然,有一点要记得的,就是把
/etc/resolv.conf
配置成请求本地的dns服务器,即改成
nameserver 127.0.0.1 #有可能不是这个,而是你本机的ipv4_bind_addresses,如192.168.1.3
好了,dns请求改好了,接下来改socket请求。
这个socket的代理程序是用开源代理dante改装过来的,具体部署方式如下(prefix可以改成自己想要的路径)。
cd path/to/socket-proxy-*
./configure--prefix=/usr/local/dante --enable-debug --enable-livedebug
make
makeinstall
之后自然也就是配置文件的事了。比如我的,本机的配置文件如下
#logging
logoutput:/usr/local/dante/log/sockd.log
debug:1
#serveraddress specification
internal: 192.168.1.3 port=33555 #(其实我本机不是这个值)这个地方填的是对内的ip与端口,即浏览器会向这里发数据
external:wlan0
#serveridentities (not needed on solaris)
#user.privileged:root
user.notprivileged:socks
#user.libwrap:libwrap
#reversedns lookup
#srchost:nodnsmismatch
#authenticationmethods
clientmethod:none
socksmethod:none
##
##SOCKS client access rules
##
#ruleprocessing stops at the first match, no match results in blocking
#blockaccess to socks server from 192.0.2.22 (exception for pass rulebelow)
#client block {
# #block connections from 192.0.2.22/32
# from: 192.0.2.22/24 to: 0.0.0.0/0
# log: error # connect disconnect
#}
#allowconnections from local network (192.0.2.0/24)
clientpass {
from:192.168.1.0/24 to: 0.0.0.0/0
log:error # connect disconnect
}
#blockcommunication with www.example.org
#block {
# from: 0.0.0.0/0 to: www.example.org
# command: bind connect udpassociate
# log: error # connect disconnect iooperation
#}
#genericpass statement - bind/outgoing traffic
sockspass {
from:0.0.0.0/0 to: 0.0.0.0/0
command:connect #bind connect udpassociate
log:error # connect disconnect iooperation
}
#blockincoming connections/packets from ftp.example.org
#block {
# from: 0.0.0.0/0 to: ftp.example.org
# command: bindreply udpreply
# log: error # connect disconnect iooperation
#}
#genericpass statement for incoming connections/packets
#sockspass {
# from: 0.0.0.0/0 to: 0.0.0.0/0
# command: bindreply udpreply
# log: error # connect disconnect iooperation
#}
#forwardingroute to SOCKS server (which supports both SOCKS version 4 and 5)
route{
from:0.0.0.0/0 to: 0.0.0.0/0 via: 220.220.200.200 port = 3333
#via后接的ip就是你远程服务器的外网ip,port就是远程服务器开启的监听端口
proxyprotocol:socks_v4 socks_v5
command:connect
protocol:tcp #udp not supported
method:none
}
而我服务器上的配置是这样的
#logging
logoutput:/usr/local/dante/log/sockd.log
debug:1
#serveraddress specification
internal:220.220.200.200 port=4442
#这个internal填的就是外网ip和自己的监听端口
external:eth0
#serveridentities (not needed on solaris)
#user.privileged:root
user.notprivileged:socks
#user.libwrap:libwrap
#reversedns lookup
#srchost:nodnsmismatch
#authenticationmethods
clientmethod:none
socksmethod:none
##
##SOCKS client access rules
##
#ruleprocessing stops at the first match, no match results in blocking
#blockaccess to socks server from 192.0.2.22 (exception for pass rulebelow)
#client block {
# #block connections from 192.0.2.22/32
# from: 192.0.2.22/24 to: 0.0.0.0/0
# log: error # connect disconnect
#}
#allowconnections from local network (192.0.2.0/24)
clientpass {
from:0.0.0.0/0 to: 0.0.0.0/0
log:error # connect disconnect
}
sockspass {
from:0.0.0.0/0 to: 0.0.0.0/0
command:bind connect udpassociate
log:error # connect disconnect iooperation
}
而之后,客户端和服务器都可以这么启动
path/to/dante-D -f path/to/configfile
当然了,有个事情不要忘了,将浏览器的代理改为本地socket的地址与端口。
这样子之后,上各种被墙的网站都无压力了,就连去某网站上看视频都ok了。
那个,你是不是没有vps?其实,如果你知道我vps配置的ip与端口的话,可以直接用我的,当然,我这上面写的不是我实际用的。
等等,我好像忘记了更重要的,这个对你没用。你用的不是linux系统,是windows系统?那你还是h程序员吗???不用go-agent都不是程序员了,不用linux还能是程序员?能是程序员???
(对了,2048这个游戏我到现在还没玩过,也不打算玩,可以的么?)
(虽然可能被嘲讽为不是程序员,因为我不知道是不是这个别人早就用了更好的方法了。还有那些肉身就已经翻(什么)墙的人也会嘲讽吧。我还是把github链接共享下,大家如果是用linux系统的话,可以试试,没有vps的可以找我要我的ip与端口,mailto 785562819 [at] qq.com)
https://github.com/jiyanmoyu/proxy_for_gfw
有疑问加站长微信联系(非本文作者)