Cloudflare Tunnel 還是開 Port?自架服務對外的兩種路線
不用公網 IP、不開防火牆洞,Cloudflare Tunnel 把自架服務接上網際網路。這篇比較它與傳統 port forwarding 的安全性、延遲、成本與限制,並給出混合架構建議。
自架服務做好之後,下一個問題永遠是同一個:要怎麼從外面連進來?
兩條路線:開 port(傳統做法)或 Cloudflare Tunnel(這幾年愈來愈多人用)。這篇不是叫你選邊,而是把兩者的攻擊面、延遲、限制講清楚,因為它們適合的東西不一樣。
一、兩種架構長什麼樣
路線 A:開 Port(Port Forwarding)
Internet → 你的公網 IP:443 → 路由器 NAT → 主機 nginx → 服務
你要的東西:公網 IP(或 DDNS)、路由器 port forward、憑證(Let’s Encrypt)、防火牆規則、以及一堆因為「機器直接暴露在掃描器面前」而來的維運工作。
路線 B:Cloudflare Tunnel
服務 ← cloudflared(主機上)→ 主動 outbound 連線 → Cloudflare Edge ← 使用者
cloudflared 在你的機器上建立對外的連線(通常是 QUIC/HTTP2 到 Cloudflare),Cloudflare 把請求送進這條連線。你不需要公網 IP、不需要開任何 inbound port。
對路由器來說,這台機器就只是「有對外連線的普通電腦」,跟瀏覽 YouTube 沒兩樣。
二、安全性:差別不在加密,在攻擊面
兩者都可以做到全程 TLS。真正的差別是誰看得到你的機器。
| 開 Port | Cloudflare Tunnel | |
|---|---|---|
| 需要公網 IP | 是(或 DDNS) | 不需要 |
| Inbound port | 至少 1 個 | 0 |
| 誰能掃到你的 nginx | 全世界 | 沒人(掃不到) |
| nginx 0-day 的風險 | 直接暴露 | 需先攻破 Cloudflare 才能觸及 |
| DDoS 防護 | 自己扛 | 內建 |
| 憑證管理 | 自己續(certbot) | Cloudflare 邊緣處理 |
| 真實 IP 隱藏 | 否 | 是 |
| 設定錯誤的後果 | 服務直接裸奔 | 服務公開(但無 port 可打) |
開 port 的真實成本不是「設定的麻煩」,是「你的 nginx 從上線那一刻起就被人掃」。上線 24 小時內就會有針對 /wp-login.php、/.env、/actuator/env 的請求出現,這不是針對你,是背景噪音。
Tunnel 把這層噪音完全消掉,因為沒有 port 可以連。這是它最大的價值。
但有個重要的誤解要拆掉
Tunnel ≠ 有認證。 它只移除「網路層暴露」,不會幫你加登入。
如果你把 Grafana、Portainer、Home Assistant 後台直接掛上 tunnel 而沒有設 Access 政策,那個介面就是公開在網路上,任何人都能打開。只是他打不到你的 nginx 而已。
所以正確做法是兩個一起用:
公開內容(部落格、官網) → Tunnel,不設 Access
管理介面(HA、Grafana) → Tunnel + Cloudflare Access(Email OTP / Google 登入)
三、延遲:實務上會被感覺到嗎
架構上多了一跳:使用者 → Cloudflare 邊區節點 → 你的機器。聽起來多一次往返,但實際上:
- Cloudflare 節點通常在離使用者 10–30ms 內
- 你原本的架構是 使用者 → 你的老家(可能 20–40ms)
- 淨差異通常是 +5 到 +20ms
對網頁、API、SSH、WebSocket 幾乎無感。對競技型遊戲、VoIP 會有感——但那些本來就不該走 tunnel。
真正的延遲殺手不是 tunnel,是你家上傳頻寬。 中華電信 100/40 的方案,使用者下載你的檔案時上限就是 40Mbps,這一點兩條路線完全一樣。
四、Tunnel 的限制(先知道再決定)
| 限制 | 說明 | 影響 |
|---|---|---|
| 主要支援 HTTP(S) | TCP 服務(SSH、MySQL)需透過 cloudflared access 用戶端,不是隨便就能連 |
遠端桌面、DB 連線要另外處理 |
| UDP 支援有限 | 別指望拿來跑遊戲伺服器或 WireGuard | 需要 UDP 就還是要開 port |
| 依賴 Cloudflare | 帳號被封、政策變更、服務中斷 → 你的服務也跟著斷 | 重要服務要有備援 |
| 流量經過第三方 | TLS 終止在邊緣,理論上 Cloudflare 看得到明文 | 極敏感資料建議端對端加密或不走 tunnel |
| 大檔案 / 長連線 | 有連線與逾時限制 | 影音串流還是直連比較好 |
| 免費方案沒有 SLA | 商業用途要評估 | 個人自架足夠 |
最後一點要講清楚:Tunnel 不是「零成本又完美」的方案,它是「用依賴換取簡單與安全」。你仍然把一個關鍵環節交給了第三方——這跟 PaaS 的取捨是同一件事,只是交出去的東西不一樣。
五、我建議的混合架構
不要全站選一邊。按「誰要能存取」分層:
第 0 層:靜態網站
直接丟 Cloudflare Pages,連自家的機器都不用。(本部落格就是這樣。)
第 1 層:要給所有人看的動態服務
Tunnel + 不設 Access。例如公開的 API、部落格後台以外的前台。
第 2 層:只有自己要用的管理介面
Tunnel + Cloudflare Access,限定自己的 email。Home Assistant、Grafana、Portainer、資料庫管理工具全放這裡。
第 3 層:真的需要 UDP / 非 HTTP
才開 port,而且用 DOCKER-USER 或 ufw 限制來源 IP。
六、實作:Tunnel 最小可用設定
1. 安裝
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
2. 登入並建立 tunnel
cloudflared tunnel login
cloudflared tunnel create blog
會產生 ~/.cloudflared/<UUID>.json(憑證),這個檔案不要進 git。
3. 設定檔
# /etc/cloudflared/config.yml
tunnel: <UUID>
credentials-file: /root/.cloudflared/<UUID>.json
ingress:
- hostname: blog.example.com
service: http://127.0.0.1:8080
- hostname: ha.example.com
service: http://127.0.0.1:8123
- service: http_status:404
最後那行 http_status:404 是必要的 catch-all,少了它 cloudflared 不會啟動。
4. DNS 與服務
cloudflared tunnel route dns blog blog.example.com
sudo cloudflared service install
sudo systemctl enable --now cloudflared
5. 驗證
sudo systemctl status cloudflared
cloudflared tunnel info blog # 應該看到 1 條以上連線
curl -I https://blog.example.com
關鍵檢查:從外部掃你的公網 IP 的 8080,應該是 closed。 如果還開著,代表你舊的 port forward 沒拆掉,等於同時開了兩條路。
七、五個常見錯誤
- 用
cloudflared tunnel --url localhost:8080當正式服務——那是臨時 tunnel,重啟就換網址,只能拿來測試。 - 掛上管理介面卻忘了設 Access 政策——服務等於公開。設完務必用無痕視窗驗證「沒登入進不去」。
- 只綁
0.0.0.0又同時保留 port forward——你以為搬家了,其實舊門還開著。 - 把憑證檔 commit 進 repo——那把 JSON 等於你 tunnel 的鑰匙。
- 沒有監控 tunnel 本身——cloudflared 掛掉時,你的網站是 502/1033,但你人在外面不知道。用 Uptime Kuma 從外部監測。
八、結論
| 你的情況 | 選 |
|---|---|
| 只有動態 IP、不想碰路由器 | Tunnel |
| 要給公眾存取的網站/API | Tunnel(或 Pages) |
| 只有自己用的管理介面 | Tunnel + Access |
| 需要 UDP、遊戲伺服器、極低延遲 | 開 Port |
| 極度敏感資料、不想經過第三方 | 開 Port + 自管憑證 |
| 靜態網站 | Cloudflare Pages,兩者都不用 |
一句話:能用 Tunnel 就用 Tunnel,需要 UDP 才開 port。 而無論選哪條,管理介面都該有第二道鎖——網路層的隱藏不是認證,只是讓你不那麼容易被找到。
最後更新:2026年10月18日