在一開始學習ssh端口轉發的時候,總是被本地端口轉發和遠程端口轉發的區別搞得頭大,纏斗數日無果,沉思一番之后,決定逐個攻破,先揪住一個掰開揉碎,另一個再如法炮制,如此一來,迷惑可解矣。ssh一般會涉及到3個角色:兩個端之間建立ssh連接,還有一個角色則是轉發的目的地,為避免A、B、C這樣一看便覺枯燥的指代名詞,我們請出在東方大陸婦孺皆知的取經隊伍
(資料圖)
某一日悟空又和三藏鬧矛盾了,三藏賭氣不理悟空了,這時悟空想要和三藏建立聯系就需要八戒來當傳聲筒。現在利用三臺虛擬機來具象化這個例子悟空:192.168.1.1(CentOS7.8)八戒:192.168.1.2(CentOS7.8)三藏:192.168.1.3(Ubuntu20.04)192.168.1.3的防火墻設置拒絕來自192.168.1.1的訪問ufw deny from 192.168.1.1
這時,192.168.1.1想要和192.168.1.3建立連接,就可以通過192.168.1.2來建立一個隧道,在192.168.1.1上執行ssh -L 30000:192.168.1.3:22 root@192.168.1.2
,這樣隧道就建立起來了。這里-L
即Local
,指本地端口轉發;30000:192.168.1.3:22
指把對192.168.1.1的30000端口的訪問轉發到192.168.1.3的22端口(在做轉發之前應該先檢查192.168.1.1的30000端口是否已經被占用了,可以使用lsof -i:port
來進行檢查);最后面的root@192.168.1.2
要和最前面的ssh
放在一起看,也就是說,192.168.1.1先執行了ssh root@192.168.1.2
,依據這個ssh連接建立起了一個本地端口轉發的隧道,隧道實現了 30000:192.168.1.3:22
所指的轉發工作。
當完成了上面所說的建立隧道的工作,就可以測試隧道的連通性了,在任意一個192.168.1.1的終端執行telnet localhost 30000
進行測試,如果測試通過(輸出結果為已連接,而不是連接被拒絕),說明隧道沒問題,下一步可以嘗試使用ssh通過隧道連接到192.168.1.3了,在任意一個192.168.1.1的終端執行ssh root@localhost -p 30000
,即可以ssh登錄到192.168.1.3,在192.168.1.3看來,該ssh會話的來源是192.168.1.2。
有個小細節,在192.168.1.1上執行ssh -L 30000:192.168.1.3:22 root@192.168.1.2
之后,終端會打開192.168.1.1到192.168.1.2的會話,但是這樣原來192.168.1.1的終端就被占用了,為了節省出這個終端,執行端口轉發可以加上-Nf
參數,-N
表示不執行命令,使得該ssh連接只起到隧道的作用,-f
表示在后臺運行該ssh連接。還有一點要注意,-f
參數不能單獨使用,因為在沒有 -N
特別指明的情況下,無法把沒有指定登錄后要執行的命令的ssh會話放到后臺。
除了在192.168.1.1執行端口轉發,192.168.1.1要和192.168.1.3建立會話,在192.168.1.2做一個本地端口轉發也能達到同樣的目的。在192.168.1.2執行:ssh -NfL 30000:192.168.1.3:22 root@localhost
,這里192.168.1.2與自身建立了一個會話,把對自己的30000端口的訪問轉發到了192.168.1.3的22端口。但是這樣還不能達到目的,這是因為OpenSSH有一個限制,默認情況下,ssh只監聽來自本機的回環地址的對于本地轉發端口的訪問,在這里也就是只有192.168.1.2自己才能訪問30000這個本地轉發端口。想要達到目的,還需要一個參數:-g
,-g
能夠取消這個限制,使得其他主機也能夠訪問這個本地轉發端口,所以192.168.1.2應該執行的完整的命令是:ssh -g -NfL 30000:192.168.1.3:22 root@localhost
。此外,如果192.168.1.2開啟了iptables,iptables的INPUT鏈中相關的 target 為 REJECT 的規則也會阻止其他主機訪問本地轉發端口。
某一日悟空又和三藏鬧矛盾了,三藏把悟空趕走了,悟空于是回到花果山,開始過逍遙自在的日子。沒過多久,三藏那邊取經形式日益嚴重,路上遇到的妖怪八戒和沙僧解決起來力有不逮,唐僧于是責怪八戒能力不足,八戒開始懷念大師兄在的日子,但是此時唐僧和猴哥都不愿說軟話,八戒沒得辦法,只得主動去找大師兄,陪著笑臉,意在溝通唐僧和悟空彼此思念之情。
仍然以三臺虛擬機來創建實例悟空:192.168.1.1(CentOS7.8)八戒:192.168.1.2(CentOS7.8)三藏:192.168.1.3(Ubuntu20.04)192.168.1.3的防火墻設置拒絕來自192.168.1.1的訪問ufw deny from 192.168.1.1
這一回,192.168.1.1無意主動通過192.168.1.2建立隧道,反過來,192.168.1.2要主動與192.168.1.1建立連接,在192.168.1.1和192.168.1.3之間建立一個隧道。為此,192.168.1.2需要執行:ssh -NfR 30000:192.168.1.3:22 root@192.168.1.1
,-R
即remote
,30000:192.168.1.3:22
同樣是指把對192.168.1.1的30000端口的訪問轉發到192.168.1.3的22端口,注意不要把這里的轉發端口當成是執行端口轉發命令的一方。最后的root@192.168.1.1
的解釋參考本地端口轉發部分。
測試隧道的連通性同本地端口轉發部分,在任意一個192.168.1.1的終端執行telnet localhost 30000
進行測試。
還有一件事,來看這種情況:192.168.1.1執行 ssh -L 30000:localhost:22 root@192.168.1.2
,這里不考慮轉發的合理性,只關注一件事:命令中的localhost
指的是誰,根據實際測試,上面命令中的localhost
指的是192.168.1.2;而如果192.168.1.1執行的是 ssh -R 30000:localhost:22 root@192.168.1.2
,情況是否相同呢?根據實際測試,這種情況下的localhost
指的是192.168.1.1。也就是說,如果是本地端口轉發,localhost
指的是接受ssh連接的一方;如果是遠程端口轉發,localhost
指的是發起ssh連接的一方(也就是執行端口轉發命令的一方)。更統一的說法是:不論本地端口轉發還是遠程端口轉發,localhost
都是指連通隧道兩端的那個主機。
[1] SSH, the Secure Shell, 2nd Edition (Barrett, Daniel J)-Chapter 9. Port Forwarding and X Forwarding[2] Ubuntu 防火墻命令(查看,關閉,啟動) 博客園[3] 如何列出和刪除防火墻規則UFW myfreax
關鍵詞:
版權與免責聲明:
1 本網注明“來源:×××”(非商業周刊網)的作品,均轉載自其它媒體,轉載目的在于傳遞更多信息,并不代表本網贊同其觀點和對其真實性負責,本網不承擔此類稿件侵權行為的連帶責任。
2 在本網的新聞頁面或BBS上進行跟帖或發表言論者,文責自負。
3 相關信息并未經過本網站證實,不對您構成任何投資建議,據此操作,風險自擔。
4 如涉及作品內容、版權等其它問題,請在30日內同本網聯系。