SSH Tunnel (Port Forwarding) 詳解

SSH 不只能用來遠端登入,它還有一個超強大的功能叫做 SSH Tunnel (通道),或是 Port Forwarding (連接埠轉發)

它可以讓你透過加密的 SSH 連線,將「本機的某個 Port」映射到「遠端的某個 Port」,或是反過來。這在穿越防火牆、連線內網服務(如 MySQL、Redis)或臨時架設 VPN 時非常有用。

有三種最常用的模式:Local (-L)、Remote (-R)、Dynamic (-D)。

1. Local Port Forwarding (-L)

場景:你想從本機連線到遠端伺服器 (Server A) 內部網路的資料庫 (Database B),但資料庫只允許內網連線。

簡單說就是:把遠端的東西拉回來本機用

# 語法:ssh -L [本機IP]:[本機Port]:[目標IP]:[目標Port] [跳板機User]@[跳板機IP]

ssh -L 3306:localhost:3306 user@remote-server.com
  • 這行指令的意思是:「在我的電腦開一個 3306 Port,當我連線到 localhost:3306 時,請透過 remote-server.com 幫我轉送到它自己 (localhost) 的 3306 Port」。
  • 現在,你只要連線本機的 3306,就像是在連線遠端的 MySQL 一樣!

進階用法:連線到遠端的內網其他機器

# 透過 remote-server 連線到它內網的 192.168.1.50 的 80 Port
ssh -L 8080:192.168.1.50:80 user@remote-server.com

現在打開瀏覽器 http://localhost:8080,就能看到那台內網機器的網頁了。

2. Remote Port Forwarding (-R)

場景:你在本機開發的一個網頁,想給遠端的朋友(或是 Internet 上的人)看,但你的電腦在內網沒有 Public IP。

簡單說就是:把本機的東西推給遠端用

# 語法:ssh -R [遠端IP]:[遠端Port]:[本機IP]:[本機Port] [遠端User]@[遠端IP]

ssh -R 8080:localhost:80 user@remote-server.com
  • 這行指令的意思是:「在 remote-server.com 上開一個 8080 Port,當有人連線到 remote-server.com:8080 時,請轉送到我這台電腦 (localhost) 的 80 Port」。
  • 如果遠端伺服器有 Public IP,現在全世界都可以透過 http://remote-server.com:8080 看到你的網站了!
注意: 預設 SSH Server (sshd_config) 的 GatewayPorts 通常是 no,這會導致 -R 監聽的 Port 只允許 localhost (127.0.0.1) 連線。如果要讓外網連線,必須在遠端伺服器的 /etc/ssh/sshd_config 設定 GatewayPorts yes 並重啟 sshd。

3. Dynamic Port Forwarding (-D)

場景:你想透過遠端伺服器上網(隱藏 IP、翻牆、繞過公司防火牆)。這就是簡易版的 VPN (SOCKS5 Proxy)。

# 語法:ssh -D [本機Port] [遠端User]@[遠端IP]

ssh -D 1080 user@remote-server.com
  • 這會在你的電腦開一個 1080 Port (SOCKS Proxy)。
  • 接著去瀏覽器或網路設定,將 SOCKS5 Proxy 指向 127.0.0.1:1080
  • 之後你的所有上網流量都會「鑽」進 SSH 通道,從 remote-server.com 出去。

實用技巧

不執行指令 (-N)

通常我們建立 Tunnel 只是為了轉發封包,不需要真的登入 Shell 打指令。加上 -N 可以只建立連線不開啟 Shell。

ssh -N -L 3306:localhost:3306 user@remote-server.com

背景執行 (-f)

搭配 -N 使用,讓 SSH 連線建立後直接在背景執行。

ssh -f -N -L 3306:localhost:3306 user@remote-server.com

斷線自動連線 (Autossh)

SSH 連線久了可能會斷掉。如果你需要長時間維持通道,建議安裝 autossh 工具,用法跟 ssh 幾乎一樣,但斷線會自動重連。

autossh -M 0 -f -N -L 3306:localhost:3306 user@remote-server.com