SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

Tailscale serve 與 funnel 怎麼選?

Tailscale serve 僅讓 tailnet 存取 HTTPS URL,funnel 則公開至網際網路。了解兩者差異,以及 policy file 中缺少 node attribute 時阻擋 funnel 的設定限制。

tailscale serve 與 funnel:誰可以存取該 URL

tailscale servetailscale funnel 的差異在於存取對象,其他方面完全相同。serve 會在本機連接埠前端提供 HTTPS(hypertext transfer protocol secure),但只會將服務發布給你的 tailnet。funnel 則會透過 Tailscale 維運的 relay servers,將同一個本機連接埠發布到整個公開網際網路。這兩個命令使用相同的 flags 與 targets。一個詞的差異,就能決定儀表板只供私人存取,或讓全世界都能連線。

兩者都會在以 ts.net 結尾的名稱上提供瀏覽器已信任的憑證,且都不需要在 VPS 防火牆開放入站連接埠。你的 tailscaled daemon 已建立通往 tailnet 的連線,因此流量會透過該連線抵達。將伺服器加入 tailnet 是另一項工作;將 VPS 設為 Tailscale exit node為私人網路發布 subnet router 都涵蓋這部分。發布已位於 tailnet 上的服務,則是本節的工作。

執行任一命令前的必要條件

  • VPS 上的 Tailscale 版本為 1.38.3 或更新版本,且已登入 tailnet。使用 tailscale versiontailscale status 檢查。
  • 已啟用 MagicDNS。MagicDNS 是 Tailscale 內建的 DNS(domain name system),可為機器提供如 blog-vps.your-tailnet.ts.net 的名稱,而不只使用 100.x 位址。
  • 已在管理主控台的 DNS 頁面中,為 tailnet 啟用 HTTPS 憑證。未啟用時,沒有可配置在連接埠前方的憑證。
  • 只有 funnel 需要在 tailnet policy file 中設定 funnel node attribute。多數人第一次嘗試都會在這裡停止,下面會說明設定方式。

這裡的每個命令都以 sudo 開頭,因為 CLI 只能透過 root 可寫入的 socket 與 tailscaled 通訊。若要讓一名使用者略過這項限制,請授予該使用者相應權限:

sudo tailscale set --operator=$USER

使用 tailscale serve 發布至 tailnet

serve 指向本機埠,後續工作會由它處理。

sudo tailscale serve 3000
Available within your tailnet:
https://amelie-workstation.pango-lin.ts.net

 |-- / proxy http://127.0.0.1:3000

Press Ctrl+C to exit.

單獨使用 3000http://127.0.0.1:3000 的簡寫。Tailscale 會在該機器的 tailnet 位址上監聽 443 埠,使用 ts.net 憑證終止 TLS(傳輸層安全性),再將純 HTTP 轉送至本機埠。您的應用程式不需要知道憑證存在。這也是在管理介面前使用此功能的主要原因,否則該介面只能以純 HTTP 對外提供。

現在查看最後一行:Press Ctrl+C to exit.。此命令會在前景執行,對應關係也只存在於該程序中。關閉終端機後,URL 就會停止運作,因為沒有任何內容寫入磁碟。加入 --bg 後,對應關係會寫入節點的 serve 設定,終端機關閉及重新開機後仍會保留。

sudo tailscale serve --bg 3000

Serve 不只接受埠號。--set-path 會將服務掛載至子路徑,讓多個應用程式共用同一個主機名稱:

sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090

目標也可以是靜態檔案目錄,或是已使用 TLS 且憑證不希望受到驗證的後端:

sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443

它也不限於 HTTP。--tcp=<port> 會轉送原始 TCP(傳輸控制協定)串流;--tls-terminated-tcp=<port> 則會在節點上終止 TLS,再轉送純文字,讓完全不支援 HTTP 的服務也能使用受信任的憑證:

sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899

為什麼 funnel 顯示未設定 node attribute?

Funnel 預設會對整個 tailnet 關閉。第一次執行時會顯示以下訊息,然後停止:

Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.

命令本身沒有問題。tailnet policy 尚未授予此 node 發布內容的權限,因此 client 在聯絡 relay 前就會拒絕操作。請在管理主控台的 Access Controls 中編輯 tailnet policy 檔案,並加入以下 attribute:

"nodeAttrs": [
  {
    "target": ["autogroup:member"],
    "attr":   ["funnel"],
  },
],

autogroup:member 會將此 attribute 授予 tailnet 的所有成員。如果只有一台機器應該能發布內容,請為該機器加上 tag,並改為指定該 tag,例如 tag:public。儲存 policy,然後再次執行 funnel 命令。

如果你的帳戶是 tailnet admin,近期版本的 client 提供捷徑:CLI 會在 login.tailscale.com 顯示同意 URL。開啟該 URL 後,系統會啟用 HTTPS 憑證,並代你加入該 attribute。如果你不是 admin,該 URL 對你沒有幫助。具備 policy 存取權限的人員必須進行這項修改。

透過 tailscale funnel 發布至網際網路

設定好屬性後,使用的指令就是你已經熟悉的指令,只需改用不同的動詞。

sudo tailscale funnel --bg 3000
Available on the internet:
https://amelie-workstation.pango-lin.ts.net

 |-- / proxy http://127.0.0.1:3000

Press Ctrl+C to exit.

每次都要先閱讀第一行。Available within your tailnetAvailable on the internet 是私有服務與公開服務之間唯一可見的差異,而產生這兩者的指令只差一個單字。

截至 2026 年 8 月,funnel 只會監聽 443、8443 或 10000 埠,不會監聽其他埠。預設值是 443,--https=8443--https=10000 可作為替代值。其他埠都會遭到拒絕,因為 funnel relay 只接受在這些埠上的連線。因此,funnel URL 一律是裸主機名稱,或在結尾附加 :8443

如何查看目前已發布的內容?

靠猜測會讓儀表板公開一個月。請直接詢問節點。

tailscale serve status
tailscale funnel status
tailscale serve status --json

這兩個狀態指令讀取相同的設定,因此使用任一個都能查看完整狀態。請在指令碼或排程檢查中使用 --json 格式,因為一般輸出是提供人員閱讀的。未設定任何內容時,會顯示一行:

No serve config

如果在確認設定成功後看到這個結果,表示對映是在前景建立的,而程序已經結束。請使用 --bg 重新建立。

若要移除單一對映,請重新執行建立該對映的指令,並在結尾加上 off。若要清除節點上的所有 serve 和 funnel 對映,請使用 reset

sudo tailscale funnel --https=443 3000 off
sudo tailscale serve reset

完成任一操作後,再次執行 tailscale serve status,確認實際剩餘內容,不要假設指令已完成預期工作。

你會得到什麼,以及必須放棄什麼

這些優點確實存在,也是人們選擇它而非反向代理的原因。

  • 瀏覽器信任的憑證會代為續期。不必安裝 ACME(automatic certificate management environment)用戶端,也不必擔心忘記設定續期工作。
  • VPS 防火牆不需要開放入站連接埠。tailscaled 會主動撥出,因此 VPS 上預設拒絕連線的 ufw 防火牆可以維持原本嚴格的設定。
  • 不必購買、指向或等待 DNS 記錄。
  • 不必設定連接埠轉送。對位於 NAT(network address translation)後方、而非具備公開 IP 的 VPS 而言,這是最主要的用途。

這些成本同樣確實存在,而且 funnel 的限制全部包括在內。

  • 這個名稱不屬於你。公開訪客會看到 host.your-tailnet.ts.net。Funnel 不支援自訂網域,因此無法在前面使用 app.example.com
  • 這個路徑不屬於你。流量會先到達 Tailscale relay,再由 relay 透過 tailnet 將串流代理到你的節點。Tailscale 表示 funnel 流量受未公開且無法設定的頻寬限制影響,因此在依賴特定數值前,請先測量自己的吞吐量。
  • 缺少控制功能。自行執行的反向代理可提供存取日誌、速率限制、請求大小上限,以及放置驗證機制的位置。Funnel 只提供 URL。其他功能都必須由應用程式自行處理。
  • 可使用的連接埠固定不變,如上所述。

這兩項功能也依賴 Tailscale 維運的基礎設施:為 ts.net 名稱簽發憑證,以及 funnel relay 本身。如果你正在評估 自行託管的 Headscale control server,不要假設這些功能也會隨之提供。請查閱計畫執行的 Headscale 版本之 release notes。

該使用哪一個?

規則很簡單。

內部用途一律使用 serve:管理介面、儀表板、不希望被索引的 metrics UI,以及網站的 staging 副本。存取控制就是 tailnet 的成員資格,而且這項控制相當可靠。不在 tailnet 上的裝置甚至無法解析該名稱。

示範連結、第三方必須 POST 到的 webhook receiver,或開發期間的 OAuth callback,使用 funnel。這是取得公開 HTTPS URL 的最快方式,而執行一個 off 命令即可停止。公開就代表公開:hostname 不是 secret;如果應用程式沒有登入機制,放在其前方的 funnel 就是開放服務。後方的服務必須自行驗證請求,並採取與 暴露的 Ollama API endpoint 相同的謹慎程度。

凡是可稱為 production 的服務,都應使用正式的 reverse proxy。網域、憑證、日誌與速率限制都由你管理,請求路徑中也不會有其他人。比較 nginx、Caddy 與 Traefik 作為 reverse proxy 可協助你選擇。

失敗模式與你會看到的訊息

Funnel 拒絕啟動。 Funnel not available; "funnel" node attribute not set. 是原則問題,不是命令問題。將 funnel 屬性加入 tailnet policy 檔案,儲存後再試一次。

原本可以運作,現在 tailscale serve status 顯示 No serve config 對應是在前景建立的,而該程序已經結束。使用 --bg 重新執行相同命令。

名稱可以解析,但沒有任何回應。 Serve 會將代理轉送到你指定的目標。因此,如果該位置沒有服務監聽,就沒有可供代理轉送的目標。在執行 tailscaled 的同一台機器上,使用 ss -ltnp | grep 3000 確認。常見原因是容器將連接埠發佈在 Docker bridge 位址,而不是 127.0.0.1,導致主機在預期位置找不到監聽中的服務。Docker Compose 網路運作方式 說明已發佈的連接埠實際位於何處。

ts.net 名稱發生憑證錯誤。 tailnet 很可能尚未啟用 HTTPS 憑證。請在管理主控台中啟用憑證,然後單獨執行憑證步驟,避免其錯誤與 serve 輸出混在一起:

sudo tailscale cert your-host.your-tailnet.ts.net

Funnel 使用行動數據時可以載入,但在筆電上的行為不同。 你的筆電位於 tailnet,因此 MagicDNS 會將名稱解析為 100.x 位址,讓你直接連到服務,不會經過 relay。這是正確行為,也表示你的筆電完全無法測試公開可連線性。請在不屬於 tailnet 的機器上使用 curl

FAQ

tailscale serve 與 tailscale funnel 有何不同?

誰可以存取該服務。tailscale serve 會將本機埠發布至 HTTPS URL,只有 tailnet 上的裝置可以存取。tailscale funnel 會將同一個埠發布至任何網際網路使用者都能存取的 URL,並透過 Tailscale 執行的 relay server 進行路由。兩者共用相同的 flags 與 targets。輸出的第一行會告訴你使用的是哪一種:Available within your tailnetAvailable on the internet

為什麼 tailscale funnel 顯示 node attribute 尚未設定?

因為除非有人啟用 funnel,否則 tailnet 預設會停用此功能。訊息內容是 Funnel not available; "funnel" node attribute not set.,且由你自己的 client 在連線至任何 relay 之前顯示。請在 Access Controls 下的 tailnet policy file 中加入 nodeAttrs 設定,將 funnel attribute 授予 autogroup:member;如果只有一台機器應發布服務,也可以授予 tag。tailnet admin 也可以依照 CLI 顯示的 consent URL 操作。

Tailscale Funnel 可以使用哪些埠?

只有 443、8443 和 10000。預設值是 443,你可以使用 --https=8443--https=10000 選擇其他埠。這是 funnel relay 的限制,不是伺服器的限制,因此無法透過修改 VPS 的防火牆或設定來解除。tailscale serve 沒有這項限制,因為流量不會離開你的 tailnet。

serve 或 funnel URL 在重新開機後仍會存在嗎?

只有使用 --bg 時才會。未使用此選項時,命令會在前景執行、顯示 Press Ctrl+C to exit.,而 mapping 會隨著該程序結束而消失。使用 --bg 時,mapping 會寫入 node 的 serve config,並在重新開機後透過 tailscaled 恢復。請使用 tailscale serve status 檢查;未設定任何項目時,該命令會顯示 No serve config

讓 funnel 持續執行是否安全?

就傳輸層面而言是安全的:連線使用 HTTPS,且防火牆不會開放任何埠。但就通常所說的安全性而言並不安全,因為 URL 是公開的,其後端應用程式也會公開。只有在 funnel 前方的應用程式會自行驗證請求時,才應讓 funnel 持續執行。示範或 webhook 測試結束後,請在建立 funnel 的命令末尾加上 off 來停止它。

上述命令行為的來源為 Tailscale Serve 與 Funnel 文件及 CLI reference:tailscale.com/docs