本地端口转发
最近由于疫情影响,厂里让大家先在家远程上班,大量的同学蜂拥上VPN,VPN的连接数经常不够用。于是厂里的IT给我们搭了个Linux机器,开启了SSH服务并映射到厂里的公网ip端口上(ip : a.b.c.d,端口:xyz),同时限制了只能通过密钥方式登录,我们可以愉快地通过这个跳板机登录到厂内环境进行搬砖。
运维的同学需要通过本地数据库客户端连接到厂里的数据库上做操作,这时候,SSH的本地端口转发功能就能派上用场了。所谓的本地端口映射,就是在本地打开一个监听端口,通过已经建立的SSH加密隧道,将这个端口映射到SSH服务端所在网络的某个端口上。任何发送到本地这个监听端口的数据,都能透明地传输到远端端口上。远端的端口可以在SSH所在的主机上,也可以是SSH主机所能达到的其他地址上的端口。比如本例中,运维同学可以将本地的31521端口映射到厂里数据库主机的1521端口,数据库主机和SSH主机是两个独立的机器,他们处于同一个局域网内。
具体的端口映射指令如下:
ssh username@a.b.c.d -p xyz -L 31521:db_ip:1521
username是SSH服务端登录用户名,a.b.c.d是SSH服务端公网ip, xyz是SSH服务端端口,如果是22可以忽略。db_ip为厂里数据库主机ip。
以上指令设置的端口转发只能监听在本地环回地址(127.0.0.1)上的31521端口,对于使用Mac OS或者Linux桌面的同学,影响不大,在本机跑这个指令就行。对于windows用户,我们一般都是通过ssh客户端登录到SSH服务器的,一般常用的ssh客户端有:SecureCRT,putty或者MobaXterm等,这些客户端都带有tunnel功能。以putty为例,打开一个putty进程,输入SSH服务端的ip:
展开SSH,选择Tunnels:
在这里【Source Port】可以输入31521,【Destination】可以输入db_ip:1521。单选框选Local,并点击【Add】按钮,然后单击【Open】进行连接,登录上SSH服务端之后就可以通过本地的31521端口访问远端的数据库了。
对于SercureCRT,首先新建一个连接到SSH服务端的会话,再点击会话选项:
在会话选项中选择端口转发
并点击【Add】按钮添加端口映射规则
MobaXterm内置了Cygwin,可以直接在MobaXterm的本地会话中执行ssh语句进行端口转发配置,体验效果等同于Linux或者Mac OS。MobaXterm还提供了图形化的界面,可以形象地指导用户进行端口转发的配置:
点击上图中的Tunneling:
点击【New SSH tunnel】按钮:
如果在本地有个Linux虚拟机,想通过虚拟机的端口作为跳板连接到远端数据库端口,可以通过指定虚拟机的监听ip为0.0.0.0。这样就可以使得和虚拟机在同一个局域网的机器都能访问到远端数据库。具体指令如下:
ssh username@a.b.c.d -p xyz -L 0.0.0.0:31521:db_ip:1521
上述指令执行时,会在终端上开启一个远程SSH会话,我们在做端口转发时并不希望登录到远端SSH服务端做操作,这时,我们可以考虑加个参数N,指出本指令不需要发送交互命令到远程SSH服务端机器,同时可以加f参数指令令转入后台执行。
ssh username@a.b.c.d -Nf -p xyz -L 0.0.0.0:31521:db_ip:1521
ssh指令在后台执行后,一段时间没有交互命令传给SSH服务端,会导致指令退出。我们可以配置ssh的参数,间歇性发送心跳指令给服务端。可以通过-o参数指定ServerAliveInterval值,也可以在~/.ssh/config这个配置文件中指定。比如本例,可以在config文件增加如下配置
host jumpserver
Hostname a.b.c.d
Port xyz
User username
ServerAliveInterval 30
然后可以用如下指令进行端口映射:
ssh jumpserver -Nf -L 0.0.0.0:31521:db_ip:1521
即便是加上了心跳,也可能面临由于网络断链导致ssh进程退出的情形。如果需要后台自动维护端口转发,可以安装autossh,通过autossh守护ssh进程:
autossh -M 2020 jumpserver -Nf -L 0.0.0.0:31521:db_ip:1521
远程端口转发
厂里对VPN做了扩容,大家都能顺利地通过VPN访问内网环境,开发同学这时又遇到问题了。他在家里搭建的开发环境需要对接到厂里的Nginx,通过Nginx反向代理提供对开发环境的联调访问。但是,不巧的是,IT同事配置的VPN给大家分配的并不是内网ip,而是一个NAT地址,这个地址可以顺畅地访问厂里的内网环境,却没法从厂里访问到这个NAT地址。这时候,远程端口转发就派上用场了。
开发同学可以在本地执行如下指令:
ssh username@a.b.c.d -p xyz -R 8888:local_ip:8080
这个指令可以将本地环境local_ip的8080端口映射到SSH服务端的8888端口上。Nginx上只要配置SSH服务端8888端口对应的url就可以实现联调了。
远程端口映射同样在putty、SecureCRT和MobaXterm等各种客户端以及autossh中都可以进行配置,此处就不一一赘述。
在办公室环境中,有时我们会通过一个带NAT功能的(Wifi)路由器连接到内网,这种情形下同样可以用远程端口转发将NAT下的设备暴露到办公网里。
动态端口转发
动态端口转发实现了一种socks代理功能,用户可以通过如下指定实现一个动态端口转发:
ssh username@a.b.c.d -p xyz -D 1080
执行上述指令后,本机会启动1080端口监听,这时,只要将浏览器的socks5代理指向本机的1080端口,就可以在浏览器里访问内网任意服务器的网页。
动态端口通常用于跳板机环境下的网页访问。