SSH Tunneling Remote Port Forwarding

問題描述

在研究ESL電子標籤時,了解到這個應用的架構是由基站與標籤兩種部件所組成,因為兩者間的通訊是透過2.4GZH來進行,通常是一部基站管理一個區域的多個標籤,然後應用程式會透基站提供的 API 來進行標籤的管理。
這次專案中使用的基站被要求使用 Private IP,但是公司的應用程式是 SaaS 服務,也就是說我們必須從外部(Cloud 的 Public IP)來呼叫基站的 API(Private IP),這時候就需要透過 SSH Tunneling Remote Port Forwarding 來達成,當然也還有別的方式,下面會再舉一個例子。

解決方法

方法一:DDNS 服務

  1. 將基站安裝在一部分享器下,並將分享器的 Public IP 與 DDNS 綁定,並設定 Port Forwarding 將基站的 Private IP 與 Port 轉發到 Public IP 與 Port,這樣就可以從外部透過 DDNS 來呼叫基站的 API。
  2. 若有多個基站,則可以將基站的 Private IP 與 Port 轉發到不同的 Port。
  3. 缺點是,你必須要有一台可以安裝基站的分享器,且分享器必須要有 Public IP,以用來綁定 DDNS 的 Domain。

方法二:透過 SSH Port Fortwarding

  1. 在基站同一個 Private IP 網段內設置一部電腦,而這部 Client 電腦必須要能夠連接到 Internet。
  2. 在 Cloud 上設置一部主機來運行 Nginx,我們會將這部主機稱為 Proxy,並新增設定檔 /etc/nginx/site-enabled/proxy,內容如下:
    1
    2
    3
    4
    5
    6
    7
    server {
    listen 80;
    server_name <your_domain>;
    location / {
    proxy_pass http://localhost:<service_port>/;
    }
    }
    存檔後,重啟 Nginx 服務。
  3. 而 your_domain 的 DNS 設定,要做一個 A record 指向 Proxy 的 Public IP。
  4. 在 Client 電腦上設置 SSH Tunneling Remote Port Forwarding,指令如下:
    1
    $ ssh -R <service_port>:基站_ip:<service_port> <user>@<proxy_ip>
    這樣就可以從外部透過 your_domain 連接到 Proxy 的 Public IP 來呼叫基站的 API,這樣的好處是 Client 的 Public IP 可以是固定的也可以是浮動的,ssh tunnel 建立後, your_domain 就會對應到 Client 電腦來進行 port forwarding,這就像是 ngrok 的服務原理一樣。
  5. 缺點就是有點複雜,準備工作比較多,但是一但設置好後,就可以很方便做這一類的應用,在 local 端測試的時候經常會用到。

參考資料

方法二是基本的概念說明,實際上如果需要使用到 https 的話,可以在 Proxy 上透過 Certbot 來產生 SSL 憑證,一樣可以打到 local 端,像是在做 FB Login 的時候,有限制 webhook 只能是 https 的網址,這時候就可以透過這個方法來達成。
另外如果是多個基站的話,可以利用 uri 導向不同的 port,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name <your_domain>;
location / {
proxy_pass http://localhost:<service_port>/;
}
location /api1 {
proxy_pass http://localhost:<service_port1>/;
}
location /api2 {
proxy_pass http://localhost:<service_port2>/;
}
}

不過這都是在開發過程中會遭遇到的問題,實際上在正式產品環境中,應該會讓基站維持在 Private 網段,而應用程式應該會透過 VPN 或是 middleware server 來進行連線,這樣就不會有這種問題了。

SSH Tunneling Remote Port Forwarding

Port Forwarding