SSH 反向隧道(Reverse SSH Tunneling)是一种在防火墙或 NAT(网络地址转换)限制下实现远程访问的技术。通过建立反向隧道,可以让外部计算机访问位于私有网络中的计算机,而无需在防火墙上打开端口,从而实现内网穿透。这也是最简单的一种内网穿透方式。

内网穿透
家里有一台新配的服务器A,但是这台服务器连接的wifi位于内网中,没有独立的公网IP地址,这样不在这个内网内的计算机和手机不能直接访问这台服务器。当我不在家的时候又想登录这台服务器就需要用到内网穿透。
| 网络设备 | IP | 用户名 | 描述 |
|---|---|---|---|
| A | 192.168.2.105 | bigk | 位于内网的目标服务器(如家里的服务器),linux系统 |
| B | 43.156.188.229 | root | 公网服务器,有独立公网IP,用来转发连接,如腾讯云和阿里云的云服务器,linux系统 |
| C | x.x.x.x | x | 任意可以访问公网的网络设备,位于内网,比如个人的mac |
其中'192.168.2.105'和'43.156.188.229'均为杜撰
默认情况下,这三个网络设备的互通关系如图所示,位于内网的设备A和设备C可以访问公网设备B,但是位于不同内网的设备间不能访问,即设备C默认访问不了目标服务器A。

由于服务器A可以访问服务器B,可以利用ssh反向隧道技术,让服务器A交出控制权给服务器B,然后设备C即可通过操纵服务器B来操纵服务器A,原理如图所示。

实现
建立ssh反向隧道
在服务器A的终端上运行
1 | ssh -lroot -p22 -qngfNTR 8822:localhost:22 43.156.188.229 -o ServerAliveInterval=10 |
此时,需要输入root@43.156.188.229的密码。该命令可以实现将服务器B的8822端口(这个端口可以任意设置)映射到服务器A的22端口(ssh默认端口),这样其他人访问服务器B的8822端口就相当于访问服务器A的22端口,具体参数含义为
1 | -lroot:指定登录远程服务器的用户名为root。 |
远程连接内网服务器
在设备C上运行
1 | ssh -p 8822 bigk@43.156.188.229 |
输入服务器A的密码,即可连接上服务器A
配置免密登录
在上述过程中存在两次输入密码登录的过程,十分麻烦也不安全,更方便的方式是通过配置ssh密钥登录,配置方式查看往期博客"ssh 免密登录远程服务器"。
首先,假如本地没有现成的公钥和私钥,需要先在本地生成:
1 | ssh-keygen -t rsa |
这将在~/.ssh文件夹下产生私钥id_rsa和公钥id_rsa.pub,持有私钥的电脑可以免密登录登记对应私钥的电脑,所以我们要把公钥传送到目标服务器
1 | ssh-copy-id [-p port] username@remote-server-ip |
具体而言,我们需要在设备C上产生的公钥分别登记到服务器B和服务器A上:
1 | ssh-copy-id -p 22 43.156.188.229 #传到服务器B |
接下来,我们需要配置~/.ssh/config来指定用私钥来免密登录持有对应公钥的远程服务器。
1 | Host TencentCloud |
配置完成后,就可以用远程服务器的别名来很方便的免密登录远程服务器了!
1 | ssh TencentCloud #免密登录远程服务器B |