Enter your email address below and subscribe to our newsletter

使用 Cloudflare Tunnel 建立穩定的 SSH 遠端連線

在實務維運中,SSH 幾乎是所有 Linux 管理工作的基礎。然而,當主機沒有固定 IP、位於 NAT 環境,或基於安全考量不希望對外開放 22 Port 時,Cloudflare Tunnel(cloudflared) 成為一個非常理想的解決方案。

不過,許多人在使用 Cloudflare Tunnel 承載 SSH 時,常會遇到一個問題:

SSH 連線會無預警中斷

本文將從實務角度出發,說明如何透過正確設定,建立一套 可長時間穩定使用的 Cloudflare Tunnel SSH 架構,並同時支援 Host 與內部 Container(Incus / Docker)

目標與適用情境

本文適合以下情境的使用者:

  • 不想對外開放 SSH Port
  • 使用 Cloudflare Zero Trust 管理存取
  • 主機內有多個內部服務或 Container
  • 曾遇過 Cloudflare Tunnel SSH 無預警斷線
  • 希望 SSH 連線可用於長時間維運或管理作業

架構概覽:Host 與 Container 共用 Tunnel

本篇教學採用以下設計原則:

  • 僅 Host 執行 cloudflared
  • Container 不對外暴露
  • SSH 流量全程經 Cloudflare Tunnel
  • SSH 金鑰驗證仍由系統 sshd 控制

架構角色說明

  • Host(DEV-vm)
    • 執行 cloudflared service
    • SSH 服務位於 127.0.0.1:22
  • Container(Incus / HestiaCP)
    • 位於內部網段(如 10.10.10.50
    • 不需安裝 cloudflared
    • SSH 由 Host 轉發

Cloudflare Tunnel ingress 設定範例

以下為 Host 上的 config.yml 範例:

ingress:
  - hostname: dev-vm.example.org
    service: ssh://127.0.0.1:22

  - hostname: dev-hcp.example.org
    service: ssh://10.10.10.50:22

  - service: http_status:404

設計重點說明

  • 使用 loopback (127.0.0.1) 連接 Host 本機 SSH
  • Container 僅能由 Host 轉發存取
  • 最後一條規則防止未匹配流量誤入 Tunnel

為什麼 Cloudflare Tunnel SSH 容易斷線?

Cloudflare Tunnel 本質上是 中介傳輸層,並不保證連線永久存在。當連線長時間沒有任何封包流動時,Cloudflare 可能會將其視為 idle 並回收連線。

這也是許多使用者遇到以下錯誤的原因:

client_loop: send disconnect: Unknown error
Connection closed by remote host

這類錯誤並非 SSH 金鑰或設定錯誤,而是 傳輸通道被中斷

Client 端(Windows)SSH 穩定性設定

為了避免 Cloudflare 判定連線為 idle,Client 端必須主動送出 keepalive 封包

以下為 ~/.ssh/config 建議設定(私鑰名稱已隱藏):

Host devvm-ssh-host
  HostName dev-vm.example.org
  User james
  IdentityFile C:\Users\USERNAME\.ssh\YOUR_PRIVATE_KEY
  ProxyCommand cloudflared access ssh --hostname %h
  GSSAPIAuthentication no
  ForwardAgent yes
  ServerAliveInterval 30
  ServerAliveCountMax 3

Host devvm-ssh-container
  HostName dev-hcp.example.org
  User annie
  IdentityFile C:\Users\USERNAME\.ssh\YOUR_PRIVATE_KEY
  ProxyCommand cloudflared access ssh --hostname %h
  GSSAPIAuthentication no
  ForwardAgent yes
  ServerAliveInterval 30
  ServerAliveCountMax 3

設定重點

  • ServerAliveInterval 30:每 30 秒主動送封包
  • ServerAliveCountMax 3:避免短暫抖動立即斷線
  • 可有效防止 Cloudflare Tunnel idle timeout

Server 端(Host)SSH 補強設定

在 Host 上,同步建議調整 sshd 設定:

ClientAliveInterval 60
ClientAliveCountMax 3
AllowAgentForwarding yes

套用後重新載入 SSH 服務:

sudo systemctl reload ssh

此設定能在 Tunnel 發生短暫 reconnect 時,提高連線存活率。

Container 端的 SSH 安全建議

Container 端建議僅保留必要設定:

PasswordAuthentication no
PubkeyAuthentication yes

Container 不需要知道 Cloudflare Tunnel 的存在,所有安全性仍由 SSH 金鑰機制負責。

常見錯誤觀念釐清

  • ❌ Cloudflare Tunnel 不穩定
  • ❌ SSH 金鑰設定錯誤
  • ❌ Container 架構導致問題

實際上,問題幾乎都來自未設定 keepalive

總結

Cloudflare Tunnel 非常適合用於 SSH 遠端管理,但前提是:

必須主動處理長連線保活問題

只要在 Client 與 Server 端正確設定 keepalive,Cloudflare Tunnel SSH 完全可以用於正式維運環境,並同時兼顧安全性與便利性。

文章分享
James Tsai
James Tsai
文章: 13

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *