Skip to content

使用遠端 Windows 主機編譯 Docker Image - Cloudflare Tunnel 代理 SSH 實現篇

前情提要 ​

之前寫了一篇文章 使用 Windows 主機的 Docker Daemon 暴露給內網使用,當時的做法是在 Windows 安裝 Docker Desktop,更改 Docker Daemon 的設定將 port 2375 公開,然後使用 Windows 的防火牆規則做 Port Proxy 對外公開 2376 port轉發到內部的 2375 port,最後內網的開發機就可以直接透過 DOCKER_HOST=192.168... docker 指令讓運算力比較強大的 Windows 主機處理 Docker 編譯工作。

該方法存在幾個缺點:

  1. 雖然在內網,但沒有一個安全的認證機制,仍有安全疑慮,萬一內網被連上,任何人都可以使用你的 Docker host。
  2. 一旦離開內網,則無法從外部環境連回家裡的 Docker。

最近剛好要出國,希望在外地也能享受到家中 Windows 主機的運算能力,以減少 Docker Image 編譯的時間,所以研究了同時解決上面提到兩個問題的新方法,而這方法借助 Cloudflare Tunnel 強大的免費功能,輕鬆實現 SSH 反向代理。

使用 Cloudflare Tunnel 代理 Windows WSL 的 SSH ​

Windows 主機的步驟 ​

  1. 移除掉 Windows Docker Desktop,因為我們要改用 WSL Ubuntu 底下的 Docker。
  2. 執行 Powershell 運行指令 wsl --install -d ubuntu 安裝 Ubuntu Linux。
  3. 執行 wsl -d ubuntu 指令進入 WSL Ubuntu,運行以下指令:
    sh
    # 安裝 docker 及 openssh
    sudo apt install docker.io openssh-server
    
    # 把開發機的 public key 加入到 authorized_keys 檔案當中
    mkdir -p ~/.ssh/
    vim ~/.ssh/authorized_keys 
    
    # 安裝 cloudflared
    wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && sudo dpkg -i cloudflared-linux-amd64.deb
    
    # 登入 cloudflare
    cloudflared tunnel login

請先確保不要關閉指令視窗,接續後面的步驟,如果關閉了指令視窗,WSL 會隨之關機斷線。

使用 Cloudflare 網頁介面新增 Tunnel ​

接下來前往 Cloudflare 建立 Tunnel,選擇從網頁介面操作而不是 CLI 的原因是,透過 CLI 建立出來的 Tunnel 好像是舊版規格,最後還是得 migrate 到新版。

  1. 前往 Cloudflare 管理介面,點選左側 Zero Trust ⇒ Access ⇒ Tunnels。
  2. 建立一個新的 Tunnel,名稱不重要,之後可以改。
  3. 選擇 Debian 及 64bit 後會看畫面上提供一道安裝指令 cloudflared service install <token> ,將其複製貼到 Ubuntu 當中執行。
  4. 設定一個子網域,名稱隨意例如: vm.exmple.com 其中 example.com 會是你在 CF 所擁有的網域。 Service Type 選 SSH ,URL 寫 localhost:22 。
  5. 完成設定後,Tunnel 的狀態應為 HEALTHY 表示 Ubuntu 與 CF 之間的連線狀態是連線中的,表示步驟 3 的指令有安裝成功。

開發機的步驟 ​

  1. 同樣把 cloudflared 指令裝到開機上並完成登入。
  2. 於 ~/.ssh/config 加入以下設定:
text
Host x-machine
HostName vm.example.com
User your-username
ProxyCommand cloudflared access ssh --hostname %h

其中 vm.example.com 的設定需與 Tunnel 的 public hostname 相同, your-username 改為你 Ubuntu 的使用者名稱;而 x-machine 可隨意取個方便識別名稱,之後可以透過 ssh x-machine 的方式登入主機。 這段設定的關鍵處在於使用 cloudflared access ssh 指令來做 proxy ssh 的連線。 3. 使用 ssh x-machine 指令登入,如果成功,表示設定完成。 4. 於 ~/.zshrc 或其他你慣用的 shell 設定中加入 export DOCKER_HOST=ssh://x-machine。 5. 使用 . ~/.zshrc 重新載入 shell 設定。

執行 docker info 指令,如果得到回應,並且得到的是 Windows WSL 環境資訊,表示成功透過了 Cloudflare Tunnel 代理的 SSH 對遠端 docker 執行指令。 之後 docker 的所有指令都會運行在遠端 Windows 主機的 WSL 之下。

常駐運行 WSL ​

如果把 Windows 主機的 WSL session 關閉,WSL 就關機了,或是 Windows 主機重開機,WSL 也不會重新啟動,這樣就無法再次透過 Cloudflare Tunnel 連線到 WSL 了。

每次都得在 Windows 上開一個小黑窗運行 wsl ,以確保 WSL 運行非常麻煩,所以參考了這個方法,我們可以在 Windows 上新增一個 startwsl.cmd 的指令檔,內容如下:

powershell
wsl bash -c "nohup bash -c 'while true; do sleep 1h; done &' &>/dev/null "
timeout /t 3

按下 win + r 執行程式 shell:common startup 會開啟一個資料夾,將 startwsl.cmd 檔案放到這個資料夾中,之後每次開機登入 Windows 時,WSL 就會自動啟動。

使用 Cloudflare WARP ​

使用 ssh 或是 docker 指令的時候都會明顯感受到網路的延遲,一個加速的方法是使用 Cloudflare 免費 VPN,安裝啟動後要選擇有 WARP 的 1.1.1.1 with WARP,瞬間消除延遲問題。

結語 ​

  • 使用 Cloudflare Tunnel 代理 Windows WSL 的 SSH,讓開發機可以透過 SSH 連線到 Windows WSL。
  • 使用 export DOCKER_HOST=ssh://x-machine 讓開發機的 docker 指令一律透過 SSH 連線到 Windows WSL 的 docker daemon。

藉由 Cloudflare Tunnel 的反向代理,我們完全不需要知道 Windows 主機或 WSL 的 IP 也不需要設定各種防火牆規則,就可以輕鬆地在外部環境 SSH 至內網的主機,重點它是 WSL!本篇是以 Docker 使用情境為例做介紹,同樣地也可以應用其他支援 SSH 連線的情境,例如:SSH 至內網的 Git Server;也可以在 WSL 底下架設網站伺服器,然後一樣使用 Cloudflare Tunnel 的反向代理功能,從外部某個公開的網址 staging.example.com 連線到內網的 WSL 網站伺服器。 一台原本只用來玩遊戲的 Windows 主機,有了 WSL + Tunnel 後,瞬間變成輔助日常生產用途的利器。

Written By
YI FENG XIE
YI FENG XIE

Creative Problem Solver