SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-10-21

Tailscale 是什麼?Mesh VPN 如何運作

了解 Tailscale 如何以 WireGuard 建立 mesh VPN:協調伺服器分發金鑰與 ACL,NAT 穿透讓節點直連,失敗時由 DERP relay 轉送封包。

什麼是 Tailscale?

Tailscale 是一種 VPN,可讓您的機器直接彼此連線,而不是將所有網路流量都經由您執行的單一閘道。每個節點都執行 WireGuard,因此封包會從一台伺服器加密傳送到另一台伺服器,傳輸路徑上的任何元件都無法讀取內容。代管的協調伺服器會處理節點間的連線建立。它會儲存並分發公開金鑰,也會告知各節點其他節點的位置。它還會下發您撰寫的存取規則。

這種分離就是整體設計。資料平面採用點對點連線,並在節點之間加密。控制平面則是由 Tailscale 代為執行的服務。關於 Tailscale 的所有重要問題,包括信任方面較難回答的問題,都源自這兩項事實。如果您已經在 VPS 上手動建立 WireGuard VPN,那麼 Tailscale 就是相同的通道,只是由它代為處理金鑰分發與防火牆穿透。

Tailscale 如何運作?

由節點組成的私有網路稱為 tailnet。機器加入 tailnet 時,會發生以下 4 件事。

  1. tailscaled daemon 啟動,產生 WireGuard 金鑰組,並將狀態儲存在 /var/lib/tailscale/tailscaled.state。私密金鑰會留在該機器上。Tailscale 的說法很直接:「私密金鑰永遠不會離開其節點。」
  2. 節點登入協調伺服器,並上傳其公開金鑰,以及它認為可供連線的位址。Tailscale 將該伺服器描述為「供公開金鑰共用的投遞箱」。
  3. 協調伺服器傳回網路對映,其中包含公開金鑰、tailnet 位址、機器名稱,以及此節點獲准連線之所有節點的候選端點。
  4. 每一對節點接著嘗試在彼此之間建立直接的 WireGuard 通道。若失敗,則改由 relay 轉送封包。

每個節點都會從 100.64.0.0/10 取得穩定位址。這是從 100.64.0.0 到 100.127.255.255 的電信級 NAT 位址範圍。Tailscale 使用此範圍,是因為它保留供服務提供者的基礎設施使用,因此很少會與伺服器目前使用的私有位址衝突。在 Linux 上,該通道會顯示為名為 tailscale0 的介面。

WireGuard 實作位於使用者空間的 tailscaled 內,而不是核心模組中。因此,Tailscale 能在容器虛擬化環境中啟動,而 sudo modprobe wireguard 會因 Operation not supported 失敗。這也表示在特定主機上,其吞吐量上限低於核心中的 WireGuard。這是 Tailscale 與純 WireGuard 的比較所討論的取捨之一。

以下 2 個命令可顯示目前狀態。

tailscale ip -4
tailscale status

tailscale status 會為每個節點列出一行,而最後一欄最重要。

100.101.102.103  web-1      you@  linux  -
100.101.102.104  db-1       you@  linux  active; direct 198.51.100.24:41641
100.101.102.105  ci-runner  you@  linux  active; relay "fra"

direct 後接位址與埠號,表示兩台機器已找到彼此的連線路徑,網路流量會以對等方式傳輸。relay "fra" 表示流量正經由位於 Frankfurt 的 Tailscale relay 傳送。- 表示目前沒有與該節點建立作用中的工作階段,這是正常情況。

協調伺服器能看見與不能看見的資訊

協調伺服器保存公開金鑰與中繼資料。它知道您的機器名稱、各節點所屬的使用者或標籤、各節點的 tailnet 位址、節點可從哪些公開位址連線、各節點上次上線的時間,以及您撰寫的政策檔案。這些資訊足以完整呈現您的伺服器群組。

協調伺服器不持有任何私密金鑰,因此無法解密兩個節點之間的流量。WireGuard 對等節點之間採用端對端加密,而協調伺服器不是對等節點。

它能做的是分發金鑰。無論是代管或自行執行的協調伺服器,您都必須信任它,讓它告知節點哪些公開金鑰屬於 tailnet。這正是後文威脅模型的關鍵,也是 Headscale,自行代管的開放原始碼協調伺服器 存在的原因。

不同防火牆後方的兩台伺服器如何直接通訊

NAT(網路位址轉換)讓多台機器共用一個公開位址。您的 VPS 通常有自己的公開位址,但您想加入 tailnet 的其他機器往往沒有,例如家用伺服器、辦公室網路上的建置執行器,或位於您無法修改的供應商防火牆後方的主機。

Tailscale 使用建構於 STUN(NAT 的工作階段穿越公用程式)與 ICE 標準之上的技術尋找路徑。每個節點都會向 STUN 伺服器傳送小型 UDP 封包,並得知路由器為該 socket 指派的公開位址與埠。兩個節點都會將這些候選位址回報給協調伺服器,再由協調伺服器傳給另一端。接著,兩個節點會同時開始互相傳送封包。每台路由器都會先看到對外傳送的封包,因此建立對映,並接受從相同位址返回的回應。兩端都不需要設定入站防火牆規則。這也是家中的 NAS 或 Pi 不需在路由器上設定連接埠轉送,仍能保持可連線的原因;使用 Tailscale 取代連接埠轉送會逐步說明這項設定,包括它無法處理的情況。如果那台 NAS 是 Synology 或 QNAP,在 Synology 或 QNAP NAS 上安裝 Tailscale會說明如何以直接的 WireGuard 連線取代 QuickConnect 或 myQNAPcloud Link,以及 DSM 7 上 TUN 開機任務的設定方式。

這些連接埠是固定的。直接 WireGuard 通道使用 UDP,來源埠預設為 41641。STUN 透過 UDP 3478 連線至 Tailscale 的中繼伺服器。控制連線優先使用 TCP 80 上的純 HTTP,並包裝在 Tailscale 自有的加密傳輸中;如果連接埠 80 沒有回應,則改用 TCP 443 上的 HTTPS。經由 Tailscale 的 DERP 伺服器中繼的資料使用 TCP 443 上的 HTTPS;而在您自己的 tailnet 內執行的對等中繼,則透過 UDP 傳輸。大多數情況下,您不需要開放任何入站連接埠。不過,在 NAT 行為較複雜的網路上,允許 UDP 41641 入站可提高建立直接連線的機率。

tailscale netcheck

查看該報告中的兩行。UDP: true 表示此機器可以向網際網路傳送 UDP,UDP: false 表示無法傳送,因此所有從此節點建立的連線都會透過中繼。MappingVariesByDestIP: true 表示路由器會針對不同目的地指派不同的公開埠,因此上述位址預測無法運作,而這些節點通常會維持透過中繼連線。

Tailscale 改用 DERP 中繼的情況

DERP(designated encrypted relay for packets,封包指定加密中繼)是備援機制。Tailscale 在多個區域執行中繼服務,可透過 TCP 443 連線;無法建立直接路徑的節點,會將 WireGuard 封包經由其中一個中繼傳送。例外是 tailnet 中指定了對等中繼的情況。這些中繼是由你自己的裝置提供,並透過 UDP 轉送流量。Tailscale 會優先嘗試這些中繼,只有在全部無法使用時才改用 DERP,接著 tailscale status 會將連線顯示為 peer-relay。

封包會持續保持加密。Tailscale 的說明很明確:「DERP 伺服器永遠無法解密你的流量。它只會盲目地將已加密的流量從一個節點轉送到另一個節點。」中繼只能看到密文,以及哪個節點正在與哪個節點通訊。

大多數連線的初始封包也會經過中繼。尋找直接路徑需要一些時間,因此工作階段通常會先以中繼方式開始,等兩個節點找到彼此後,再原地升級為直接連線。你可以觀察這個過程。

tailscale ping db-1

最初的回應會以 via DERP(fra) 返回,稍後的某一行則會回報類似 via 198.51.100.24:41641 的內容。這項變化表示已升級為直接通道。若狀態始終沒有變化,請在兩端執行 tailscale netcheck。中繼路徑仍可正常運作,但會增加延遲,因為每個封包都必須繞經第三台機器。如果你注意到的是傳輸速度變慢,而不是連線中斷,請參閱為什麼經由中繼的 Tailscale 連線比直接連線慢得多,其中會量測差異,並說明如何讓 VPS 建立直接路徑。

將 VPS 加入 tailnet

安裝指令碼涵蓋 Ubuntu 和 Debian。

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

sudo tailscale up 會輸出 URL。開啟該 URL、完成驗證,節點就會出現在管理主控台中。接著確認 daemon 在重新開機後仍會啟動,因為這是最容易被略過的步驟。

sudo systemctl is-enabled tailscaled
tailscale status

is-enabled 應輸出 enabled,而 tailscale status 應列出新的節點及其 100.x 位址。對於透過指令碼建立的伺服器,互動式 URL 沒有用處。請在管理主控台中產生 auth key,並將它與標記一併傳入,以記錄這台機器的類型。

sudo tailscale up --auth-key=tskey-auth-REPLACE-ME --advertise-tags=tag:server

標記節點的擁有者是該標記,而不是執行指令的人。因此,即使該使用者的帳戶已不存在,節點仍可繼續運作。必須先在 tagOwners 下方的 policy 檔案中宣告該標記,否則指令會遭拒。標記也會改變機器計入方案的方式,因為標記資源的計費與使用者自己的裝置分開,而免費方案實際涵蓋的內容會說明這些限制的範圍。

Fleet 有兩項設定需要注意。節點金鑰預設在 180 days 後到期(截至 October 2026),金鑰到期後,「與指定端點的連線都會停止運作」,直到裝置重新驗證為止。管理員可以在管理主控台中,對已過期的機器選擇 Temporarily extend key,取得 30 minutes 的時間重新登入,或停用到期功能。使用標記完成驗證的節點,例如上方的節點,預設會停用金鑰到期功能。對於其他無人值守的伺服器,請在管理主控台中開啟該機器的列,然後選擇 Disable Key Expiry。對於在 20 October 2022 當天或之後建立的 tailnet,MagicDNS 預設已啟用,會為每個節點提供類似 db-1.yak-bebop.ts.net 的名稱,並由位於 100.100.100.100 的 stub resolver 解析。請使用名稱而非位址,因為重建節點後會取得新的位址,但名稱會保留。

如果安裝程序在 apt 或 repository 上失敗,請參閱Ubuntu 上常見的 Tailscale 安裝錯誤,其中說明相關修正方法。

連線至繫結 localhost 的服務

這正是 tailnet 發揮作用的地方,也是許多人卡住的地方。加入 tailnet 不會讓 loopback 服務變得可連線。

ss -tlnp | grep 3000

如果輸出 127.0.0.1:3000,表示 socket 只接受目的地為 127.0.0.1 的封包。來自其他節點的請求會以本節點的 100.x 位址為目的地送達,因此 kernel 找不到正在監聽的服務,並回覆 TCP reset。用戶端會顯示 Connection refused。tunnel 沒有問題,問題出在 listener。

有兩種直接的修正方式。將服務繫結至節點的 tailnet 位址。這樣不需要 proxy,也能避免服務暴露在公開介面上:傳入 --bind 100.101.102.104,或在設定檔中使用等效選項;若是容器,請將連接埠發布為 -p 100.101.102.104:3000:3000。或者讓服務維持在 loopback,並在前方放置 Tailscale。

tailscale serve 3000

這會將請求 proxy 至 http://127.0.0.1:3000,並在啟用 tailnet 的 HTTPS 憑證後,透過 ts.net 名稱在 tailnet 內提供服務。服務仍只對節點保持私有。相同概念的公開版本是 Funnel,而 Tailscale serve 與 funnel 的比較說明應使用哪一種。

另外兩項相關工作各有專頁。若要連線至未安裝 Tailscale 的完整私有網路,請參閱 VPS 上的 subnet router;若要將節點對外的網際網路流量經由另一個節點傳送,請參閱 exit node。

關閉不再需要的連接埠

當所有管理員都能透過 tailnet 連線到伺服器後,公開的 22 埠便不再有用途。這就是實際效益:關閉的連接埠無法遭受暴力破解,日誌也不會持續填滿嘗試連線的記錄。

操作順序很重要。先加入 tailnet 存取規則,從第二個工作階段確認可以透過 tailnet 登入,然後才移除公開規則。

sudo ufw allow in on tailscale0
sudo ufw status verbose

接著刪除公開的 SSH 規則,並使用 MagicDNS 名稱重新連線。請注意 ufw allow in on tailscale0 的實際作用:它會信任所有從通道抵達的流量,因此存取控制會由 Tailscale 政策檔案取代 ufw。撰寫政策時必須將此點納入考量。

使用容器的使用者還需注意一點。已發布的 Docker 埠會自行安裝 NAT 規則,並繞過 ufw,因此 ufw deny 無法關閉該埠。Docker 已發布的連接埠繞過 ufw 說明了其運作機制。如上所述,將服務發布到 tailnet 位址即可避開這個問題。如果應用程式由 Docker Compose 執行,在 Compose 堆疊中使用 Tailscale sidecar 可進一步完全移除已發布的埠,讓容器只能透過其 tailnet 名稱存取。

Tailscale 可防護的內容,以及無法防護的內容

這點值得直接說明,因為行銷說法容易模糊界線。

可防護的內容:兩個節點之間的流量會透過 WireGuard 進行端對端加密,中間的任何中繼器都無法讀取。私密金鑰不會離開產生它的機器。節點不需要公開的入站埠,因此網際網路無法掃描 22 或 5432。節點之間的存取由政策檔案決定,而不是由知道某個位址的人決定。

無法防護的內容:協調伺服器會看到你的裝置拓撲。這些中繼資料本身就很敏感,因為機器名稱、擁有者、位址和上線時間會描述你的基礎架構。協調伺服器也會分發金鑰,這是更直接的風險。Tailscale 直接說明:「如果 Tailscale 具備惡意,並偷偷將新節點插入你的網路,Tailscale 就能以明文向現有節點傳送流量,或從現有節點接收流量。」你的單一登入提供者也位於相同的信任路徑中,因為任何能在該處簽發身分的人都能加入節點。而遭入侵的節點是 tailnet 內的對等節點,因此它接下來能存取的內容,就是你的政策允許的內容。這是否構成可接受的風險,取決於你要防禦的對象;完整的信任模型會逐一說明這些情況,包括遭竊的身分帳戶實際上能做什麼。

金鑰分發風險有兩種應對方式。第一種是 tailnet lock。它要求現有的受信任節點以密碼編譯方式簽署新節點,其他節點才會接受該節點。若控制平面加入的節點沒有有效簽章,就會被忽略。管理主控台會為簽署節點產生確切的 tailscale lock init 行,每個節點都能確認自己看到的內容。

tailscale lock status

所有節點都應回報相同的一組受信任簽署金鑰。第二種方式是自行執行控制平面。自架 Headscale 協調伺服器會使用相同的通訊協定與相同的用戶端互通,將裝置拓撲與金鑰分發移至你擁有的硬體上。你也必須自行負責該伺服器的可用性。如果你仍在比較自架控制平面,而尚未決定採用這個方案,NetBird 是另一個 mesh VPN,可由你在單一 VPS 上從頭到尾自行執行伺服器。

第一天就應修正一項預設設定。新的 tailnet 預設採用寬鬆設定:「預設的 tailnet 政策檔案會允許 tailnet 內的所有裝置彼此通訊。」加入 acls 區段後,模型就會切換為預設拒絕,只有符合你規則的流量能夠通過。

{
  "tagOwners": {
    "tag:server": ["autogroup:admin"]
  },
  "acls": [
    {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}
  ]
}

該政策允許 tailnet 成員連線至已標記伺服器上的 SSH,除此之外不允許其他連線。每項服務都應新增一條規則,不要保留萬用字元,因為萬用字元代表只要一台筆記型電腦的金鑰遭竊,攻擊者就能連線至你的資料庫。

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

tailscale status 一律顯示 relay。 兩個節點從未建立直接路徑。在兩端執行 tailscale netcheck。UDP: false 表示對外的 UDP 流量遭到封鎖,因此只能使用 relay。MappingVariesByDestIP: true 表示存在嚴格 NAT;在你能控制的一端允許 UDP 41641 的入站流量,通常即可解決問題。

運作數月的節點消失。 常見原因是節點金鑰在預設的 180 天後過期,因此先在管理主控台檢查該機器。若顯示已過期,在該機器上執行 sudo tailscale up 即可恢復;在伺服器上停用金鑰到期功能,可避免問題再次發生。若金鑰未過期,請檢查 policy 檔案,因為 Tailscale 對於裝置未出現在 tailscale status 的建議,是檢查是否有阻止連線的存取規則。

已列出對等節點,但連線逾時。 若 tailscale ping 收到回覆,表示連線正常,最可能的原因是 policy 拒絕了該流量。檢查 acls 區段是否有涵蓋此來源、目的地與連接埠的規則。遭拒的封包會直接丟棄,而不是回覆,因此你會收到逾時,而不是 Connection refused。

MagicDNS 名稱無法解析。 ping db-1 失敗,但 ping 100.101.102.104 正常。先確認用戶端接受 Tailscale 的 DNS 設定:以 --accept-dns=false 啟動的節點不會將查詢傳送至 100.100.100.100 的 stub resolver。接著檢查 cat /etc/resolv.conf,以及該機器上其他會寫入此檔案的程式。在使用 systemd-resolved 的系統上,該檔案通常是指向 /run/systemd/resolve/stub-resolv.conf 的 symbolic link,因此其中未列出 100.100.100.100 是預期行為。若 tailscaled 直接寫入該檔案,會覆寫檔案的 DHCP 用戶端或其他工具就會導致 MagicDNS 失效。若以上原因都不成立,問題也可能出在本機或網路的 DNS 設定。這與 WireGuard tunnel 內部的 DNS 故障 屬於同一類問題。

tailscale up 拒絕你的 tag。 policy 檔案的 tagOwners 下未宣告該 tag。請在該處新增 tag,然後再次執行該命令。

FAQ

Tailscale 是 VPN 還是 mesh network?

這兩個說法都正確,但描述的是不同層次。通道使用 WireGuard,因此屬於 VPN。拓撲是 mesh,因為每個節點會直接與其通訊的其他節點建立通道,而不是讓每個封包都經過單一中央伺服器。協調伺服器位於控制路徑,不在資料路徑中,因此即使無法連線,現有通道仍會繼續傳送網路流量。服務中斷期間會停止的是新節點加入,以及金鑰或政策變更的套用。Tailscale 預設不是隱私 VPN:在流量經過 exit node 前,網站仍會看到你自己的公開位址;Tailscale 對網站和 ISP 隱藏的內容則取決於各項設定。

Tailscale 能讀取我的網路流量嗎?

無法讀取內容。節點之間的網路流量使用 WireGuard 進行端對端加密,私密金鑰不會離開節點,而 DERP relay 只能轉送無法解密的封包。Tailscale 仍會看到中繼資料,包括機器名稱、擁有者、公開金鑰、端點位址,以及各節點的上線時間。Tailscale 也會分發金鑰,因此遭入侵的協調伺服器可能嘗試加入一個你的節點群組會信任的節點。Tailnet lock 會要求由你自己的受信任節點簽署,阻止這類情況;Headscale 則將代管的控制平面移除。

Tailscale 需要開放防火牆連接埠嗎?

幾乎不需要開放入站連線。Tailscale 的官方說明是:「大多數情況下,你不需要開放任何防火牆連接埠。」在出站方向,節點需要透過 TCP 443 連線至協調伺服器與 relay,並透過 UDP 3478 使用 STUN。直接通道使用 UDP,來源連接埠預設為 41641。開放 UDP 41641 的入站連線是選擇性的,只能協助直接連線在複雜的網路環境中成功建立。

為什麼其他節點無法連線到我在 port 3000 上的服務?

先使用 ss -tlnp 檢查繫結位址。監聽 127.0.0.1:3000 的 socket 只接受 loopback 目的位址,因此會拒絕送往節點 100.x tailnet 位址的連線,客戶端會看到 Connection refused。請將服務繫結至 tailnet 位址,或執行 tailscale serve 3000 進行代理。如果 listener 已經位於 0.0.0.0,而連線是逾時而非遭拒絕,問題就不是繫結位址。先檢查政策規則與主機防火牆,再檢查網路防火牆,以及任一裝置的驗證是否已過期。

我應該改用 Headscale,而不是 Tailscale 的協調伺服器嗎?

如果裝置拓撲或金鑰分發必須維持在你所控制的基礎架構上,或 tailnet 必須不依賴外部服務即可運作,請使用 Headscale。客戶端與通訊協定相同。代價是你必須自行運作協調伺服器;伺服器中斷時,新節點無法加入,政策變更也無法套用。對小型裝置群組而言,啟用 tailnet lock 的代管控制平面通常是較佳的取捨。