前几篇有关ssh的文章,咱们只是介绍了ssh的登陆功能。其实ssh功能不仅是这些,这篇文章咱们来介绍下有关ssh隧道的功能。 前端
ssh隧道也叫ssh端口转发,或者叫ssh tunnel,这些都是说的是ssh隧道功能。在此,咱们统称为ssh隧道。node
ssh隧道分为正向隧道和反向隧道,在实际工做中咱们能够根据须要来随其分别使用。mysql
下面开始对正向和反向隧道分别介绍下,因为使用平台的不一样,咱们分为Linux和windows平台。nginx
什么是ssh正向隧道?sql
就是client连上server后,而后把server能访问的IP地址和端口(固然也包括server本身)镜像到client的端口上。shell
在平时工做中,正向隧道是咱们使用最多的一种方式。数据库
ssh正向隧道的命令以下:windows
ssh –L clientC_IP:clientC_port:serverB_IP:serverB_port -p serverA_sshport username@serverA_IP后端
上述命令的意思是在客户端clientC上经过ssh链接服务器serverA,而后再把服务器serverB上的serverB_port端口映射到客户端clientC的clientC_port端口。安全
也就是说若是咱们如今链接clientC的clientC_port端口的话,就是链接服务器serverB上的serverB_port的端口。
上述命令的使用场景通常是,客户端clientC在公司内部使用的是内网IP,而服务器serverA和serverB在IDC机房或者在云服务器商那边。服务器serverA有公网IP能与客户端clientC正常通讯,而服务器serverB没有公网IP不能与客户端clientC直接通讯,可是服务器serverA和服务器serverB是经过内网进行通讯的。如今要求客户端clientC访问serverB的相关端口。
客户端clientC、服务器serverA与服务器serverB,通讯示意图以下:
要达到上述要求,咱们就能够经过ssh正向隧道的功能。为了看出实际的效果,在此以链接后端的mysql数据库为例。具体配置根据操做平台的不一样,分别介绍以下。
在Linux下配置ssh正向隧道比较简单,直接使用上述命令便可。以下:
ssh -g -f -NL 192.168.7.7:44010:10.66.115.185:3306 -i /home/ilanni/id_dsa_1024_0601 ilanni@115.159.39.187
ps -ef |grep 44010
上述命令的意思是在192.168.7.7这台机器经过ssh方式链接115.159.39.187这台服务器,而后把10.66.115.185这台服务器的3306端口也便是mysql端口映射为192.168.7.7的44010端口。
如今在局域网内,只要咱们链接192.168.7.7的44010端口,其实就在链接10.66.115.185的3306端口。
如今咱们来测试下,是否能够链接成功。在与192.168.7.7同一个LAN中的任意一台能链接192.168.7.7的44010端口的机器上,使用mysql的客户端,以下:
注意:IP地址和端口必定要填写为192.168.7.7和44010,而用户名和密码只须要填写mysql数据库对应的用户名和密码便可。
经过上面两张图,咱们能够看到链接192.168.7.7的44010端口,确实就是链接的10.66.115.185的3306端口。也便是在公司内部链接IDC内的后端数据库。
若是公司内部对访问后端数据库有权限要求的话,咱们能够在服务器serverB(mysql数据库10.66.115.185)上只容许服务器serverA(115.159.39.187)访问服务器serverB(10.66.115.185)的3306端口经过相关的安全策略好比IPtables或者mysql用户受权对服务器serverA(115.159.39.187)。
而后再在服务器serverA(115.159.39.187)也便是192.168.7.7上经过IPtables配置相关的内网机器能访问44010端口。
经过这样的操做就能够在公司内部达到控制后端mysql数据库的权限控制。
在windows下配置ssh正向隧道,须要咱们使用ssh相关的客户端软件。在此我使用的xshell,固然你也可使用putty等之类的软件。
打开xshell,新建一个链接到serverA(115.159.39.187)的会话,以下:
注意:这个地方填写的是serverA的IP地址。
在这填写的用户就是serverA的用户。
这张图很重要,由于是ssh正向隧道,因此在此类型里面选择的是Local。
源主机填写的是clientC的IP地址(在哪台机器就填写哪台机器的IP),侦听端口就是serverB的serverB_Port端口映射到clientC上的端口。注意侦听端口能够随便自定义。
目标主机填写的是serverB的IP地址,目标端口填写的是serverB_Port端口号。
以上配置完毕后,咱们在本机192.168.1.180上链接看看是否能够正确链接serverB的serverB_Port端口。以下:
经过以上几张图,咱们能够很明显的看出,以上配置是正确的。
注意:windows下配置ssh正向隧道和Linux仍是有所不一样的。windows正确配置后,若是要使用隧道的话。xshell链接serverA的会话不能关闭。也就是说clientC链接serverA的ssh会话要一直开着,并且即便正常链接后,该ssh会话也是一直存在的。以下:
什么是ssh反向隧道?
就是client连上server后,而后把client能访问的IP地址和端口(也包括client本身)镜像到server的端口上。
ssh反向隧道使用场景,好比你的客户端在内网,在外网是没法直接访问到的,这时用反向隧道打通一条链接,就能够从外网经过这条隧道进来了。
ssh反向隧道的命令以下:
ssh –R serverA_IP:serverA_port:clientC_IP:clientC_port -p serverA_sshport username@serverA_IP
上述命令的意思是在客户端clientC(或者clientC所在的LAN中的任意一台能链接clientC_port的机器)上经过ssh链接服务器serverA,而后再把客户端clientC的clientC_port端口映射到服务器serverA上的serverA_port端口。
也就是说若是咱们如今在服务器serverB上链接服务器serverA上的serverA_port端口的话,就是链接clientC的clientC_port端口。数据流向,以下图示:
注意:建议修改serverA服务器的ssh配置文件sshd_config,添加GatewayPorts yes。而后重启ssh服务。
这样ssh反向隧道创建成功后,在serverA服务器监听的端口为serverA服务器的全部地址。以下:
若是不这样修改的话,在serverA服务器监听的端口会为127.0.0.1。以下:
在Linux下配置ssh反向隧道比较简单,直接使用上述命令便可。以下:
ssh -g -f -NR 115.159.39.187:44010:192.168.5.174:3306 -i /home/ilanni/id_dsa_1024_0601 ilanni@115.159.39.187
ps -ef |grep 44010
上述命令的意思是在192.168.5.174这台机器经过ssh方式链接115.159.39.187这台服务器,而后把192.168.5.174这台服务器的3306端口也便是mysql端口在115.159.39.187服务器上映射为44010端口。
也就是说如今在公网上,只要咱们链接115.159.39.187的44010端口,其实就是在链接192.168.5.174的3306端口。
为了能很实际的效果,如今咱们在192.168.5.174上新建ilanni这个一个数据库。以下:
mysql -uroot -p123456
create database ilanni;
show databases;
如今咱们登陆到115.159.39.187服务器上进行查看。以下:
netstat -tunlp
经过上图,咱们能够看到115.159.39.187服务器上确实在监听44010端口。
下面咱们在115.159.39.187服务器上来链接下192.168.5.4的3306端口。以下:
mysql -h127.0.0.1 -P44010 -uroot -p123456
show databases;
经过上图,咱们能够很明显的看到在115.159.39.187服务器上链接44010端口确实链接到了192.168.5.4的3306端口。
在windows下配置ssh反向隧道,和配置ssh正向隧道基本同样也须要使用ssh相关的客户端软件,在此我使用的仍是xshell。
注意:ssh反向隧道,咱们能够在与clientC同一LAN的任意一台能访问clientC_Port端口的机器上进行。
打开xshell,新建一个链接到serverA(115.159.39.187)的会话,以下:
注意:这个地方填写的是serverA的IP地址。
在这填写的用户就是serverA的用户。
这张图很重要,由于是ssh反向隧道,因此在此类型里面选择的是Remote。
源主机填写的是serverA的IP地址,侦听端口就是clientC的clientC_Port端口映射到serverA上的端口。注意侦听端口能够随便自定义。
目标主机填写的是clientC的IP地址,目标端口填写的是clientC_Port端口号。
如今咱们登陆到115.159.39.187服务器上进行查看。以下:
netstat -tunlp
经过上图,咱们能够看到115.159.39.187服务器上确实在监听44010端口。
下面咱们在115.159.39.187服务器上来链接下192.168.5.4的3306端口。以下:
mysql -h127.0.0.1 -P44010 -uroot -p123456
show databases;
经过上图,咱们能够很明显的看到在115.159.39.187服务器上链接44010端口确实链接到了192.168.5.4的3306端口。
以上介绍了ssh正反向隧道详细使用方法,以mysql的3306端口为例子。下面我就结合实际的工做需求,介绍下ssh隧道的其余使用场合。
ssh隧道也是代理能够在windows以及Linux的远程桌面的,这种场合通常是在这样的场合下使用。
公司对外提供×××服务,可是该***服务器在网络DMZ防火区。***服务器能够访问lan内的机器,可是lan内的机器不能访问***服务器。结构图,以下:
***客户端链接进来后,咱们只须要在DMZ区的服务器上,建议一条ssh正向隧道便可链接隧道指定的lan机器。
以下:
ssh -g -f -N -L 7002:192.168.5.140:3389 wangxy@192.168.7.7
上述命令的意思是把192.168.5.140的3389端口映射到192.168.7.7的7002端口。也就说咱们如今在***客户端链接192.168.7.7的7002端口其实就是链接192.168.5.140的3389端口。以下:
经过上图,咱们能够很明显的看出ssh正向隧道已经代理了远程桌面。
如今公司线上云服务器上有一台业务serverB,前端使用nginx作反向代理,后端使用的是nodejs,serverB只对云服务器提供访问。
目前要求在公司内部也能够访问serverB上的nginx,而且不是公司内部全部人员均可以访问,只有指定的个别人才能有权限访问。
分析:若是要使公司内部访问serverB上的nginx,咱们只须要在serverB开放对公司公网的IP访问权限便可。
可是若是还要控制访问权限的话,这个就须要借助ssh正向隧道来实现了。
在云服务器上开放一台serverA,serverA能访问serverB的nginx(该访问权限的控制能够经过nginx或者iptables进行控制),而serverA又对公司的公网IP开放SSH端口。
而后在公司内网的任意一台lanC上,作一条ssh正向隧道。该隧道把serverB的nginx端口映射到serverC上一个PortC端口。
此时咱们再在lanC上对PortC端口的访问权限进行控制(该访问权限的控制能够经过nginx或者iptables进行控制)便可达到上述要求。
如今lanC上使用以下命令:
ssh -g -f -NL 192.168.5.4:8080:10.104.13.164:80 -i id_dsa_1024_0601 ilanni@115.159.39.187
ps -ef |grep 8080
上述命令的意思是在192.168.5.4上经过115.159.44.136这台服务器把10.105.12.163这台服务器的80端口映射为192.168.5.4的8080端口。
lanC的nginx配置以下:
server {
listen 80;
server_name 192.168.5.4;
allow 127.0.0.1;
allow 192.168.5.140;
deny all;
location / {
proxy_pass http://192.168.5.4:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 200;
proxy_send_timeout 200;
proxy_read_timeout 600;
}
}
上述nginx配置的意思是容许192.168.5.140这台机器访问192.168.5.4的80端口,而192.168.5.4会把访问192.168.5.4:80的请求交给192.168.5.4:8080进行处理。
这样就达到了前文的要求。
如今在192.168.5.140上访问192.168.5.4的80端口。以下:
经过上图,咱们能够很明显的看出ssh正向隧道已经能够代理nginx。
ssh多级隧道跳转看起来感受很难,其实若是细细拆分的话很简单的。
下面有一个实际的要求,咱们来分析下。
状况介绍:
serverC只容许serverB链接serverC的1001端口其余端口不容许serverB链接,而serverB只容许serverA能链接serverB的22端口,不能链接serverC的1001端口,同时serverA是只对公网开放的ssh的22端口其余端口不对公网开放。
要求:
如今要求lan内部的clientC能链接serverC的1001端口。
分析:
若是咱们直接serverC的1001端口那是不可能的,由于安全策略有限制。那么咱们能够经过ssh正向隧道来解决此问题。
首先在serverA上经过serverB作一条ssh正向隧道把serverC的1001端口映射为serverA的1002端口。
即访问serverA的1002端口就是访问serverC的1001端口。
由于serverA的1002端口不对公网开放,那么为了能访问serverA的1002端口,咱们能够在clientC经过serverA再作一条ssh正向隧道把serverA的1002端口映射为clientC的1003端口。
也就是说此时咱们链接clientC的1003端口其实就是在链接serverC的1001端口。
以上ssh多级隧道跳转的原理介绍清楚了,在次就不在进行演示。若是有哪位不懂的能够多多理解理解上面的描述。