本章主要介紹了什么是 SSH 隧道以及如何使用 SSH 隧道,包括 SSH 隧道加密數(shù)據(jù)傳輸以及繞過防火墻。
1. 什么是 SSH 隧道
SSH 隧道是 SSH 中的一種機制,它能夠將其他 TCP 端口的網(wǎng)絡數(shù)據(jù)通過 SSH 連接來轉發(fā),并且自動提供了相應的加密及解密服務。因為 SSH 為其他 TCP 鏈接提供了一個安全的通道來進行傳輸,因此這一過程也被叫做“隧道”(tunneling)。
SSH 隧道也可以叫做端口轉發(fā)
SSH 隧道能夠提供兩大功能:
-
1)加密 SSH Client 端至 SSH Server 端之間的通訊數(shù)據(jù)。
-
2)突破防火墻的限制完成一些之前無法建立的 TCP 連接。
本地轉發(fā)和遠程轉發(fā)
SSH 端口轉發(fā)自然需要 SSH 連接,而 SSH 連接是有方向的,從 SSH Client 到 SSH Server 。而我們的應用也是有方向的,比如需要連接 MySQL Server 時,MySQL Server 自然就是 Server 端,我們應用連接的方向也是從應用的 Client 端連接到應用的 Server 端。如果這兩個連接的方向一致,那我們就說它是本地轉發(fā)。而如果兩個方向不一致,我們就說它是遠程轉發(fā)。
相關參數(shù)
-
“-L選項”:local,表示使用本地端口轉發(fā)創(chuàng)建 ssh 隧道
-
“-R選項”:remote,表示使用遠程端口轉發(fā)創(chuàng)建 ssh 隧道
-
“-D選項”:dynamic,表示使用動態(tài)端口轉發(fā)創(chuàng)建 ssh 隧道
-
“-N選項”: 表示創(chuàng)建隧道以后不連接到 sshServer端,通常與”-f”選項連用
-
“-f選項”:表示在后臺運行ssh隧道,通常與”-N”選項連用
-
“-g選項”:表示 ssh 隧道對應的轉發(fā)端口將監(jiān)聽在主機的所有IP中,不使用”-g選項”時,轉發(fā)端口默認只監(jiān)聽在主機的本地回環(huán)地址中,”-g” 表示開啟網(wǎng)關模式,遠程端口轉發(fā)中,無法開啟網(wǎng)關功能
2. 演示
本地轉發(fā)
客戶端:192.168.172.131
服務端:192.168.172.133
一般是 server 端有 IP 能訪問時用本地轉發(fā)。
將服務器 192.168.172.133 上的 8888 端口映射到本地[192.168.172.131]的 18888 端口,即將本地 18888 端口流量轉發(fā)到服務器 192.168.172.133 上的 8888 端口。
比如不能直接訪問 server 的 8888 端口,此時就可以使用 ssh 隧道來突破該限制。
在服務器 192.168.172.133 上啟動一個 http server:
[root@localhost ~]# python -m SimpleHTTPServer 8888
Serving HTTP on 0.0.0.0 port 8888 ...
然后在本地執(zhí)行以下命令,開啟 ssh 隧道。
命令1
[root@davytestcentos ~]# ssh -N -L 18888:localhost:8888 root@192.168.172.133
root@192.168.172.133's password:
#這里隧道建立后,會正常進行,進程沒有退出 -f 后臺運行
該命令表示在本地和 192.168.172.133 之間建立 ssh 隧道,由 ssh 客戶端監(jiān)聽本地的 8888 端口并將流量轉發(fā)到 192.168.172.133 的 sshServer,最終由 sshServer 在轉發(fā)到 8888 端口
每部分參數(shù)具體含義如下:
-
“-N選項”:表示創(chuàng)建隧道以后不連接到 sshServer 端
-
“-L選項”:local,表示使用本地端口轉發(fā)創(chuàng)建 ssh 隧道
-
18888:localhost:8888:遠端的 8888 端口會被轉發(fā)到 localhost:8888 端口上去。
-
這里的 localhost 實際上指監(jiān)聽【192.168.172.133 】的本地回環(huán)地址,如果要監(jiān)聽其他 IP 也可以手動指定
-
root@192.168.172.133 :我們創(chuàng)建的 ssh 隧道是連接到 192.168.172.133 上的 root 用戶的
測試一下,請求本地[curl http://localhost:18888] 18888 端口能否訪問到 遠程服務器上的 http server。
[root@davytestcentos ~]# curl http://localhost:18888
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
。。。。。。。。。
</body>
這時轉發(fā)數(shù)據(jù)流是: client 上的應用客戶端將數(shù)據(jù)發(fā)送到本地的 18888 端口上, client 上的 ssh 客戶端將本地 18888 端口收到的數(shù)據(jù)加密后發(fā)送到 server 端的 ssh server上,ssh server 會解密收到的數(shù)據(jù)并將之轉發(fā)到監(jiān)聽的 8888 端口 最后再將從 http server 返回的數(shù)據(jù)原路返回以完成整個流程。
可以看到,本地已經(jīng)開啟的 18888 端口的監(jiān)聽。
[root@davytestcentos ~]# netstat -tunlp|grep 18888
tcp 0 0 127.0.0.1:18888 0.0.0.0:* LISTEN 7306/ssh
tcp6 0 0 ::1:18888 :::* LISTEN 7306/ssh
命令2
命令1執(zhí)行后,沒有執(zhí)行本地地址,默認是在監(jiān)聽本地回環(huán)地址??梢栽O置監(jiān)聽非本地回環(huán)地址,比如執(zhí)行下面這個命令就可以在 ip 192.168.172.131 上監(jiān)聽:
[root@davytestcentos ~]# ssh -N -L 192.168.172.131:18888:192.168.172.133:8888 root@192.168.172.133
root@192.168.172.133's password:
訪問網(wǎng)址:
[root@davytestcentos ~]# curl http://localhost:18888
curl: (7) Failed connect to localhost:18888; 拒絕連接
[root@davytestcentos ~]# curl http://192.168.172.131:18888
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
。。。。。。。
</html>
本地端口監(jiān)聽如下:
[root@davytestcentos ~]# netstat -tunlp|grep 18888
tcp 0 0 192.168.172.131:18888 0.0.0.0:* LISTEN 7400/ssh
命令3
如果你覺得這還不夠,希望所有 IP 地址的 18888 端口都被監(jiān)聽,那么可以在建立隧道時開啟”網(wǎng)關功能”,使用”-g”選項可以開啟”網(wǎng)關功能”:
[root@davytestcentos ~]# ssh -g -N -L 18888:192.168.172.133:8888 root@192.168.172.133
root@192.168.172.133's password:
訪問網(wǎng)址:
[root@davytestcentos ~]# curl http://localhost:18888
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
。。。。。。。。。
</body>
</html>
[root@davytestcentos ~]# curl http://192.168.172.131:18888
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
。。。。。。。。。。
</body>
</html>
本地監(jiān)聽情況如下:
[root@davytestcentos ~]# netstat -tunlp|grep 18888
tcp 0 0 0.0.0.0:18888 0.0.0.0:* LISTEN 7513/ssh
tcp6 0 0 :::18888
至此,我們已經(jīng)了解 ssh 本地轉發(fā)功能了,接下來看一下遠程轉發(fā)。
遠程轉發(fā)
客戶端:192.168.172.131
服務端:192.168.172.133
當 server 端沒有可以直接訪問的 IP 時就無法使用本地轉發(fā)了,如果本地有 IP 可以直接訪問那么還可以使用遠程轉發(fā),也就是在服務端設置遠程轉發(fā)。
在服務器 192.168.172.133 上啟動一個 http server:
[root@localhost ~]# python -m SimpleHTTPServer 8888
Serving HTTP on 0.0.0.0 port 8888 ...
然后假設本地有一個 server (192.168.172.133)端能訪問的IP地址 192.168.172.131 ,然后在 服務端(192.168.172.133)上執(zhí)行以下命令將端口轉發(fā)到本地端口
[root@localhost ~]# ssh -N -R 18888:localhost:8888 root@192.168.172.131
root@192.168.172.131's password:
可以看做是在 server 端執(zhí)行的一個本地轉發(fā),因為 server 端沒有 ip 所以需要反過來操作。
端口監(jiān)聽都是在本地發(fā)生,但是執(zhí)行命令的機器卻變成了 server 端。
命令執(zhí)行后會在本地(192.168.172.131)監(jiān)聽端口,并將流量轉發(fā)到我們的 server 端。之前本地轉發(fā)時也是在本地監(jiān)聽端口
將本地服務器(192.168.172.131) 的 18888 端口轉發(fā)到 server 端的 8888 端口。
唯一區(qū)別是遠程轉發(fā)模式下 只能監(jiān)聽本地回環(huán)地址,不能監(jiān)聽其他IP,也不能開啟網(wǎng)關模式,即無法讓其他機器通過本地服務器(192.168.172.133) 來訪問 server。
由于是在 server 端執(zhí)行的命令,因此該場景中 server端扮演的是 ssh client 的角色,而 client 端則是 ssh server。
此時的數(shù)據(jù)流向為:client 端數(shù)據(jù)發(fā)送到 18888 端口,client 端上的 ssh server 監(jiān)聽該端口并對數(shù)據(jù)進行加密后轉發(fā)到 server 端的 ssh client,ssh client 解密數(shù)據(jù)后轉發(fā)到 server 節(jié)點的 8888 端口。
擴展-跨機器轉發(fā)
ServerAIP:192.168.172.135
ServerBIP:192.168.172.131
ServerBIP:192.168.172.133
具體場景如下圖所示:
如上圖所示,我們想要在A與B之間創(chuàng)建隧道,最終通過隧道訪問到ServerC中的 http 服務。
ServerA與ServerB上沒有開啟任何 http 服務,ServerC中開啟了 http 服務,監(jiān)聽了 8888 端口。
我們需要在 ServerA 192.168.172.135上執(zhí)行以下命令開啟 ssh 隧道:
[root@localhost ~]# ssh -N -L 18888:192.168.172.133:8888 root@192.168.172.131
root@192.168.172.131's password:
執(zhí)行后 ServerA 上已經(jīng)開始監(jiān)聽 8888 端口了,默認是在本地回環(huán)地址上,需要其他機器訪問的話可以指定 ip 或者增加 -g 參數(shù)開啟網(wǎng)關模式。在本地轉發(fā)篇講過
[root@localhost ~]# netstat -tunlp|grep 18888
tcp 0 0 127.0.0.1:18888 0.0.0.0:* LISTEN 1608/ssh
tcp6 0 0 ::1:18888 :::* LISTEN 1608/ssh
然后測試一下
[root@localhost ~]# curl http://localhost:18888
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
。。。。。。。。。
</body>
</html>
注意
上述場景中存在一個問題,就是數(shù)據(jù)安全性的問題,我們之所以使用ssh隧道,就是為了用它來保護明文傳輸?shù)臄?shù)據(jù),從而提升安全性,不過,在上例的場景中,只有ServerA與ServerB之間的傳輸是受ssh隧道保護的,ServerB與ServerC之間的傳輸,仍然是明文的,所以,如果想要在上述場景中使用ssh隧道進行數(shù)據(jù)轉發(fā),首先要考慮ServerB與ServerC之間的網(wǎng)絡是否可靠。
其實,當我們在創(chuàng)建隧道時如果開啟了網(wǎng)關功能,那么應用客戶端與Client之間的通訊也會面臨同樣的問題。
其實一般這種場景主要是為了繞過防火墻。
動態(tài)轉發(fā)
對于本地端口轉發(fā)和遠程端口轉發(fā),都存在兩個一一對應的端口,分別位于 SSH 的客戶端和服務端,而動態(tài)端口轉發(fā)則只是綁定了一個本地端口,而目標地址:目標端口則是不固定的。目標地址:目標端口是由發(fā)起的請求決定的,比如,請求地址為192.168.1.100:3000,則通過 SSH 轉發(fā)的請求地址也是192.168.1.100:3000。
在本地執(zhí)行以下命令,
ssh -N -D localhost:2000 root@192.168.172.133
會在本地開啟一個 socks 代理,監(jiān)聽 2000 端口
[root@kc-1 tmp]# netstat -tunlp|grep 2000
tcp 0 0 127.0.0.1:2000 0.0.0.0:* LISTEN 25496/ssh
tcp6 0 0 ::1:2000 :::* LISTEN 25496/ssh
我們只需要在本地配置上 socks 代理,localhost:2000 即可把所有請求通過 ssh 2000 端口轉發(fā)到 192.168.172.133 這臺機器上去了。
3. 通過跳轉主機建立 SSH 隧道
許多大公司為了保障安全,會實施嚴格的規(guī)則來訪問托管應用程序的服務器。其中一種安全措施是在客戶端和需要訪問的服務器之間放置一個網(wǎng)關,也被稱為跳轉服務器、跳轉主機或跳轉盒。
一種典型實現(xiàn)如下:首先需要使用您的憑據(jù)打開與 Jump 主機的 SSH 連接。然后,從 Jump 主機內部打開第二個 SSH 連接,以訪問需要使用另一個帳戶訪問的實際服務器。通常,這個帳戶是用于部署和運行應用程序的用戶,而不是個人帳戶。
假設您在這樣的公司工作,并且想要創(chuàng)建一個 SSH 隧道,讓連接到只能從App Server訪問的 Oracle DB Server的端口 1521。您需要做的是創(chuàng)建一個如下所示的 SSH 隧道:
以下命令通過跳轉主機創(chuàng)建此 SSH 隧道(系統(tǒng)將提示您輸入用戶密碼):
$ ssh -v -N appusr@appserver -J myusr@jumphost -L 1521:dbserver:1521
命令解釋:
將本地主機的端口 1521 通過和DB Server的端口 1521建立了隧道。包含以下參數(shù):
-
-v:表示啟用詳細模式,輸出詳細的連接信息,這對于調試很有用,并且不返回appserver的 shell 提示符
-
-N:表示禁用遠程命令執(zhí)行,只連接到遠程主機,不執(zhí)行任何命令,也是就是只做轉發(fā)端口。
-
appusr@appserver:表示要連接的遠程主機的用戶名和主機名。
-
-J:表示使用代理命令連接到跳板機。
-
myusr@jumphost:其中,myusr 是跳板機的用戶名,jumphost 是跳板機的主機名。
-
-L :local,表示使用本地端口轉發(fā)創(chuàng)建 ssh 隧道。
-
1521:dbserver:1521:表示將本地端口 1521 映射到遠程主機的端口 1521。其中,1521 是本地端口號,dbserver 是遠程主機的主機名,1521 是遠程主機的端口號。
命令的作用:使用 appusr 用戶名連接到 appserver 主機,并通過跳板機 jumphost 連接到 dbserver 主機,將本地端口 1521 映射到遠程主機的端口 1521。
換句話說:您首先使用用戶myusr與jumphost建立SSH連接,然后使用用戶appusr與appserver建立另一個SSH連接,最后將端口1521從本地主機轉發(fā)到dbserver。
建立后效果: 您可以使用SQL 客戶端工具連接到遠程數(shù)據(jù)庫服務器,就像它在 localhost:1521 上運行一樣。
4. 小結
SSH 有以下功能:
-
1)保護 tcp 會話,保護會話中明文傳輸?shù)膬热荨?/p>
-
2)繞過防火墻或者穿透到內網(wǎng),訪問對應的服務。
常用命令:
創(chuàng)建本地轉發(fā)模式的ssh隧道,命令如下
ssh -g -N -L forwardingPort:targetIP:targetPort user@sshServerIP
本機上的 forwardingPort 將會被監(jiān)聽,訪問本機的 forwardingPort,就相當于訪問 targetIP 的 targetPort,ssh隧道建立在本機與 sshServer 之間。
創(chuàng)建遠程轉發(fā)模式的ssh隧道,命令如下
ssh -N -R forwardingPort:targetIP:targetPort user@sshServerIP
sshServer 上的 forwardingPort 將會被監(jiān)聽,訪問 sshServer 上的 forwardingPort,就相當于訪問 targetIP 的 targetPort,ssh 隧道建立在本機與 sshServer 之間。
5. 參考
SSH Tunneling: Examples, Command, Server Config文章來源:http://www.zghlxwxcb.cn/news/detail-739792.html
ssh端口轉發(fā):ssh隧道文章來源地址http://www.zghlxwxcb.cn/news/detail-739792.html
到了這里,關于SSH 隧道簡明教程的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!