rsync over ssh over socks

之所以要这么折腾,首先需要强烈谴责那些为某墙作出过贡献的程序员,解放后你们是一定会被清算的。

需求

这事的需求是这样的,我有几个国外的VPS用来跑自己和朋友的BLOG,为了保险起见,我搞了一套备份系统:

在家里的服务器上开了一个ZFS做远程VPS的备份,备份方法是每天晚上通过rsync over ssh进行同步,然后本地服务器生成快照做版本控制。

实现起来很简单,也可以满足需求:

如 果远端VPS数据丢失(故障,意外删除,被黑等),我都可以立即重新开一个VPS,再把本地备份的数据恢复回去。即使是远程数据被错误修改,我也可以 通过本地ZFS的快照克隆出之前几天的备份来恢复。总体上说还是相当靠谱的——虽然目前也只恢复过一次,去年有一次DO的母鸡出了故障,VPS恢复后无法 SSH接入,它们那个破CONSOLE在国内根本连不上,只好重装。

但是现在问题来了。

因为rsync走的是SSH通道,而SSH协议是被监视的,流量一大就会被封,我因为这个备份功能被封了好几次,真是TMD想砍人。反革命都是这样被逼出来的。

然而在解放前,只能自己想办法解决了……

现在就来说说新的方案吧。

方案选择

本来是想参照前文说的那个方案用GPG加密后通过HTTP明文传输——因为某墙不会直接封杀明文的HTTP,只是会对其中传输的内容进行审查,但是因为经过了GPG加密,它也审查不出啥来,只是速度会慢而已,但至少不会断。

但是问题来了:因为GPG解密过程必须要有私钥密码,这个又必须是人工输入,不能自动输入(可以用GPG-agent在内存中保存一段时间不用重输,类似sudo输入一次密码可以用一段时间一样),所以无法做成自动任务。

于是只能继续在rsync上作文章。最后想到一个办法:

ssh over socks

方法如下:

首先你需要一个叫nc(netcat)的工具,这个FreeBSD是自带的,Linux需要另外安装。nc的全名叫做netcat,正如其名,就是一个网络版的cat,在Linux上它甚至被称为TCP/IP的瑞士军刀。

之后就是在~/.ssh/下创建一个config文件,内容为:

Host your-prox
    Hostname yourserver.com
    ProxyCommand /usr/bin/nc -x localhost:1080 %h %p

其中 your-prox 这个名字可以自己随便取一个,yourserver.com是实际的远程服务器,localhost:1080是指运行于本地的 socks代理(如果是内网其它机器也可以,改成相应的内网地址和端口即可),注意,这个socks代理的出口必须在墙外(废话),而且是可以直接访问 yourserver.com的地方。

顺便说一句,在Linux下还可以用另一个简单的工具来代替nc,那就是connect-proxy,在这里的用法跟nc差不多,只是要把ProxyCommand改为:

/usr/bin/connect -S localhost:1080 %h %p

这个操作的作用就是创建一个虚拟的SSH服务器配置,之后就可以通过这样的方式走socks代理连接远程服务器yourserver.com:

ssh username@your-prox

就是简单地把yourserver.com换成your-prox即可。

然后rsync也一样:

rsync -az -e ssh username@your-prox:~/yourdir .

最后,在.ssh/config里可以配置多个Host针对不同的remote server,当然 *-prox 名字不能一样。

原理

为什么这样可以防止被封?

原来的rsync over ssh是这样的:

local rsync <=> SSH <=> (某墙) <=> remote server

但是现在变成了这样:

local rsync <=> SSH <=> local socks proxy <=> (某墙) <=> remote socks proxy <=> remote server

在socks proxy之间你可以用无数种方法去规避某墙的审查和封杀。

最后让我们一起来唾弃那些用民脂民膏建某墙坑害人民的猪狗不如的家伙们吧,诅咒它们终生丧失性能力。

推送到[go4pro.org]