8
回答
关键字:国外镜像服务器,Nginx,Proxy,G姓防火墙,SSH,压缩,加密传输,专用隧道。
开发十年,就只剩下这套Java开发体系了   

想了好久,这个标题应该怎样写。
就如同我想了很久这需求应该怎样配。

我所建立以摄影图片为主的论坛,有一大部分朋友远在国外。
他们在各地的校园或市镇里头上网所连接位于国内的服务器稳定与速度不尽人意。
而且那时候同时也经历了 .cn 以及所谓的国内不允许个人开设论坛,要统一关停等风波。
因此在上年,我在美国租用了一台 VPS 充当基于 Nginx,Proxy,Squid 作为国内服务器的proxy作临时转发。论坛的域名也因此指出到国外。

因为美国 VPS 的性能,空间有限。所以是直接把域名指向国外VPS的IP后,再由 Nginx Proxy 把请求转发回国内的服务器主机。
整个过程走的都是 http 协议,而且是明文传输。
并且都启用了 Gzip 压缩。

从性能上观察,对于国内的访问,跑出去兜了个圈再回来,慢是正常的。
但过国外的朋友反映,虽然 Squid 让加载图片的速度比直接访问国内服务器要快。
但基于动态请求的页面响应改善也不明显。
经过对宽带进行测试,两台服务器双方请求文件包的下载至少也有400k/s 的速度。
因此延时可以排除是因宽带不足所导致。
但也可测试校验的条件不多,当时也是临时规划,因而慢就慢吧,先等风头过去再说。

不过,后来在我 “翻” 出外网的时候留意到一个点。
在国内被封的国外网站,例如 facebook。封的不止是对方的IP以及DNS禁止解析。
而是彻底的从http数据中过滤屏蔽 www.facebook.com 的域名。
因此即使使用在线代理,也无法进行访问,非得是专用的 “翻” 软件。或者 SSH

经查阅相关的文章,原来 “G姓防火墙” 会对所有进出国内外互联网的数据作处理。
特别针对 80端口,明文 http 协议传输的内容。
就是说,这两地的连通早就已经并非单纯的线路来往了。

明文的 HTTP 数据经过了 “G姓防火墙” 的处理。
即使没对内容作出过滤,也应该会对速度造成了影响。
这很可能就是之前提到性能低下的原因。
为了证实这一点,我将需要找一种 “隧道” 来重新运载 HTTP 避免其明文传递。
再而比较两个性能的差距。

较为便捷可考虑的方式两个:
1,VPN
2,SSH

VPN 的配置比较复杂。需要额外安装多个组件。
而 SSH 确几乎就是现成,

因此挑选 SSH 上任!
我们需要用此建立一条为两台服务器之间的专用加密压缩隧道,从国外的VPS连接到国内主机。以保证脆弱的明文 HTTP 协议在 Proxy 过程中免受窃听以及内容的篡改。

开始前,我们需要对SSH服务进行适当的调整。

1,设置ssh超时时间,让SSH客户端长久保持在线。

/etc/ssh/sshd_config中配置
ClientAliveInterval=60

表示如果没任何操作,也每隔60秒向后端发起一下请求,判断其是否在线。

2,关闭SSH的DNS反向查询,已提高连接效率

/etc/ssh/sshd_config中配置
UseDNS no

3,启动压缩已减少宽带消耗

/etc/ssh/sshd_config中配置
Compression yes


然后到配置客户端,即国外VPS服务器的配置。

SSH 建立隧道连接,命令格式如下:
ssh -2 -N -f -L 本地端口:127.0.0.1:服务端端口 user@ip

相关参数的解释:

-2
使用 SSH 2.0 协议

-f Fork into background after authentication.
后台认证用户/密码,通常和-N连用,不用登录到远程主机。

-L port:host:hostport
将 本地机(客户机)的某个端口转发到远端指定机器的指定端口. 

-C Enable compression.
压缩数据传输。

-N Do not execute a shell or command.
不执行脚本或命令,通常与-f连用。

user
远程服务器的SSH登陆账号

ip
远程服务器的IP

该命令连接后能把远程服务器中的指定服务端口,映射到本地的指定端口。
例如把远端服务器80端口,映射到本地的80端口。
这么本地访问 http://127.0.0.1:80 打开的内容就是远端的http内容
这个命令以端口为基准,所以也能封装一切协议,包括 SMTP,POP,Mysql,Rsync 等等...

而且隧道链接一旦建立,对于远程服务器来说,访问来自的映射是来自 127.0.0.1 的本地。
所以即使远端防火墙关闭了 80 端口的对外访问,本地服务器通过 SSH 也将能访问到80端口的内容。真正是直通核心的隧道。

但以上这条命令仅能用于手工执行,因为执行之后需要人手输入密码才能进行链接。

然而开机能自动启动,或者断线重拨,我们需要写个脚本。

vim /run/ssh_go.sh

#! /usr/bin/expect

set ip "远程服务器IP"

set username "远程服务器用户名"

set passwd "远程服务器密码"

spawn ssh -2 -C -N -f -L 本地端口:127.0.0.1:远端端口 $username@$ip

expect {
                  "yes/no" {send "yes\r";exp_continue}

                  "password:" {send "$passwd\r";exp_continue}
}

expect eof

以上这脚本,可能需要增加 expect 组件。

也相当简单,相关方法在本文就不详述了。 按照实际需求进行修改。

然后,我们需要再写一个脚本,用于判断连接是否被断开。

以上脚本是否在还后台运行,如果没有,则再次执行。

vim /run/run_ck.sh

#! /usr/bin/perl
$ck=`ps -ef | grep '远程主机IP' | grep -v grep`;
        if ($ck eq ''){
        print "SSH_go Down, Start up now\n";
        `/run/ssh_go.sh`;

        }else{
        print "SSH_go Running\n";
        }

以上是一个 Perl 脚本,原理是用于是被系统进程中,
有否还存在包含远程主机 IP 的SSH进程 如果没有,
则报告
SSH_go Down, Start up now 并且执行 /run/ssh_go.sh
如果有,则报告 SSH_go Running 然后不做任何动作。

完成后把 /run/run_ck.sh 加入到 crontab 中,设置每分钟运行。如果遇到短线或者意外退出,都能自动运行脚本重链。

SSH 隧道建立后!

例如把远程服务器的80端口,映射到本地的8080.。这么只要在 Nginx 的 Proxy 映射地址设置到 127.0.0.1:8080

远端的 HTTP 数据就能通过 SSH 加密压缩隧道进行 Proxy 到 Nginx

实际测试,使用这这种方式穿越 “G姓防火墙” 性能提高明显!!!!
现在即使是国内用户访问,速度也能比上普通国内二三线机房。
即使理论上 SSH 默认的加密解密算法是需要消耗一定的资源以及时间。但实际也要比 “G姓防火墙” 的影响要少得多。 曾试过用 Apache AB 进行并发压力测试,性能损耗也没太大的影响。

而且,非只是加密,就其压缩节省宽带的效果也是立竿见影。如下图:

现在这套系统已经给我用于实测数天,暂时没发现不稳定情况。 因而放心分享给大家。

举报
范堡
发帖于7年前 8回/2K+阅
顶部