下午闲了一会儿,想起前年实习搬服务器的时候,当时公司的服务器,被我们安装到某个地方的内网之后,没有外网IP只是通过NAT访问外网,但是公司服务器可以直接主动登陆上去操作,当时我还以为是端口转发,或者VPN,两个月之后运维主管离职,从某团空降来一个运维领导,试了一下iptables的端口转发。。。然后采用了VPN,无疑我感觉这很low逼。所以这项神秘的技术一直被我记到现在。。
下边先介绍下ssh的端口转发
SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH 还同时提供了一个非常有用的功能,这就是端口转发。它能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务。这一过程有时也被叫做“隧道”(tunneling),这是因为 SSH 为其他 TCP 链接提供了一个安全的通道来进行传输而得名。例如,Telnet,SMTP,LDAP 这些 TCP 应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传输。而与此同时,如果您工作环境中的防火墙限制了一些网络端口的使用,但是允许 SSH 的连接,那么也是能够通过将 TCP 端口转发来使用 SSH 进行通讯。总的来说 SSH 端口转发能够提供两大功能:
加密 SSH Client 端至 SSH Server 端之间的通讯数据。
突破防火墙的限制完成一些之前无法建立的 TCP 连接。
本地端口转发
格式 ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
例如 我们将本地8000端口转发到提供LDAP
服务的主机Ldapserver_host1 的389端口(ldap_server默认端口)可以这样写
ssh -L 7001:localhost:389 LdapServer_host1
这个时候netstat -tpln
看
tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN 15889/ldap
本地端口已经起来了 ,但是只允许在本机访问,这个时候区别的机器用 nmap
扫描是看不到7001
端口的
但是怎么让别的主机也可以使用呢?
SH 同时提供了 GatewayPorts 关键字,我们可以通过指定它与其他机器共享这个本地端口转发。
ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname>
这个时候可以使用ssh 提供的Gateway Port
关键字-g
ssh -g -L 8001:0.0.0.0:22 localhost
我们把这台主机的22端口转发到本机的8001端口
然后这时候我们可以到另一台机器上 nmap
发现本机 8001端口已经打开了 然后试下 ssh -p 8001 是可以登得上的。
远程端口转发
其实这就是所谓的ssh反向隧道
主机介绍:
主机名 | 是否有外网地址 | 地址 | 用户 |
---|---|---|---|
server1 | 是 | 123.21.201.189 | fanquqi |
server2 | 否 | localhost | fanquqi |
server3 | 否 | localhost | fanquqi |
主要参数
-R
反向代理-N
不执行远程指令-f
后台执行
命令格式
ssh -NfR 6789:localhost:22 fanquqi@123.21.201.189
在server2上执行上述命令,执行完输完密码之后,我们可以在server1上看下端口 正常6789端口已经是监听了的。
然后 我们可以在 这台外网地址机器上执行
ssh -p 6789 fanquqi@localhost
即可连接到连接到NAT后面的server2。。
可以看到上面列出了三台机器,第三台还没有用到。我们来用一下,试下让两台没有外网的机器建立连接。
先杀掉server1
上6789端口。
在server3
上执行
ssh -fN -R 123.21.201.189:6789:localhost:22 fanquqi@123.21.201.189
然后在server1
上确认6789打开
这时候在server2上就可以连接server3了
只需要运行
ssh -p 6789 fanquqi@123.21.201.189
即可。其实不止server1,是任何有网络的机器
其实我们还可以把公钥互相传一下 就不用来回输密码了。 如果nat后面那台主机不在手边,经常上不去 建议使用autossh
提供隧道断开自动重连功能。或者更改ssh配置文件~/.ssh/config
ServerAliveInterval
ServerAliveCountMax
更改如上两个参数
第一个参数表示如果服务器(外网)没数据发来则过一段时间客户端(内网)会发送一个空包到服务器,以保持tcp长连接,默认值为0,表示不会发心跳包,这里可以设置一分钟。。
第二个参数表示,如果服务器(内网)没有收到心跳包指定次数,就中断连接。可以设置为无限大。