现在GFW不断加高,翻墙的服务搞不好什么时候就挂了,之前我在文章里介绍过比较稳定的方法是使用一台能够从ipv4到ipv6的跳板机。但跳板机挂了就糟糕了。这篇文章就是我昨天遇到这个问题时弄的一个临时性办法,可以在Shadowsocks流量被拦截,跳板机挂掉的情况下,使用SSH隧道连接翻墙服务器以使用Shadowsocks的服务。但是前提是你的服务器的 IP 没有被 Ban 掉

最近因为新冠肺炎疫情的关系,GFW对于翻墙流量的审查更加严格了,基于IPv4的直连方式访问Shadowsocks基本不可能了。但是GFW的拦截基本针对流量特征的,有些服务器的IP实际上并未处于黑名单中。因此我们使用别的方式还是能够连接到翻墙服务器的。例如SSH访问服务器就能成功。这时我们可以使用SSH开通一个从我们本地电脑的localhost到翻墙服务器的localhost的隧道,将我们本地的地址的端口映射到翻墙服务器的本地地址端口。这样我们通过本地地址端口访问远端的Shadowsocks的服务时,我们的客户端和服务器的通信流量就不再是Shadowsocks流量,而是SSH特征的流量,这样通信就可以绕过GFW的检查了。

2021年1月份我添加了一篇新的文章,提供了一个比 autossh 更加稳健的隧道部署方案:代替autossh的更加稳健的ssh隧道方案

1 SSH 隧道

完整的SSH隧道的教程网络上能搜到很多,比如这篇。我们只需要使用Local Forwarding模式。这个模式下,客户端的本地端口被映射到服务端的端口。命令的基本形式如下:

1
ssh -L local_addr:local_port:remote_addr:remote_port username@jump-server-addr

如果我们的翻墙服务器的地址是jump.server.com,用户名是ss,Shadowsocks服务的端口是11111则使用下面的命令:

1
ssh -L 8000:localhost:111111 ss@jump.server.com

我们就可以将我们本地的8000端口映射到Shadowsocks的服务端口上。在Shadowsocks设置中,原本的设置只需要将地址修改为localhost,端口修改8000,就可以访问远端的Shadowsocks服务了。

不过上面的命令会打开一个SSH会话,如果我们退出这个会话,会导致隧道中断。因此我们改进命令为

1
ssh -N -f -L 8000:localhost:111111 ss@jump.server.com

这个命令会在打开SSH隧道,将ssh进程转到后台运行。

2 autossh

不过ssh命令本身可能不太稳定,连接中断后ssh会退出。为了提升稳定性,我们需要能够监管ssh进程并在断线时自动重启ssh服务。autossh就是这样一款工具。目前autossh可以在Linux和macOS上运行,适用于Windows的工具我还没来得及找到。以macOS为例,可以使用Homebrew安装:

1
brew instal autossh

其使用方式非常简单,命令形式是

1
autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS]

其中-V是查看版本,不用管。-M是指定检测端口,实际上就是用来检测连接是否可用的。只是使用你不需要了解太多,随意指定一个本地高位端口(低位端口容易被占用)即可,例如20000(关于-M的地址的讨论参见这个链接)。-f会让程序在后台运行。而后跟上ssh的选项即可。注意因为autossh会管理ssh进程,我们不需要在后面在引入-f来告诉ssh进入后台运行。那么

1
ssh -N -f -L 8000:localhost:111111 ss@jump.server.com

这个命令用autossh改写为

1
autossh -M 20000 -f -N -L 8000:localhost:111111 ss@jump.server.com

即可。

3 Windows的支持

Windows上用的比较多的SSH客户端是PuTTY,不过PuTTY不能很好地满足ssh隧道的需求。这里我推荐的是Bitvise这个软件(点击链接可以前往下载页面)。这里给出Bitvise的配置方法。

首先下载Bitvise软件并完成安装。安装完成后打开,在Login界面,输入服务器的信息,包括Host,Port,以及用户名。这里Initial Method指的是认证手段,图中选择的是密码,通过下拉框也可以选择公钥验证或其他验证方法。

接下来前往Options页面,确保"Automatically reconnect if successful connection breaks"。这个功能比较关键,可以确保ssh连接中断时程序能够自动重新建立连接。另外要注意右侧的选项。由于我们只希望建立操作,而不需要登录到服务器进行其他操作,所以我们可以去掉Open Terminal和Open SFTP的选项。

最后前往C2S界面配置端口映射以建立SSH隧道:

需要解释的是:

  • Listen Interface 表示本地监听的接口。如果只是作为ssh客户端的电脑使用,那么填写localhost即可。如果希望把隧道同局域网内的其他设备共享,可以填写局域网地址或者0.0.0.0。
  • List. Port 为本地监听监听端口
  • Destination Host 这个概念要非常注意。很多新手可能会填写服务器的地址,如其公网IP。其实这是对SSH隧道缺乏了解导致的。这里的目的地址,是从服务器的视角来看的,我们要连接的是服务器本地的端口,所以这里填写localhost。
  • Dest. Port 为服务器端 Shadowsocks 服务的端口

上面的配置完成以后点击Log in即可建立连接。注意右上角有一个"Closing and minimization"的按钮,点开这个按钮可以选择点击右上角关闭按钮之后的程序行为,我们可以选择的"Hide to notification area if connected, exit otherwise",这样可以关闭窗口同时保证程序继续在后台运行。

4 稳定性讨论

用SSH隧道来实现翻墙,连接本身就是不太稳定的,在这个链接,答主提到使用-M选项来让autossh负责检查连接的可用性会比较不可靠,推荐使用ssh自己来负责监控连接。具体方式是设置-M 0,同时为ssh传递-o "ServerAliveInterval 30" -o "TCPKeepAlive yes"参数。完整的命令为

1
autossh -M 0 -f -N -f -L 8000:localhost:111111 ss@jump.server.com -o "ServerAliveInterval 30" -o "TCPKeepAlive yes"

-M 0时,autossh只会在ssh进程退出时重启进程,而不会检测联机本身的是否可用。关于ServerAliveInterval作用的细节,参见这篇文章

后面的实际使用中还是发现 -M 0 选项不够稳定,如果 ssh 链路中断,autossh 可能无法恢复连接。因此这里最好还是显式地指定一个端口,让 autossh 来监控链接的状况。不过要注意不同的用户需要使用不同的端口。

5 更多阅读