1.1 ssh安全隧道(一):本地端口轉發
如下圖,假如host3和host1、host2都同互相通信,但是host1和host2之間不能通信,如何從host1連接上host2?
對于實現ssh連接來說,實現方式很簡單,從host1 ssh到host3,再ssh到host2,也就是將host3作為跳板的方式。但是如果不是ssh,而是http的80端口呢?如何讓host1能訪問host2的80端口?
ssh支持本地端口轉發,語法格式為:
ssh -L [local_bind_addr:]local_portremote_port middle_host
以上圖為例,實現方式是在host1上執行:
[root@xuexi ~]# ssh -g -L 222280 host3
其中"-L"選項表示本地端口轉發,其工作方式為:在本地指定一個由ssh監聽的轉發端口(2222),將遠程主機的端口(host2:80)映射為本地端口(2222),當有主機連接本地映射端口(2222)時,本地ssh就將此端口的數據包轉發給中間主機(host3),然后host3再與遠程主機的端口(host2:80)通信。
現在就可以通過訪問host1的2222端口來達到訪問host2:80的目的了。例如:
再來解釋下"-g"選項,指定該選項表示允許外界主機連接本地轉發端口(2222),如果不指定"-g",則host4將無法通過訪問host1:2222達到訪問host2:80的目的。甚至,host1自身也不能使用172.16.10.5:2222,而只能使用localhost:2222或127.0.0.1:2222這樣的方式達到訪問host2:80的目的,之所以如此,是因為本地轉發端口默認綁定在回環地址上。可以使用bind_addr來改變轉發端口的綁定地址,例如:
[root@xuexi ~]# ssh -L 172.16.10.5host2:80 host3
這樣,host1自身就能通過訪問172.16.10.5:2222的方式達到訪問host2:80的目的。
一般來說,使用轉發端口,都建議同時使用"-g"選項,否則將只有自身能訪問轉發端口。
再來分析下轉發端口通信的過程。
當host4發起172.16.10.5:2222的連接時(即步驟①),數據包的目標地址和端口為"172.16.10.5:2222"。由于host1上ssh已經監聽了2222端口,并且知道該端口映射自哪臺主機哪個端口,所以將會把該數據包目標地址和端口替換為"172.16.10.3:80",并將此數據包通過轉發給host3。當host3收到該數據包時,發現是host1轉發過來請求訪問host2:80的數據包,所以host3將代為訪問host2的80端口。
所以,host1和host3之間的通信方式是SSH協議,這段連接是安全加密的,因此稱為"安全隧道",而host3和host2之間通信協議則是HTTP而不是ssh。
現在再來考慮下,通過本地端口轉發的方式如何實現ssh跳板的功能呢?仍以上圖為例:
[root@xuexi ~]# ssh -g -L 2233322 host3]
這樣只需使用ssh連上host1的22333端口就等于連接了host2的22端口。
最后,關于端口轉發有一個需要注意的問題:ssh命令中帶有要執行的命令。考慮了下面的三條在host1上執行的命令的區別。
[root@xuexi ~]# ssh -g -L 2233322 host3 [root@xuexi ~]# ssh -g -L 2233322 host3 "ifconfig" [root@xuexi ~]# ssh -g -L 2233322 host3 "sleep 10"
第一條命令開啟了本地端口轉發,且是以登錄到host3的方式開啟的,所以執行完該命令后,將跳到host3主機上,當退出host3時,端口轉發功能將被關閉。另外,host1上之所以要開啟端口轉發,目的是為了與host2進行通信,而不是跳到host3上,所以應該在ssh命令行上加上"-f"選項讓ssh在本機host1上以后臺方式提供端口轉發功能,而不是跳到host3上來提供端口轉發功能。
第二條命令在開啟本地轉發的時候還指定了要在host3上執行"ifconfig"命令,但是ssh的工作機制是遠程命令執行完畢的那一刻,ssh關閉連接,所以此命令開啟的本地端口轉發功能有效期只有執行ifconfig命令的一瞬間。
第三條命令和第二條命令類似,只不過指定的是睡眠10秒命令,所以此命令開啟的本地轉發功能有效期只有10秒。
結合上面的分析,開啟端口轉發功能時,建議讓ssh以后臺方式提供端口轉發功能,且明確指示不要執行任何ssh命令行上的遠程命令。即最佳開啟方式為:
[root@xuexi ~]# ssh -f -N -g -L 2233322 host3
1.2 ssh安全隧道(二):遠程端口轉發
ssh除了支持本地端口轉發,還支持遠程端口轉發。顧名思義,遠程端口轉發表示的是將遠程端口的數據轉發到本地。
如下圖:假如host3是內網主機,它能和host2互相通信,也能和host1通信,但反過來,host1不能和host3通信。這時要讓host1訪問host3或host2就沒辦法通過本地端口轉發了,因為要在host1上開啟本地端口轉發,必須要和host3通信請求建立隧道。
可以通過在host3上發起遠程端口轉發來實現,因為host3能和host1通信,host3可以請求在host1和host3之間建立隧道。
語法如下:
ssh -R [bind_addr:]remote1_port:host:port remote1
以上圖為例,實現方式是在host3上執行:
[root@xuexi ~]# ssh -R 2233380 host1
這表示host3請求host1上的sshd服務,在host1上建立一個套接字監聽22333端口,它是host2端口的映射,當有主機連接host1:22333時,此連接中的數據全部都通過host1和host3之間的安全隧道轉發給host3,再由host3向host2的80端口發起訪問。由于host3請求開啟的轉發端口是在遠程主機host1上的,所以稱為"遠程端口轉發"。
再考慮下面這條命令所開啟的遠程轉發端口,它是在host3上執行的。
[root@xuexi ~]# ssh -R 2233380 host1
該命令將自身的host3:80映射到host1:22333上,這也能讓host1和host2、host3通信,因為隧道是建立在host1:22333<-->host3:80上的。
但是,遠程端口轉發和本地端口轉發最大的一個區別是,遠程轉發端口是由host1上的sshd服務控制的,默認配置情況下,sshd服務只允許本地開啟的遠程轉發端口(22333)綁定在環回地址(127.0.0.1)上,即使顯式指定了bind_addr也無法覆蓋。例如:
[root@xuexi ~]# ssh -R *host2:80 host1 [root@xuexi ~]# netstat -tnlp Active Internet connections (only servers) tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 8405/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1422/master tcp 0 0 127.0.0.1:22333 0.0.0.0:* LISTEN 8407/sshd tcp 0 0 :::22 :::* LISTEN 8405/sshd tcp 0 0 ::1:25 :::* LISTEN 1422/master tcp 0 0 ::1:22333 :::* LISTEN 8407/sshd
要允許本地的遠程轉發端口綁定在非環回地址上,需要在host1的sshd配置文件中啟用"GatewayPorts"項,它的默認值為no。啟動該選項后,不給定bind_addr或bind_addr設置為"*"都表示綁定在所有地址上。如下:
[root@xuexi ~]# ssh -g -R *host2:80 host1 [root@xuexi ~]# netstat -tnlp Active Internet connections (only servers) tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 8466/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1422/master tcp 0 0 0.0.0.0:22333 0.0.0.0:* LISTEN 8468/sshd tcp 0 0 :::22 :::* LISTEN 8466/sshd tcp 0 0 ::1:25 :::* LISTEN 1422/master tcp 0 0 :::22333 :::* LISTEN 8468/sshd
和前面的本地轉發端口一樣,建議的幾個選項是:"-g"、"-f"、"-N"。即推薦的命令寫法是:
[root@xuexi ~]# ssh -fgN -R 2233380 host1
現在,就可以通過訪問host1:22333達到訪問host2:80的目的了。如下圖所示。
1.3 ssh安全隧道(三):動態端口轉發(SOCKS代理)
無論是本地端口轉發還是遠程端口轉發,都是將某固定主機及其端口映射到本地或遠程轉發端口上,例如將host2:80映射到host1:2222。也就是說,本地或遠程轉發端口和目標端口所代表的應用層協議是一對一的關系,2222端口必須對應的是http的80端口,使用瀏覽器向host1:2222端口發起http請求當然沒問題,但是使用ssh工具向host1:2222發起連接將會被拒絕,因為host2上http服務只能解析http請求,不能解析ssh連接請求。
ssh支持動態端口轉發,由ssh來判斷發起請求的工具使用的是什么應用層協議,然后根據判斷出的協議結果決定目標端口。
以下圖為例進行說明,host1處在辦公內網,能和host3互相通信,但它無法直接和互聯網和host2通信,而host3則可以和host2以及互聯網通信。
要讓host1訪問互聯網,又能和host2的22端口即ssh服務通信,顯然在host1上僅設置一個本地端口轉發是不夠的,雖然可以設置多個本地轉發端口分別映射不同的端口,但這顯然比較笨重和麻煩。使用動態端口轉發即可。
語法格式為:
ssh -D [bind_addr:]port remote
以上圖為例,在host1上執行:
[root@xuexi ~]# ssh -Nfg -D 2222 host3
執行完上面的命令,host1將在本地開啟SOCKS4或SOCKS5服務來監聽2222端口。只要客戶端程序工具(隱含了使用的應用層協議類型)將其自身的代理設置為host1:2222,則該程序所有產生的數據都將轉發到host1:2222,再由host1:2222將數據通過隧道轉發給host3,最后由host3和互聯網或host2上對應客戶端工具的應用層協議的端口進行通信。
其實很簡單,假如host4使用IE瀏覽器作為客戶端工具,并將IE瀏覽器的代理設置為host1:2222,由于IE瀏覽器發起的請求使用的是http協議(此處不考慮其他可能的協議),那么IE瀏覽器產生的數據都轉發到host1:2222,再由host1:2222通過隧道轉發給host3,host3能聯網,所以host4就實現了聯網功能。如下圖設置:
再比如host4上的QQ客戶端也可以設置代理。這樣QQ產生的數據都將通過host1:2222轉發出去,host1:2222再將QQ的數據轉發到host3上,host3知道這些數據使用的協議是oicq,所以host3會去連接騰訊的QQ服務器(oicq服務對應的端口)。
ssh只支持socks4和socks5兩種代理,有些客戶端工具中需要明確指明代理類型。
和本地、遠程端口轉發一樣,建議的選項是:"-f"、"-N"和"-g"。
由于ssh動態端口轉發是ssh客戶端的功能,所以不使用ssh命令,使用SecurtCRT、putty等ssh客戶端工具都可以實現代理上網。例如,本地主機不能上網,但能和172.16.10.6的SSH服務通信,而172.16.10.6能上網,則可以在本地主機先使用SecurtCRT連接172.16.10.6,再在對應的會話選項上做如下設置,使得本地主機也能上網。(注意:我沒說可以FQ啊,好公民不FQ!!!)
然后,在本地主機查看下是否監聽了SecurtCRT中指定的8888動態轉發端口。
現在,本機所有數據包都通過SecurtCRT所連接的172.16.10.6流向外界。
鏈接:https://www.cnblogs.com/f-ck-need-u/p/10482832.html
-
主機
+關注
關注
0文章
1029瀏覽量
35713 -
端口
+關注
關注
4文章
1003瀏覽量
32604 -
SSH
+關注
關注
0文章
192瀏覽量
16692
原文標題:SSH隧道:端口轉發功能詳解
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
探索物聯網HMI的端口轉發和NAT功能

SSH端口號是什么?SSH原理詳解分析

SSH端口號是什么?SSH是如何工作的?

Ubuntu修改SSH默認端口指南
宏集干貨丨探索物聯網HMI的端口轉發和NAT功能

評論