Contents

SSH Tunnel 三種方式備忘錄

最近要連某一台主機上的 Transmission 管理介面,Port 是 9091,但主機本身沒有直接對外開放這個 Port,所以最後還是得靠 SSH Tunnel 裡最常見的 Local Port Forwarding 來處理。

這個功能我以前就知道,只是通常久久才會用一次。每次要用的時候,又得重新想一次 -L-R-D 到底差在哪裡。既然這次剛好重新整理,就乾脆把重點記下來,之後自己複習也比較快。

先講在前面
如果你想看非常完整、圖解很多的版本,我還是推薦這篇:SSH Tunneling (Port Forwarding) 詳解 · John Engineering Stuff。這篇文章主要是整理我自己最常用、最容易忘的重點,方便之後快速回頭查。

文章重點心智圖

mindmap root((SSH Tunnel 三種方式)) Local Port Forwarding 本機連遠端內網服務 最常用 瀏覽器或工具接 localhost Remote Port Forwarding 把本機服務反向暴露到遠端 常受安全限制 需要注意 GatewayPorts Dynamic Port Forwarding 建立 SOCKS 代理 瀏覽器與工具可走代理 適合臨時跳板使用 核心觀念 透過 SSH 建立安全通道 中間通常有一台 SSH Server 重點是搞懂來源與目的地

先理解前提

SSH Tunnel 的核心概念,其實就是透過一台可以 SSH 連線的主機,幫兩個原本無法直接互通的環境建立通道。

實務上你可以把它想成這樣:

  1. 你手上有一台可以連上的 SSH Server,通常是跳板機、遠端主機,或某台有對外開放 SSH 的機器。
  2. 你想存取的真正目標服務,可能只開在內網,或只綁在 localhost,外部碰不到。
  3. 這時就靠 SSH Tunnel 把流量從一端安全地轉到另一端。
一句話記法
先不要背指令,先搞懂「誰發起連線、流量要送去哪裡、哪一端要開 Port 給誰用」,這樣看 -L-R-D 會輕鬆很多。

三種方式常見情境

  1. Local Port Forwarding:自己的電腦想連遠端內網服務。
  2. Remote Port Forwarding:想讓遠端主機反向連回自己這端的服務。
  3. Dynamic Port Forwarding:直接把 SSH 連線變成 SOCKS 代理來使用。

如果硬要一句話總結,這三種都是「透過 SSH,把原本不能直接連的流量轉過去」,差別只是 Port 開在哪一端、給誰用而已。

Local Port Forwarding

這是我自己最常用的一種。典型場景就是:我自己的電腦,想去連遠端機器上的某個服務,但那個服務沒有直接對外開放。

https://gist.github.com/user-attachments/assets/7603a54e-9710-4f1b-aae1-68ab81d21d0d

基本指令

1
ssh -L [bind_address:]<port>:<host>:<host_port> <SSH Server>

我以前看到這個格式也常常頭很痛,後來比較容易記的方式是:

本機要開的 Port透過 SSH Server 幫你轉到哪個 host:port

我的使用範例

假設遠端主機有開 SSH Port 37022,而且 Transmission 只綁在遠端的 localhost:9091,那可以這樣下:

1
ssh -p 37022 -L 9091:localhost:9091 user@domain-or-ip

這時你在自己電腦打開瀏覽器,直接開 http://localhost:9091,就會連到遠端那台機器上的 Transmission 介面。

bind_address 代表什麼

上面的範例省略了 [bind_address:],等同只綁在本機 localhost,也就是只有你自己這台電腦能使用這個轉發 Port。

如果你真的想讓同網段其他機器也能透過你這台電腦使用,就可以明確指定 0.0.0.0

1
ssh -p 37022 -L 0.0.0.0:9091:localhost:9091 user@domain-or-ip
這裡不要亂開
0.0.0.0 代表你的本機會對外開一個可被其他人連到的 Port。除非你很清楚自己所在的網路環境與風險,不然一般情況只綁 localhost 就夠了。

Remote Port Forwarding

Remote Port Forwarding 則是反過來,把你這一端的服務,暴露到遠端 SSH Server 那邊。

1
ssh -R [bind_address:]<port>:<host>:<host_port> <SSH Server>

這裡最容易搞混的是:bind_address 指的是 SSH Server 那一端要綁定的位址,不是你本機。

常見情境

例如你本機有一個只開在 localhost:80 的測試網站,但你想讓遠端主機可以連回來看,就可以這樣做:

https://gist.github.com/user-attachments/assets/ee910090-6611-4a1b-b570-5113e56c4d50

1
ssh -R 2121:localhost:80 user@192.168.50.212

這代表你登入 192.168.50.212 後,在那台遠端主機上打 curl localhost:2121,就會連回你這台電腦的 localhost:80

轉到其他主機也可以

<host>:<host_port> 不一定非得是你本機,也可以指定其他主機,例如:

1
ssh -R 9090:tw.yahoo.com:80 user@192.168.50.212

這樣在遠端主機上執行:

1
curl localhost:9090

就能拿到 tw.yahoo.com:80 的 HTML 內容。

要讓遠端其他人也能連,需要 GatewayPorts

基於安全考量,Remote Forwarding 預設通常只會綁在 SSH Server 的 localhost,所以單靠下面這種指令:

1
ssh -R 0.0.0.0:9090:localhost:80 user@192.168.50.212

很多時候還是不會真的讓外部主機連進來。你還需要調整 SSH Server 上的 sshd_config,通常在 /etc/ssh/sshd_config,加入:

1
GatewayPorts yes

這個設定常見有三種:

  1. no:預設值,只允許綁在 localhost
  2. yes:允許綁到萬用位址,例如 0.0.0.0
  3. clientspecified:讓 Client 自己決定要綁在哪個位址。
我自己比較少用這個
這種做法雖然很強,但安全風險也高。很多情況下,如果真的要對外提供服務,我反而會優先考慮反向代理、VPN,或直接調整正式的網路架構,而不是讓使用者透過 -R 臨時開洞。

Dynamic Port Forwarding

Dynamic Port Forwarding 可以把 SSH 連線直接變成一個 SOCKS Proxy,這個在臨時代理流量時滿方便。

這種方式的感覺
可以把它想成:先 SSH 到某台能上外網或能進特定網段的主機,再讓自己的瀏覽器或工具把流量丟進這個 SOCKS 代理。

指令

1
ssh -D 9090 user@host.domain

如果只是單純開代理、不需要進互動式 shell,也可以加上 -N

1
ssh -N -D 9090 user@host.domain

測試方式

1
2
3
4
5
# 不走代理
curl https://ifconfig.me

# 走 SOCKS5 代理
curl --socks5 127.0.0.1:9090 https://ifconfig.me

如果兩次拿到的出口 IP 不同,就代表代理有正常生效。

瀏覽器設定重點

各家瀏覽器都能設代理,但這裡最重要的一點只有一個:要選 SOCKS 代理,不是一般的 HTTP 代理。

Firefox:

https://gist.github.com/user-attachments/assets/4542fad2-93ed-4d29-acb3-820cc3ae492f

Windows 11 下的 Chrome、Edge 因為共用系統代理,設定時要特別注意 socks=127.0.0.1 這類格式。我當初找這個點卡了滿久,真的有點雷。

https://gist.github.com/user-attachments/assets/f0e29d95-5272-437d-ac7b-3d758f20f5bc

參考資料:How can I set socks proxy on windows? - Super User

設定好之後,可以直接打開 https://ifconfig.me 看出口 IP 有沒有變化。

三種方式快速比較

方式 典型用途 Port 開在哪裡 我自己使用頻率
-L 本機連遠端內網服務 本機
-R 讓遠端反向連回本機或其他位置 遠端 SSH Server
-D 建立 SOCKS 代理 本機

我的看法

這三種方式,說穿了就是把兩個隔離環境,透過一台有 SSH 的中介主機串起來。

如果以我自己的實用度來排,大概會是:Local Port Forwarding > Dynamic Port Forwarding »»» Remote Port Forwarding

Local Port Forwarding 真的最常見,因為太多內網服務都只有 SSH 能進、服務本身不會直接開給外部。Dynamic Port Forwarding 也很好用,尤其你只是暫時需要代理流量時,很省事。至於 Remote Port Forwarding,不是不能用,而是它通常牽涉到更高的權限與安全風險,所以我自己會比較保守。

另外,SSH 權限真的不要隨便開放給一般使用者。因為一旦能建立 Tunnel,本質上就等於多了一種繞過原本網路限制的手段。功能很方便,但權限控管一定要更小心。

更多參考資料

之後如果又忘記 -L-R-D 差在哪裡,我應該會先回來看這篇,而不是再從頭 Google 一次。