爛泥:學習ssh之ssh隧道應用

前幾篇有關ssh的文章,我們只是介紹了ssh的登錄功能。其實ssh功能不只是這些,這篇文章我們來介紹下有關ssh隧道的功能。    

ssh隧道也叫ssh端口轉發,或者叫ssh tunnel,這些都是說的是ssh隧道功能。在此,我們統稱爲ssh隧道。

ssh隧道分爲正向隧道和反向隧道,在實際工作中我們可以根據需要來隨其分別使用。

下面開始對正向和反向隧道分別介紹下,由於使用平臺的不同,我們分爲Linux和windows平臺。

一、ssh正向隧道

什麼是ssh正向隧道?

就是client連上server後,然後把server能訪問的IP地址和端口(當然也包括server自己)鏡像到client的端口上。

在平時工作中,正向隧道是我們使用最多的一種方式。

ssh正向隧道的命令如下:

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,通信示意圖如下:

clip_image001

要達到上述要求,我們就可以通過ssh正向隧道的功能。爲了看出實際的效果,在此以連接後端的mysql數據庫爲例具體配置根據操作平臺的不同,分別介紹如下。

1.1 Linux下配置ssh正向隧道

在Linux下配置ssh正向隧道比較簡單,直接使用上述命令即可。如下:

ssh -g -f -NL 192.168.7.7:44010:10.66.115.185:3306 -i /home/ilanni/id_dsa_1024_0601 [email protected]

ps -ef |grep 44010

clip_image002

上述命令的意思是在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的客戶端,如下:

clip_image003

注意:IP地址和端口一定要填寫爲192.168.7.7和44010,而用戶名和密碼只需要填寫mysql數據庫對應的用戶名和密碼即可。

clip_image004

clip_image005

通過上面兩張圖,我們可以看到連接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數據庫的權限控制。

1.2 windows下配置ssh正向隧道

在windows下配置ssh正向隧道,需要我們使用ssh相關的客戶端軟件。在此我使用的xshell,當然你也可以使用putty等之類的軟件。

打開xshell,新建一個連接到serverA(115.159.39.187)的會話,如下:

clip_image006

注意:這個地方填寫的是serverA的IP地址。

clip_image007

在這填寫的用戶就是serverA的用戶。

clip_image008

clip_image009

這張圖很重要,因爲是ssh正向隧道,所以在此類型裏面選擇的是Local。

源主機填寫的是clientC的IP地址(在哪臺機器就填寫哪臺機器的IP),偵聽端口就是serverB的serverB_Port端口映射到clientC上的端口。注意偵聽端口可以隨便自定義。

目標主機填寫的是serverB的IP地址,目標端口填寫的是serverB_Port端口號。

以上配置完畢後,我們在本機192.168.1.180上連接看看是否可以正確連接serverB的serverB_Port端口。如下:

clip_image010

clip_image011

clip_image012

通過以上幾張圖,我們可以很明顯的看出,以上配置是正確的。

注意:windows下配置ssh正向隧道和Linux還是有所不同的。windows正確配置後,如果要使用隧道的話。xshell連接serverA的會話不能關閉。也就是說clientC連接serverA的ssh會話要一直開着,而且即使正常連接後,該ssh會話也是一直存在的。如下:

clip_image013

二、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端口。數據流向,如下圖示:

clip_image014

注意:建議修改serverA服務器的ssh配置文件sshd_config,添加GatewayPorts yes。然後重啓ssh服務。

clip_image015

這樣ssh反向隧道建立成功後,在serverA服務器監聽的端口爲serverA服務器的所有地址。如下:

clip_image016

如果不這樣修改的話,在serverA服務器監聽的端口會爲127.0.0.1。如下:

clip_image017

2.1 Linux下配置ssh反向隧道

在Linux下配置ssh反向隧道比較簡單,直接使用上述命令即可。如下:

ssh -g -f -NR 115.159.39.187:44010:192.168.5.174:3306 -i /home/ilanni/id_dsa_1024_0601 [email protected]

ps -ef |grep 44010

clip_image018

上述命令的意思是在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;

clip_image019

現在我們登錄到115.159.39.187服務器上進行查看。如下:

netstat -tunlp

clip_image016[1]

通過上圖,我們可以看到115.159.39.187服務器上確實在監聽44010端口。

下面我們在115.159.39.187服務器上來連接下192.168.5.4的3306端口。如下:

mysql -h127.0.0.1 -P44010 -uroot -p123456

show databases;

clip_image020

通過上圖,我們可以很明顯的看到在115.159.39.187服務器上連接44010端口確實連接到了192.168.5.4的3306端口。

2.2 windows下配置ssh反向隧道

在windows下配置ssh反向隧道,和配置ssh正向隧道基本一樣也需要使用ssh相關的客戶端軟件,在此我使用的還是xshell。

注意:ssh反向隧道,我們可以在與clientC同一LAN的任意一臺能訪問clientC_Port端口的機器上進行。

打開xshell,新建一個連接到serverA(115.159.39.187)的會話,如下:

clip_image021

注意:這個地方填寫的是serverA的IP地址。

clip_image007[1]

在這填寫的用戶就是serverA的用戶。

clip_image008[1]

clip_image022

這張圖很重要,因爲是ssh反向隧道,所以在此類型裏面選擇的是Remote。

源主機填寫的是serverA的IP地址,偵聽端口就是clientC的clientC_Port端口映射到serverA上的端口。注意偵聽端口可以隨便自定義。

目標主機填寫的是clientC的IP地址,目標端口填寫的是clientC_Port端口號。

現在我們登錄到115.159.39.187服務器上進行查看。如下:

netstat -tunlp

clip_image016[2]

通過上圖,我們可以看到115.159.39.187服務器上確實在監聽44010端口。

下面我們在115.159.39.187服務器上來連接下192.168.5.4的3306端口。如下:

mysql -h127.0.0.1 -P44010 -uroot -p123456

show databases;

clip_image020[1]

通過上圖,我們可以很明顯的看到在115.159.39.187服務器上連接44010端口確實連接到了192.168.5.4的3306端口。

三、實際應用

以上介紹了ssh正反向隧道詳細使用方法,以mysql的3306端口爲例子。下面我就結合實際的工作需求,介紹下ssh隧道的其他使用場合。

3.1 遠程桌面

ssh隧道也是代理可以在windows以及Linux的遠程桌面的,這種場合一般是在這樣的場合下使用。

公司對外提供***服務,但是該***服務器在網絡DMZ防火區。***服務器可以訪問lan內的機器,但是lan內的機器不能訪問***服務器。結構圖,如下:

clip_image023

***客戶端連接進來後,我們只需要在DMZ區的服務器上,建議一條ssh正向隧道即可連接隧道指定的lan機器。

如下:

ssh -g -f -N -L 7002:192.168.5.140:3389 [email protected]

clip_image024

上述命令的意思是把192.168.5.140的3389端口映射到192.168.7.7的7002端口。也就說我們現在在***客戶端連接192.168.7.7的7002端口其實就是連接192.168.5.140的3389端口。如下:

clip_image025

clip_image026

clip_image027

通過上圖,我們可以很明顯的看出ssh正向隧道已經代理了遠程桌面。

3.2 nginx訪問

現在公司線上雲服務器上有一臺業務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 [email protected]

ps -ef |grep 8080

clip_image028

上述命令的意思是在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端口。如下:

clip_image029

通過上圖,我們可以很明顯的看出ssh正向隧道已經可以代理nginx。

3.3 ssh多級隧道跳轉

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多級隧道跳轉的原理介紹清楚了,在次就不在進行演示。如果有哪位不懂的可以多多理解理解上面的描述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章