前幾篇有關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多級隧道跳轉的原理介紹清楚了,在次就不在進行演示。若是有哪位不懂的能夠多多理解理解上面的描述。