使用遠端 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,運行以下指令:
     # 安裝 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 TrustAccessTunnels
  2. 建立一個新的 Tunnel,名稱不重要,之後可以改。
  3. 選擇 Debian64bit 後會看畫面上提供一道安裝指令 cloudflared service install <token> ,將其複製貼到 Ubuntu 當中執行。
  4. 設定一個子網域,名稱隨意例如: vm.exmple.com 其中 example.com 會是你在 CF 所擁有的網域。 Service TypeSSH ,URL 寫 localhost:22
  5. 完成設定後,Tunnel 的狀態應為 HEALTHY 表示 Ubuntu 與 CF 之間的連線狀態是連線中的,表示步驟 3 的指令有安裝成功。

開發機的步驟

  1. 同樣把 cloudflared 指令裝到開機上並完成登入。
  2. ~/.ssh/config 加入以下設定:
      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 的指令檔,內容如下:

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, 安裝啟動後要選擇有 WARP1.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 後,瞬間變成輔助日常生產用途的利器。

留言