ssh端口转发

为什么写这篇文章

一般公司会把服务器放在内网中, 比如数据库只能通过跳板机来访问, 这就导致一些很好用的工具, 比如navicat,studio 3T, adminMongo这样的图形界面工具与生产数据库无缘了, 程序员只能带着命令行里玩泥巴. 好一点的给你的TUI(终端图形界面), 或者有个自动提示, 比如mycli, postcli依靠可怜的tab提示自娱自乐.对于效率来说, 阿章觉得这还是在玩泥巴.

然后呢? 公司会给你个VPN, 在公司可以拨通VPN然后再被限定了端口范围里面, 可以直接本机连. 在家还要拨通VPN去连公司的数据库, 阿章觉得这样不好玩.

下面的部分参考了阮一峰的博客 SSH原理与运用(二):远程操作与端口转发, 但是做了修改.大神的介绍深入浅出, 而且结构合理. 但是有一些地方不清晰, 如host1 host2 host3这样的名字, 很容易绕晕. 在此略作修改.如果不想看这些知识介绍, 可以直接跳到最后, 告诉你如何应用.

知识介绍

ssh参数介绍

    -C  压缩数据传输
    -f  后台运行
    -N  只连接远程主机,不打开shell
    -g  允许打开的端口让远程主机访问        
    -L  本地端口转发
    -R  远程端口转发
    -p  ssh 端口

开tunnels的2大作用

1.加密SSH client 与 SSH server 传输的数据
2.突破防火墙限制

绑定本地端口

既然SSH可以传送数据,那么我们可以让那些不加密的网络连接,全部改走SSH连接,从而提高安全性。 假定我们要让8080端口的数据,都通过SSH传向远程主机,命令就这样写:

$ ssh -D 8080 user@host

SSH会建立一个socket,去监听本地的8080端口。一旦有数据传向那个端口,就自动把它转移到SSH连接上面,发往远程主机。可以想象,如果8080端口原来是一个不加密端口,现在将变成一个加密端口。

本地端口转发

名词解释

以下部分local_host指本机, local_port指本机端口, jump_host指跳板机ip, jump_ssh_port指跳板机ssh端口, db_host指公司数据库服务器(在内网, 只能通过内网访问)ip, db_port指公司数据库服务器上要连接的端口.

详解

有时,绑定本地端口还不够,还必须指定数据传送的目标主机,从而形成点对点的”端口转发”。为了区别后文的”远程端口转发”,我们把这种情况称为”本地端口转发”(Local forwarding)。 假定local_host是本地主机,db_host是远程主机。由于种种原因,这两台主机之间无法连通。但是,另外还有一台jump_host,可以同时连通前面两台主机。因此,很自然的想法就是,通过jump_host,将local_host连上db_host。 我们在local_host执行下面的命令:

$ ssh -L local_port:db_host:db_port jump_host [-p jump_ssh_port]

命令中的-L参数一共接受4个值,分别是”本地端口:目标主机:目标主机端口 跳板主机”,它们之间用冒号分隔。这条命令的意思,就是指定SSH绑定本地端口local_port,然后指定jump_host将所有的数据,转发到目标主机db_hostdb_port端口(假定db_host运行mongodb,默认端口为27017)。 这样一来,我们只要连接local_host2121端口,就等于连上了db_hostdb_port端口。

$ mongo localhost:27017

“本地端口转发”使得local_hostdb_host之间仿佛形成一个数据传输的秘密隧道,因此又被称为”SSH隧道”。

远程端口转发

名词解释

以下部分local_host指本机, local_port指本机端口, jump_host指跳板机ip, jump_port指跳板机端口, db_host指公司数据库服务器(在内网, 只能通过内网访问)ip, db_port指公司数据库服务器上要连接的端口.my_cloud_host指自己买的云服务器(或者自己的电脑通过蒲公英等手段有外网ip也可以) my_cloud_port指自己的云服务器上面的端口.

详情

既然”本地端口转发”是指绑定本地端口的转发,那么”远程端口转发”(remote forwarding)当然是指绑定远程端口的转发。 还是接着看上面那个例子,local_hostdb_host之间无法连通,必须借助jump_host转发。但是,特殊情况出现了,db_host是一台内网机器,它可以连接外网的my_cloud_host,但是反过来就不行,外网的my_cloud_host连不上内网的db_host。这时,”本地端口转发”就不能用了,怎么办? 解决办法是,既然db_host可以连my_cloud_host,那么就从db_host上建立与my_cloud_host的SSH连接,然后在my_cloud_host上使用这条连接就可以了。 我们在jump_host执行下面的命令:

$ ssh -R my_cloud_port:db_host:db_port my_cloud_host

R参数也是接受4个值,分别是”远程主机端口:目标主机:目标主机端口 远程主机”。这条命令的意思,就是让my_cloud_host监听它自己的my_cloud_port端口,然后将所有数据经由自己jump_host,转发到db_hostdb_port端口。由于对于jump_host来说,my_cloud_host是远程主机,所以这种情况就被称为”远程端口绑定”。 绑定之后,我们在my_cloud_host就可以连接db_host了:

$ mongo localhost:27017

这里必须指出,”远程端口转发”的前提条件是,db_hostmy_cloud_host两台主机都有sshDssh客户端。

SSH的其他参数

SSH还有一些别的参数,也值得介绍。 N参数,表示只连接远程主机,不打开远程shell;T参数,表示不为这个连接分配TTY。这个两个参数可以放在一起用,代表这个SSH连接只用来传数据,不执行远程操作。

$ ssh -NT -D 8080 host

f参数,表示SSH连接成功后,转入后台运行。这样一来,你就可以在不中断SSH连接的情况下,在本地shell中执行其他操作。

$ ssh -f -D 8080 host

应用

在公司如何让本机直接访问原本只能通过跳板机才能访问的远程服务器上的数据库

在本机上执行

# 一定要注意参数顺序 -L要放在最后面
ssh -NfL local_port:db_host:db_port jump_host [-p jump_ssh_port]

解释:

-L表示本地端口转发

-N表示只连接远程主机不打开远程shell

-f表示转入后台

-p是本地连接跳板机时用的端口号, 如果是22可以不加

后面是 本地端口:数据库服务器ip:数据库端口 跳板机ip -p 跳板机ssh使用的端口号

在家如何在自己云主机上不用vpn直接访问公司内网服务器上的数据库

在跳板机上执行

 # 一定要注意参数顺序 -R要放在最后面
 ssh -NfR my_cloud_port:db_host:db_port my_cloud_host

解释:

-R表示远程端口转发

-N表示只连接远程主机不打开远程shell

-f表示转入后台

-p是本地连接跳板机时用的端口号, 如果是22可以不加

后面是我的云主机端口:数据库服务器ip:数据库服务器端口 我的云主机ip