【學記】SSH Tunneling
What is SSH Tunneling?
網路的連線由 2 個端點組成,而連線中經常會經過 untrusted networks(例如 internet),其中的資料傳輸就不安全,可能會有被偷窺,甚至收到錯誤資料的風險,tunneling 技術就是為此而生。
Tunneling 指的是將網路上的 2 個端點用某種方式連接起來,形成一個隧道,而 SSH tunneling 就是用 SSH protocol 建立隧道,不但能加密通訊,即便中間有設下防火牆或者要連上在別的內網的機器,SSH tunneling 都能建立連線。
舉例而言,今天有個 web server 建立在 remote server 的 9000 port,而該 server 並沒有 external IP,而是需要透過 jump host 才能連上。
我們可以透過 SSH 的 port forwarding 來建立一個在自己的 machine 與 remote server 間的 tunnel,如此一來便能連上架設在 remote server 上的 web server
Type of port forwarding
port forwarding 可以分為:
- Local port forwarding
- Remote port forwarding
- Dynamic port forwarding
以下將分別介紹各個 port forwarding 的使用方式以及使用場景。
Local port forwarding
command
Local port forwarding 的指令格式如下:
1 | ssh -L [bind_address:]local_port:host:remote_port user@remote-server |
注意 host address 是對於 remote-server 的 address,因此若 host 為 localhost 則是指 remote-server 自己。
假設我們要將 local 的 9090 port forward 到 remote server 的 8080 port,指令如下:
1 | ssh -L 9090:localhost:8080 user@remote-server |
即在 client 上開啟 9090 port 等待連線,當有人連上時,將所有的資料送到 remote-server:8080,也就是將 request 導向 server 上。
scenario
SSH local port forwarding 的使用情境為何?讓我們看一個例子。
假設在 server 的 8080 port 架有一個 website,而該 server 需要透過 jump host 才能連上(也就是沒有 external IP),若我們想要在自己電腦的瀏覽器 access 該 website,可以怎麼做呢?
首先,設定 SSH 讓自己的電腦可以透過 SSH 連上 remote server,可以透過編輯 ~/.ssh/config 設定使用 jump host,而這並不是本篇學記的重點,因此不多著墨。
目前的 ~/.ssh/config 如下:
1 | Host jumpHost |
測試連線:
1 | ssh remoteServer |
local port forwarding:
1 | ssh -L 9090:localhost:8080 remoteServer |
此時當我們在瀏覽器打開 localhost:9090,會將瀏覽器的連線請求導向 remote server 的 8080 port,也就是該網頁架設的地點,如此一來我們便可以透過 ssh port forwarding 連上原本無法連上的服務。
Remote port forwarding
Remote port forwarding 的指令、使用方法與場景跟 local port forwarding 類似。
command
Remote port forwarding 的指令格式如下:
1 | ssh -R [bind_address:]port:host:host_port user@remote-server |
注意 host address 是對於 client 的 address,因此若 host 為 localhost 的話則是你的電腦自己。
假設我們要將 remote server 的 8080 port forward 到自己的 9090 port,指令如下:
1 | ssh -R 0.0.0.0:8080:localhost:9090 user@remote-server |
即當有人連線到 remote server 的 8080 port,將所有的資料送到你電腦的 9090 port 上,此時若你的電腦有 web server 架設在 9090 port,便可以收到該資料。
綜上,我們可以看出 remote 跟 local port forwarding 的差別在於 service 架設在哪裡,在自己的電腦要給別人連線(remote port forwarding)或是在 server 上,要用自己電腦的瀏覽器連線(local port forwarding)。
scenario
Remote port forwarding 的使用情境,我們看以下的例子。
假設我要在自己的電腦上架設一個 web server(9090 port),而不想直接暴露自己的 IP,要求 user 透過 ssh server 連線,此時我們可以透過以下指令將 ssh server 的 8080 port forward 到我的 9090 port:
1 | ssh -R 8080:localho:9090 user@remote-server |
此時當 user 連線上 remote server 的 8080 port,我架設在我電腦 9090 port 的 web service 便會收到 request,因為我透過 remote port forwarding 將 remote server 的 8080 port 上的所有資料送到我電腦上的 9090 port 了。
Demo
我前幾天想要查看在 remote server 上的 prometheus 資料,該 server 需要透過多層 jump host 才能連上,但我又想要在自己電腦的瀏覽器上查看 grafana dashboard(一個資料視覺化的工具,有支援 prometheus)。此時可以透過 local port forwarding 將 local 的 9000 port forward 到 remote 的 9000 port,再將架設在 remote server 的 kubernetes cluster 中的 grafana port forward 到 remote server 的 9000 port,這樣一來所有連線請求送到我電腦的 9000 port 就會被 forward 到執行 grafana 的 container 上,因此就可以看到 grafana 的資料了!
local port forwarding:
1 | ssh -L 9000:localhost:9000 remoteServer |
kubernetes port forward:
1 | kubectl port-forward svc/prometheus-grafana 9000:90 |
90 port 是透過 kubectl get svc 查看得知。
打開瀏覽器連線 localhost:9000:















