SSH有三種埠轉發模式,本地埠轉發(Local Port Forwarding),遠端埠轉發(Remote Port Forwarding)以及動態埠轉發(Dynamic Port Forwarding)。對於本地/遠端埠轉發,兩者的方向恰好相反。動態埠轉發則可以用於科學上網。
SSH埠轉發也被稱作SSH隧道(SSH Tunnel),因為它們都是通過SSH登陸之後,在SSH客戶端與SSH服務端之間建立了一個隧道,從而進行通訊。SSH隧道是非常安全的,因為SSH是通過加密傳輸資料的(SSH全稱為Secure Shell)。
在本文所有示例中,本地主機A1為SSH客戶端,遠端雲主機B1為SSH服務端。從A1主機通過SSH登陸B1主機,指定不同的埠轉發選項(-L、-R和-D),即可在A1與B1之間建立SSH隧道,從而進行不同的埠轉發。
本地埠轉發
應用場景:
遠端雲主機B1執行了一個服務,埠為3000,本地主機A1需要訪問這個服務。
示例為一個簡單的Node.js服務:
var http = require('http');
var server = http.createServer(function(request, response)
{
response.writeHead(200,
{
"Content-Type": "text/plain"
});
response.end("Hello Fundebug\n");
});
server.listen(3000);
複製程式碼
假設雲主機B1的IP為103.59.22.17,則該服務的訪問地址為:http://103.59.22.17:3000
為啥需要本地埠轉發呢?
一般來講,雲主機的防火牆預設只開啟了22埠,如果需要訪問3000埠的話,需要修改防火牆。為了保證安全,防火牆需要配置允許訪問的IP地址。但是,本地公忘IP通常是網路提供商動態分配的,是不斷變化的。這樣的話,防火牆配置需要經常修改,就會很麻煩。
什麼是本地埠轉發?
所謂本地埠轉發,就是將傳送到本地埠的請求,轉發到目標埠。這樣,就可以通過訪問本地埠,來訪問目標埠的服務。使用**-L**屬性,就可以指定需要轉發的埠,語法是這樣的:
-L 本地網路卡地址:本地埠:目標地址:目標埠
複製程式碼
通過本地埠轉發,可以將傳送到本地主機A1埠2000的請求,轉發到遠端雲主機B1的3000埠。
# 在本地主機A1登陸遠端雲主機B1,並進行本地埠轉發
ssh -L localhost:2000:localhost:3000 root@103.59.22.17
複製程式碼
這樣,在本地主機A1上可以通過訪問http://localhost:2000來訪問遠端雲主機B1上的Node.js服務。
# 在本地主機A1訪問遠端雲主機B1上的Node.js服務
curl http://localhost:2000
Hello Fundebug
複製程式碼
實際上,-L選項中的本地網路卡地址是可以省略的,這時表示2000埠繫結了本地主機A1的所有網路卡:
# 在本地主機A1登陸遠端雲主機B1,並進行本地埠轉發。2000埠繫結本地所有網路卡
ssh -L 2000:localhost:3000 root@103.59.22.17
複製程式碼
若本地主機A2能夠訪問A1,則A2也可以通過A1訪問遠端遠端雲主機B1上的Node.js服務。
另外,-L選項中的目標地址也可以是其他主機的地址。假設遠端雲主機B2的區域網IP地址為192.168.59.100,則可以這樣進行埠轉發:
# 在本地主機A1登陸遠端雲主機B1,並進行本地埠轉發。請求被轉發到遠端雲主機B2上
ssh -L 2000:192.168.59.100:3000 root@103.59.22.17
複製程式碼
若將Node.js服務執行在遠端雲主機B2上,則傳送到A1主機2000埠的請求,都會被轉發到B2主機上。
遠端埠轉發
應用場景:
本地主機A1執行了一個服務,埠為3000,遠端雲主機B1需要訪問這個服務。
將前文的Node.js服務執行在本地,在本地就可以通過http://localhost:3000訪問該服務。
為啥需要遠端埠轉發呢?
通常,本地主機是沒有獨立的公網IP的,它與同一網路中的主機共享一個IP。沒有公網IP,雲主機是無法訪問本地主機上的服務的。
什麼是遠端埠轉發?
所謂遠端埠轉發,就是將傳送到遠端埠的請求,轉發到目標埠。這樣,就可以通過訪問遠端埠,來訪問目標埠的服務。使用**-R**屬性,就可以指定需要轉發的埠,語法是這樣的:
-R 遠端網路卡地址:遠端埠:目標地址:目標埠
複製程式碼
這時,通過遠端埠轉發,可以將傳送到遠端雲主機B1埠2000的請求,轉發到本地主機A1埠3000。
# 在本地主機A1登陸遠端雲主機B1,並進行遠端埠轉發
ssh -R localhost:2000:localhost:3000 root@103.59.22.17
複製程式碼
這樣,在遠端雲主機A1可以通過訪問http://localhost:2000來訪問本地主機的服務。
# 在遠端雲主機B1訪問本地主機A1上的Node.js服務
curl http://localhost:2000
Hello Fundebug
複製程式碼
同理,遠端網路卡地址可以省略,目標地址也可以是其他主機地址。假設本地主機A2的區域網IP地址為192.168.0.100。
# 在本地主機A1登陸遠端雲主機B1,並進行遠端埠轉發
ssh -R 2000:192.168.0.100:3000 root@103.59.22.17
複製程式碼
若將Node.js服務執行在本地主機A2上,則傳送到遠端雲主機A1埠2000的請求,都會被轉發到A2主機上。
動態埠轉發
應用場景:
遠端雲主機B1執行了多個服務,分別使用了不同埠,本地主機A1需要訪問這些服務。
為啥需要動態埠轉發呢?
一方面,由於防火牆限制,本地主機A1並不能直接訪問遠端雲主機B1上的服務,因此需要進行埠轉發;另一方面,為每個埠分別建立本地埠轉發非常麻煩。
什麼是動態埠轉發?
對於本地埠轉發和遠端埠轉發,都存在兩個一一對應的埠,分別位於SSH的客戶端和服務端,而動態埠轉發則只是繫結了一個本地埠,而目標地址:目標埠則是不固定的。目標地址:目標埠是由發起的請求決定的,比如,請求地址為192.168.1.100:3000,則通過SSH轉發的請求地址也是192.168.1.100:3000。
-D 本地網路卡地址:本地埠
複製程式碼
這時,通過動態埠轉發,可以將在本地主機A1發起的請求,轉發到遠端主機B1,而由B1去真正地發起請求。
# 在本地主機A1登陸遠端雲主機B1,並進行動態埠轉發
ssh -D localhost:2000 root@103.59.22.17
複製程式碼
而在本地發起的請求,需要由Socket代理(Socket Proxy)轉發到SSH繫結的2000埠。以Firefox瀏覽器為例,配置Socket代理需要找到首選項>高階>網路>連線->設定:
這樣的話,Firefox瀏覽器發起的請求都會轉發到2000埠,然後通過SSH轉發到真正地請求地址。若Node.js服務執行在遠端雲主機B1上,則在Firefox中訪問localhost:3000即可以訪問。如果主機B1能夠訪問外網的話,則可以科學上網…...
鏈式埠轉發
本地埠轉發與遠端埠轉發結合起來使用,可以進行鏈式轉發。假設A主機在公司,B主機在家,C主機為遠端雲主機。A主機上執行了前文的Node.js服務,需要在B主機上訪問該服務。由於A和B不在同一個網路,且A主機沒有獨立公共IP地址,所以無法直接訪問服務。
通過本地埠轉發,將傳送到B主機3000埠的請求,轉發到遠端雲主機C的2000埠。
# 在B主機登陸遠端雲主機C,並進行本地埠轉發
ssh -L localhost:3000:localhost:2000 root@103.59.22.17
複製程式碼
通過遠端埠轉發,將傳送到遠端雲主機C埠2000的請求,轉發到A主機的3000埠。
# 在A主機登陸遠端雲主機C,並進行遠端埠轉發
ssh -R localhost:2000:localhost:3000 root@103.59.22.17
複製程式碼
這樣,在主機B可以通過訪問http://localhost:3000來訪問主機A上的服務。
# 在主機B訪問主機A上的服務
curl http://localhost:3000
Hello Fundebug
複製程式碼
參考連結
關於Fundebug
Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了6億+錯誤事件,得到了Google、360、金山軟體等眾多知名使用者的認可。歡迎免費試用!
版權宣告:
轉載時請註明作者Fundebug以及本文地址:
blog.fundebug.com/2017/04/24/…