你好!你對使用 SSH 的遠程訪問世界感到興趣嗎?在之前的文章中,我們討論了 SSH 密鑰生成、基本連接命令以及本地端口轉發(-L 選項)。這次我們將專注於 SSH 的另一個強大功能:反向端口轉發(Reverse Port Forwarding),也就是 -R 選項。

如果 -L 選項是「從我的電腦建立通道以訪問外部資源」,那麼 -R 選項則是相反的。它允許「從外部電腦建立通道以訪問我的電腦的內部資源」,就像在牆上開一扇門一樣。


什麼是反向端口轉發?(-R 選項概述)

一般來說,從遠程服務器(Server A)直接連接到本地電腦(Client B)是困難的。這主要是因為 Client B 常常使用私有 IP 地址或位於防火牆後面,或沒有固定 IP。

在這種情況下,使用反向端口轉發(-R 選項),Client B 向 Server A 嘗試 SSH 連接的同時,還能在 Server A 上建立通道,將進入 Server A 的特定端口的請求轉發到 Client B 的特定端口

簡單來說:

  1. Client B(我的電腦)Server A(外部伺服器) 嘗試進行 SSH 連接。
  2. 此時使用 -R 選項來命令「請把來自 Server A 的 X 號端口的請求發送到我的電腦(Client B)的 Y 號端口!」
  3. 現在,另一個連接到 Server A 的外部用戶如果訪問 Server A 的 X 號端口,該請求將通過 SSH 通道轉發到 Client B 的 Y 號端口

這就像是 Client B 向 Server A 請求「幫我開一扇可以連接到我的門」

SSH 反向端口轉發流程圖:外部請求通過伺服器傳遞到本地的結構


-R 命令的組成

反向端口轉發的基本命令格式如下:

ssh -R [遠程_端口]:[目標_主機]:[目標_端口] [遠程_伺服器_用戶]@[遠程_伺服器_地址]

讓我們仔細看看每個元素:

  • ssh:執行 SSH 客戶端的命令。
  • -R:反向端口轉發選項。
  • [遠程_端口]:要打開的 遠程伺服器(Server A)的端口號。當外部用戶訪問此端口時將連接到 Client B 的資源。
  • [目標_主機]:當 [遠程_伺服器_用戶]@[遠程_伺服器_地址] 連接時,Client B(我的電腦)內部要訪問的資源的主機名稱或 IP 地址。通常是 localhost(即 Client B 自己)。
  • [目標_端口]Client B(我的電腦)內部運行的服務的端口號。外部請求最終到達的地方。
  • [遠程_伺服器_用戶]@[遠程_伺服器_地址]:要連接的 外部伺服器(Server A)的用戶帳戶和地址。是 Client B 連接到 Server A 的路徑。

示例:

當我想從我的本地電腦(Client B)的 8080 端口訪問外部伺服器(Server A)上的 8888 端口時:

# 在 Client B(我的電腦)上執行
ssh -R 8888:localhost:8080 user@server_a_public_ip

如果這條命令成功執行,則會以 SSH 方式連接到 server_a_public_ip。此時,從其他計算機訪問 http://server_a_public_ip:8888,實際上是訪問 Client B(我的電腦)的 8080 端口。


反向端口轉發在哪些情况下有用?(在開發過程中的應用)

反向端口轉發在某些特定情況下非常強大,這些情況通常無法通過普通的 SSH 連接解決。尤其在開發過程中,可以很有用。

1. 將位於 NAT/防火牆後的本地開發伺服器公開

  • 問題情況:假設你在家或公司內部網絡中開發了一個 Web 應用程序(例如:在 localhost:3000 上運行),你希望向外部的團隊成員或客戶展示這個應用程序,但由於本地電腦使用私有 IP,無法直接從外部訪問。路由器或公司防火牆的設置又很複雜,需要管理員批准。
  • 解決方案:可以通過擁有公共 IP 的外部伺服器(例如 AWS EC2 實例或 VPS)來暴露本地開發伺服器。
# 在我的本地開發機(Client B)上執行
ssh -R 80:localhost:3000 your_user@your_public_server.com
# 或者由於 80 端口需要 root 權限,可以使用其他端口(例如:8080)
ssh -R 8080:localhost:3000 your_user@your_public_server.com
之後,訪問 `your_public_server.com:8080` 時,實際上會訪問你本地機器上運行的 Web 應用程序(`localhost:3000`)。這樣,外部人員可以實時查看你的開發進度。

2. 測試 Webhook

  • 問題情況:你希望在本地開發伺服器上測試來自支付系統、Git 存儲庫(GitHub/GitLab)、消息平台等的 Webhook 事件。然而,Webhook 只能發送到公共 URL。
  • 解決方案:通過反向端口轉發,可以將本地 Webhook 端點(例如:localhost:5000/webhook)映射到公共伺服器的特定 URL。
# 在我的本地開發機(Client B)上執行
ssh -R 5000:localhost:5000 your_user@your_public_server.com
現在在 Webhook 設定中輸入 `http://your_public_server.com:5000/webhook`,Webhook 事件將被傳遞到你的本地伺服器,可以進行測試。

3. 直接訪問遠程伺服器的特定端口(穿越安全網絡)

  • 問題情況:假設你想直接訪問位於遠程伺服器(Client B)上的數據庫或內部管理工具(例如:在 localhost:9000 上運行),但是由於防火牆限制外部訪問某個特定端口或該伺服器位於私有網絡。不過 Client B 可以通過 SSH 連接到外部的公共伺服器(Server A)。
  • 解決方案:Client B 向 Server A SSH 連接的同時,請求反向端口轉發,並告訴 Server A「幫我建立一條連接到我的 9000 端口的通道」。
# 在 Client B(防火牆後的伺服器)上執行
ssh -R 9000:localhost:9000 your_user@server_a_public_ip
現在,當你從你的計算機(或其他外部計算機)訪問 `server_a_public_ip:9000` 時,就能訪問 Client B 的 9000 端口服務。

4. 臨時展示或共享

  • 問題情況:假如你想向同事展示你本地運行的某個應用程序的工作方式,或想臨時地公開給外部人員以獲取反饋。
  • 解決方案:通過簡單的反向端口轉發,可以在特定期間內將本地服務暴露給外部。演示結束後,可以關閉 SSH 會話來阻止訪問,這非常方便。

使用反向端口轉發時的注意事項

  • GatewayPorts yes:通過反向端口轉發開放的遠程端口默認僅能從執行 SSH 伺服器(server_a_public_ip)的機器上訪問。如果要讓 SSH 伺服器外的其他計算機也能訪問此端口,需要在 SSH 伺服器的 sshd_config 文件中添加 GatewayPorts yes 設置並重啟 SSH 服務。(此設置可能會影響安全性,請小心使用。)

  • 安全性:反向端口轉發將本地網絡的特定端口暴露給外部,所以,必須僅在可信的伺服器上使用。必須提前檢查暴露的服務的安全漏洞。

  • 保持 SSH 會話:反向端口轉發通道僅在 SSH 會話保持的期間有效。要使其在背景中繼續運行,通常會使用 ssh -fN -R ... 來同時使用 f(在背景運行)和 N(不執行遠程命令)選項。


總結

SSH 反向端口轉發(-R 選項)在複雜的網絡環境或防火牆後需要將特定服務暴露給外部時非常有用。特別是在開發過程中,將本地環境與外部共享或進行 Webhook 測試時,這將成為強大的生產力工具。

如果這個概念讓你難以理解,實際嘗試一次並體會是最好的。積極利用 SSH 反向端口轉發來提升你的開發工作流程吧!

如果有任何疑問,請隨時在評論中詢問!