【Linux】SSH 大小事(一) Local Port Forwarding

Jimmy Yeh
6 min readSep 19, 2022

--

前言:
近期接觸到一些以前沒使用過的 SSH 指令。透過這些指令可以讓我們的 remote server 更加安全。這系列預計會至少三篇,分別針對 SSH Port Forwarding 的三種模式來實作並說明。

使用情境: 我們常常在雲端的 VM 上啟動一些服務(如 API/MySQL 等)。當我們想把這些服務開放出去給外部連線使用時,會面臨到網路防火牆的問題。但並不是所有服務都需要且適合把防火牆打開,針對不同的服務會有不同的情境需要處理。

  • API 服務需要開啟防火牆、CORS 管理、Auth 機制(甚至 IP 白名單)。
  • Web 服務可能就會需要讓多數用戶都可以存取。
  • MySQL/Redis 等服務就不會需要去做外部存取,內部服務能夠連線即可。

接下來的例子,就針對第三種情形去做討論。試想,當我們今天想查看 remote Redis 的資料,最簡單直覺的方式當然就是直接把 port 打開,並且在 local 端安裝相關 GUI 或 Redis-CLI,接著透過 IP:Port 去連線去做存取。但這在安全性上會有很大的問題,任何知道 IP 及 port 的人都可以去做連線,即使加上了 IP 白名單也還是有很大的風險。 因此,我們可以採用 Port Forwarding 的方式,透過 SSH 連線到 remote server 的服務上。下圖為實際上伺服器的情形,我們只有開放 22 port 給 SSH 連線,但我們要透過 22 port 繞到內部的其他服務。

實作:
一、前置作業
Step1.
先到雲端上面開一台機器,並且把 22 port 開放出來,這邊我使用的是 GCP

如果要開 SSH 建議一定要把 22 port 換掉, 這邊因為示範就不特別去做調整

Step2.
連線到遠端機器設定 SSH 權限後,確認自己本地機器可以 SSH到遠端機器

Step3. 安裝 docker(方便接下來開服務做使用)
Step4. 在 remote server 上面使用 docker 啟動一個 redis 服務,並且把 port開放出來

redis原生port為6379,這邊為了方便分別,所以開放出來的port改為6380

Step5. 進到redis內, 新增幾筆資料供測試使用

這邊在 docker exec 後可以直接使用 redis-cli 進到 local 端的 redis,就不必先用 bash再下 redis-cli

二、實作 port forwarding
Step1.
在 local 端也啟動一個 docker redis (目的只是為了 redis-cli , 或是要直接裝redis-cli 套件也可)

這裡我們待會要 remote server的 redis,所以先使用bash,待會要搭配完整的 redis-cli 指令

Step2.
開啟一個新的視窗,執行 SSH local port forwarding 指令
ssh -L 0.0.0.0:本地port:localhost:遠端port user@ssh-server-ip

實際上指令如下
ssh -L 0.0.0.0:6381:localhost:6380 user@ssh-server-ip

  • 6381 為 local 要使用的 port
  • 6380為 remote server 的 port
  • 0.0.0.0 的目的是因為我們待會要使用 docker 內的 redis-cli,因此要開放給本地其他服務去做讀取
  • localhost 代表的是 remote server 指向它的本地端

此時我們會看到畫面出現一個看起來像實際 SSH 到 server 的視窗, 但實際上我們已經做完 port forwarding 的動作,所以千萬不要把視窗傻傻關掉XD

看起來跟一般 ssh 沒兩樣

Step3.
查看本地的內部 IP

Step4.
回到local的 redis-cli 嘗試進行遠端連線
redis-cli -h ip -p port

大功告成!正確且順利的存取到遠端的redis

此時我們需要顧好的唯一入口就是 SSH 的 port,如果想加強ssh的防護性, 可以參考網路上其他的 SSH 防護方法,不是本文重點,就不多做贅述

如果搭配 SSH config 可以這樣寫:

Host remote-server
HostName 123.45.67.89
Port 22
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa
User jimmyyeh
LocalForward 0.0.0.0:6381 localhost:6380 # 重點在這一行

如果把 MySQL 接出來,就可以讓習慣使用 GUI 的人,搭配 PHPMyAdmin 或是其他 GUI 來使用。 而 Local Port Forwarding 的功能當然不只這樣。有時候可以再搭配其他的方式,例如將 Remote Server 的 localhost 改成該 Server 可存取的其他機器內部 IP,去讓這一台開放 SSH 的 Remote Server,做到 VPN Tunnel 的效果。這邊只是提供一個簡單的範例來實作。

以上就是 Local Port Forwarding 的實作紀錄,參考這一篇文章寫得蠻清楚的。實際說明可以參考該篇文章。

Reference:
SSH Tunneling (Port Forwarding) 詳解 · John Engineering Stuff (johnliu55.tw)

--

--