利用SSH反向隧道,连接内网服务器

时间:2024-01-16 17:46:38

前言

公司有一台文件服务器(内部使用,无外网IP),上面主要安装了SVN服务,用来存储和共享各部门的文档,因为都是内网,直接远程(mstsc)上去就可以方便维护,但最近公司租了新的办公室,部分员工被分配到这边办公,毫无疑问,无法远程和使用SVN了。

要解决有很多方法,比如路由器端口映射、VPN,我们只说一种最简单,也最奇妙的,SSH反向隧道

公司在云上有一台公网Linux服务器(假设是 52.199.166.132),我用它来端口转发

机器 IP地址 用户名 端口
A(内网) 10.3.174.94 administrator 3389(远程连接)
443(SVN)
B(公网) 52.199.166.132 root 23389(远程连接)
10443(SVN)

通俗的说我们要实现:

跳板机:远程桌面连接 52.199.166.132:23389 实际连的内网的 10.3.174.94:3389
服务转发:SVN连接 https://52.199.166.132:10443 实际连接的是内网的 https://10.3.174.94

开放端口

在B机器,执行以下命令,防火墙中开放端口10443和23389,并重启防火墙(B机器的系统是CentOS 7)

firewall-cmd --zone=public --add-port=23389/tcp --permanent
firewall-cmd --zone=public --add-port=10443/tcp --permanent
firewall-cmd --reload

打开 /etc/ssh/sshd_config,将GatewayPorts参数设为yes,然后重启sshd服务:

systemctl restart sshd.service

建立反向隧道

原理:内网的A通过SSH连接公网的B,并且两者建立一个通信隧道,通常防火墙只限制入站不限制出站,所以SSH可以穿透防火墙

1. 保证B服务器已安装和开启SSH(现在SSH是Linux标配)

2. 因为A是一台Windows,需要单独安装一个SSH客户端,比如 OpenSSH(Win10 已内置,可在 PowerShell 中使用)、Putty、SecureCRT 等,

我使用的Cygwin,这是一个Windows平台上运行的模拟UNIX环境,安装Cygwin时记得选择OpenSSH包 【Cygwin安装教程(图文)

如果用其它SSH客户端工具,注意 -i 后面的密钥路径格式

在终端中,执行两条命令:

ssh -i "/cygdrive/d/id_rsa/test_centos_secret_key.pem" -fNR :localhost: root@52.199.166.132 -p
ssh -i "/cygdrive/d/id_rsa/test_centos_secret_key.pem" -fNR :localhost: root@52.199.166.132 -p

执行成功,则SSH反向隧道建立

查看监听端口

登录机器B,通过 netstat 命令查看监听端口,有23389  10443端口

利用SSH反向隧道,连接内网服务器

然后在本地通过 telnet 查看23389和10443端口是否通

telnet 52.199.166.132
telnet 52.199.166.132

如果都通了,就大功告成了!

遇到的问题

1. 如果在A机器上执行SSH连接B失败,提示:Warning: remote port forwarding failed for listen port
或者B上面监听端口的IP地址不是0.0.0.0,而是127.0.0.1,可以在B上面把这两个端口对应的进程 kill 掉,然后A重新连接

2. SSH超时会断开(虽然我的一天都没断开过),不会重连,解决办法是用 autossh,那在安装 Cygwin 时一并安装 autossh 包,A上的命令这样写:

autossh -i "/cygdrive/d/id_rsa/test_centos_secret_key.pem" -M 7777 -NR :localhost: root@52.199.166.132 -p
autossh -i "/cygdrive/d/id_rsa/test_centos_secret_key.pem" -M 7777 -NR :localhost: root@52.199.166.132 -p

其中端口 7777 是负责监听连接状态,一旦连接不正常,通知A重连

参数说明

-p 22 远程主机SSH端口,默认是22,也可以省略
-i "*.pem" 基于密钥认证,如果基于口令认证,忽略
-f 表示后台执行,autossh 本来就在后台执行,所以不需要
-o ServerAliveInterval=180 保持连接Alive间隔180秒,可以调小
-N 表示不执行任何命令
-R 建立反向隧道
-L 建立正向代理
-M 监听隧道状态的端口,如果隧道不正常,告诉内网机器重连
-C 允许压缩数据