科学上网之 SSH 隧道

SSH 隧道介绍

摘自IBM developerWorks 中国

我们知道,SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH 还同时提供了一个非常有用的功能,这就是端口转发。它能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务。这一过程有时也被叫做“隧道”(tunneling),这是因为 SSH 为其他 TCP 链接提供了一个安全的通道来进行传输而得名。例如,Telnet,SMTP,LDAP 这些 TCP 应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传输。而与此同时,如果您工作环境中的防火墙限制了一些网络端口的使用,但是允许 SSH 的连接,那么也是能够通过将 TCP 端口转发来使用 SSH 进行通讯。总的来说 SSH 端口转发能够提供两大功能:

  1. 加密 SSH Client 端至 SSH Server 端之间的通讯数据。
  2. 突破防火墙的限制完成一些之前无法建立的 TCP 连接。

原理图如下:
SSH 端口转发

服务器配置(可选)

创建专用用户组

1
root@vps:~# groupadd gfw

创建专用用户名,该用户属于gfw组,只能使用 SSH 代理,不能登录 Shell

1
2
3
4
root@vps:~# useradd -d /home/gfw -m -g gfw -s /bin/false gfw
root@vps:~# useradd -d /home/test -m -g gfw -s /bin/false test
root@vps:~# passwd gfw
root@vps:~# passwd test

客户端 SSH 隧道配置(Mac OS X/Linux)

隧道配置

最简单的

1
2
3
4
5
huzhifeng@Ubuntu16041:~$ ssh -N -D 7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ netstat -nlp | grep 7070
tcp 0 0 127.0.0.1:7070 0.0.0.0:* LISTEN 25936/ssh
tcp6 0 0 ::1:7070 :::* LISTEN 25936/ssh
huzhifeng@Ubuntu16041:~$

仅限于本机

1
2
3
4
huzhifeng@Ubuntu16041:~$ ssh -N -D 127.0.0.1:7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ netstat -nlp | grep 7070
tcp 0 0 127.0.0.1:7070 0.0.0.0:* LISTEN 25954/ssh
huzhifeng@Ubuntu16041:~$

共享给局域网(可能还需要配置防火墙规则)

1
2
3
4
5
6
7
8
huzhifeng@Ubuntu16041:~$ ssh -N -D 0.0.0.0:7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ netstat -nlp | grep 7070
tcp 0 0 0.0.0.0:7070 0.0.0.0:* LISTEN 25996/ssh
huzhifeng@Ubuntu16041:~$ ssh -N -D "*:7070" gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ netstat -nlp | grep 7070
tcp 0 0 0.0.0.0:7070 0.0.0.0:* LISTEN 26017/ssh
tcp6 0 0 :::7070 :::* LISTEN 26017/ssh
huzhifeng@Ubuntu16041:~$

高级参数

1
2
3
4
5
6
7
-D Tells SSH that we want a SOCKS tunnel on the specified port number (you can choose a number between 1025-65536) 隧道端口
-C Requests gzip compression of all data 压缩传输内容
-T Disable pseudo-tty allocation 不要分配 tty
-N Do not execute a remote command. This is useful for just forwarding ports. 不执行远程命令
-f Requests ssh to go to background just before command execution. 后台运行
-n Redirects stdin from /dev/null (actually, prevents reading from stdin). 标准输出重定向到/dev/null
-q Quiet mode. Causes most warning and diagnostic messages to be suppressed. 安静模式

例如:

1
2
3
4
huzhifeng@Ubuntu16041:~$ ssh -qTCnfND 7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ ps axu | grep 7070
huzhife+ 26079 0.0 0.0 49352 2548 ? Ss 22:21 0:00 ssh -qTCnfND 7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ kill 26079

检查

1
2
3
huzhifeng@Ubuntu16041:~$ ps axu | grep 7070
huzhife+ 24480 0.0 0.0 49052 5680 pts/2 S+ 21:39 0:00 ssh -N -D 7070 gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$

测试

1
2
huzhifeng@Ubuntu16041:~$ curl --proxy socks5://127.0.0.1:7070 google.com
huzhifeng@Ubuntu16041:~$ curl --socks5 127.0.0.1:7070 google.com

关闭

1
2
huzhifeng@Ubuntu16041:~$ ps axu | grep ssh
huzhifeng@Ubuntu16041:~$ kill 26079

SSH 免密登录

先要修改服务器,允许 Shell 登录

1
2
3
4
root@vps:~# grep -E "(gfw|test)" /etc/passwd
gfw:x:1000:1000::/home/gfw:/bin/bash
test:x:1001:1000::/home/test:/bin/bash
root@vps:~#

然后客户端执行ssh-copy-id

1
2
huzhifeng@Ubuntu16041:~$ ssh-copy-id gfw@huzhifeng.com
huzhifeng@Ubuntu16041:~$ ssh-copy-id test@huzhifeng.com

最后服务端再禁止 Shell 登录

1
2
3
4
root@vps:~# grep -E "(gfw|test)" /etc/passwd
gfw:x:1000:1000::/home/gfw:/bin/false
test:x:1001:1000::/home/test:/bin/false
root@vps:~#

后台服务(TODO)

开机自启(TODO)

客户端 SSH 隧道配置(Windows)

下载 PuTTY

PAC/FoxyProxy/SwitchyOmega(TODO)

参考

SSH隧道翻墙的原理和实现
Proxy Using SSH Tunnel
如何把 VPS 作为 SSH 代理翻墙
How To Route Web Traffic Securely Without a VPN Using a SOCKS Tunnel
实战 SSH 端口转发

EOF

如果本文对您有所帮助,请随意打赏,您的支持将鼓励我继续创作!