SSH反向隧道的搭建与原理

SSH反向隧道的搭建与原理

九月 13, 2019
当前设备屏幕尺寸过小,推荐使用PC模式浏览。

基本概念

SSH反向隧道可以实现SSH的内网穿透,其作用原理是:

  • 内网机器BB监听公网服务器AA的端口PAP_A
  • 一旦公网机器AA收到来自端口PAP_A的请求,则转发/映射到内网机器BB的端口PBP_B(内网机器BB的ssh默认端口为22)

注意: 若要将内网机器的默认端口PBP_B修改为非22端口,请到/etc/ssh/sshd_config中更改。

设备概览

服务器代号 IP 对外暴露的SSH端口
A(公网) 114.114.114.114 2061
B(内网) 192.168.1.101 22
C(内网) 192.168.1.102 22
…(内网)

适用场景

假设我现在有N台内网机器,只有一台公网机器AA,现在我需要利用公网机器AA作为中转站,操作内网机器B,C,D,E,FB,C,D,E,F

搭建反向隧道

下面,我们对内网机器BB的SSH端口22进行穿透。所有操作默认采用root权限。

文章分为三个部分:

  1. 正向代理(公网机器操作)
  2. 反向代理(内网机器操作)
  3. 稳定机器及开机自动建立反向隧道(内网机器操作)

公网机器配置

正向代理

当你知道内网机器IP时,你可以如下配置:

1
ssh -fCNL <内网机器B的IP>:<内网机器B的端口,如22>:localhost:<公网机器A的端口,如2601> localhost

其中ssh指令的各参数意义为:

-f 后台执行ssh指令
-C 允许压缩数据
-N 不执行远程指令
-R 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口
-L 将本地机(客户机)的某个端口转发到远端指定机器的指定端口
-p 指定远程主机的端口

但是,如果内网服务器BB采用DHCP或者分布在两个内网中,很难锁定这个IP的值。

开放权限

这种情况下,我们可以修改公网机器AA的SSH配置文件/etc/ssh/sshd_config,添加/修改以下内容:

1
GatewayPorts yes

然后刷新一下服务:

1
service sshd restart

[推荐方法]或者,依旧采用ssh正向代理指令:(该方法需要设一下开机自启,详见下)

1
ssh -fCNL *:<内网机器B的端口,如22>:localhost:<公网机器A的端口,如2601> localhost

以上两种方法都可以把被监听的端口开放/绑定到任意IP0.0.0.0上。

内网机器配置

我们假设PAP_A2061,即访问公网机器端口2061时会自动转发到内网端口22实现ssh登录。

反向代理

注意,推荐利用autossh建立反向隧道,而不是ssh指令,详见下文。

1
ssh -fCNR 2061:localhost:22 <公网机器A的ssh登录用户名>@<公网机器A的IP>
  • <公网机器A的ssh登录用户名>: 指的是在公网机器AA上负责转发请求的用户,可以直接使用root,或者新建一个用户bridge。执行上述命令后会让你输入登录公网机器的ssh密码。

在公网机器A上执行指令:lsof -i:<公网机器A被监听的端口,如2061>,会看到:

result

此时,可以尝试进行反向登录了:

1
ssh <公网机器A的IP> -p <公网机器A的端口>

理论上将会顺利穿透到内网机器,否则请检查防火墙的设置。

  • 你可以在内网机器使用指令ps -aux | grep ssh来查看相关进程,用kill -p <PID>关闭相关反向隧道的进程。

稳定连接与开机自启

由于SSH在一段时间没有数据包之后,会自动断开,所以我们需要设置一下autossh

(以下操作均在内网机器B进行)

  1. 首先是进行下载:apt-get install autossh
  2. 然后添加我们内网机器的ssh-key到公网以实现自动登陆:ssh-copy-id <公网机器A的ssh登录用户名>@<公网机器A的IP>
  3. (Options)如果本机不存在key,你需要先执行ssh-keygen -t rsa -C "[email protected]"再进行第二步。
  4. 利用autossh建立反向隧道:
1
autossh -M 55555  -fCNR 2061:localhost:22 <公网机器A的ssh登录用户名>@<公网机器A的IP>

autossh和与ssh直接建立反向隧道的指令并无太大不同,只不过添加了一个端口用于进行心跳包的发送,即-M <port>(样例中为55555端口)

接下来,还需要设置开机自启:(/etc/rc.local文件根据系统版本有所不同,请自行搜索)

1
vim /etc/rc.local

添加上述autossh指令即可。