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

在 VPS 上執行 Tailscale 子網路由器

從 VPS 將私有網段宣告至 tailnet:核准路由、設定可在重開機後保留的 IP forwarding,並在 Linux 上使用 --accept-routes 旗標。

Tailscale 子網路由器的功能

Tailscale 子網路由器是負責向 tailnet 宣告整段私有 IP 位址範圍的機器,因此 tailnet 上的每台裝置都能連線到該範圍內的位址,即使那些裝置沒有執行 Tailscale。tailnet 是您的私有 Tailscale 網路,也就是登入同一個帳戶或組織的一組裝置。Exit node 是常被混淆的功能,但它執行的是相反的工作。它會將裝置的所有流量經由 VPS 對外傳送,因此 VPS 會成為該裝置連往公用網際網路的路由。

每句話各自說明一件事。子網路由器會讓 tailnet 連線到一個私有網路。Exit node 會改變公用流量的對外出口。若您需要的是後者,請改讀如何在 VPS 上執行 Tailscale exit node。這兩項功能使用不同的旗標;同一台 VPS 可以同時提供兩者,但它們解決的是不同問題,故障原因也不同。

VPS 需要子網路由器的情況

常見情況是供應商已提供私有網路。VPS 具有公開位址,並透過第二個介面連線至私有網段;該網段上的其他伺服器完全沒有公開位址,例如位於 10.0.0.20 的資料庫,以及位於 10.0.0.30 的備份目標。只要在一台 VPS 上安裝 Tailscale 並宣告 10.0.0.0/24,筆記型電腦就能直接連線至這些私有位址。網段上的其他設定都不必變更,資料庫仍然沒有公開位址。如果你只需要存取該網段上一個連接埠的一個 Web 應用程式,宣告整個範圍就超出實際需求;此時可改用 Tailscale serve,在該單一連接埠上提供 HTTPS。相同的原則也適用於刻意只繫結至 localhost 的 daemon,例如在 systemd 下以無頭模式執行的 dsh。此時,該 VPS 上的 tailnet 位址可取代原本為了存取其 UI 而必須持續開啟的 SSH tunnel。

另一種情況是 VPS 另一側的網路。這可以是由自身路由器連線至網路的家庭或辦公室 LAN (local area network),也可以是完全無法執行 Tailscale 的設備網路,例如受管理交換器或韌體受鎖定的舊 NAS。該網路上的一台 Linux 主機會成為其他所有設備的子網路由器。在家中,這台主機通常是已在使用的 hypervisor 上執行的小型 VM;在決定服務應位於 tunnel 的哪一端之前,應先釐清家用 Proxmox 主機與租用 VPS 的成本比較。

這兩種情況都有一項共同要求。子網路由器必須已能使用自身的 routing table 與 firewall 存取它所宣告的範圍。Tailscale 不會建立這條連線。它只會將流量傳送至路由器,再交給 kernel 進行轉送。

安裝 Tailscale,並先檢查本機路由

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

此指令碼會偵測發行版、加入 Tailscale 的套件儲存庫、安裝 tailscale 指令與 tailscaled daemon,然後啟用服務。使用 systemctl is-active tailscaled 確認結果;該指令應輸出 active。

在進行其他操作前,先確認 VPS 能連線至您計畫宣告的網路。

ip route show
ping -c3 10.0.0.20

ip route show 必須在實體介面上列出私有網段,例如 10.0.0.0/24 dev enp7s0 proto kernel scope link src 10.0.0.5。如果在這裡執行 ping 失敗,也就是無法連線至路由器本身,任何 Tailscale 旗標都無法修正問題。問題出在 VPS 的網路設定,或目標主機上的防火牆。請先修正,因為後續所有測試都依賴這項連線。

啟用 IP forwarding,並讓設定在重新開機後保留

Linux 機器在未啟用 forwarding 時,會丟棄所有目的地不是本機的封包。轉送其他機器的封包是子網路由器的主要工作,因此這個步驟不能省略。

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

使用 sysctl net.ipv4.ip_forward 檢查。該命令應輸出 net.ipv4.ip_forward = 1。

許多人只完成了這個步驟的一半。sudo sysctl -w net.ipv4.ip_forward=1 會立即生效,但下一次開機時就會消失。因此,子網路由器可能持續運作數週,卻在核心升級後重新開機的隔天早上停止運作。令人困惑的是,表面上看不出任何故障。tailscale status 仍顯示節點在線上,管理主控台仍顯示路由已核准,客戶端也仍保有已安裝的路由。封包抵達 VPS 後,核心會直接丟棄它們,且不會記錄任何日誌。將這些值寫入 /etc/sysctl.d/99-tailscale.conf,才能讓設定在重新開機後恢復。

如果在 forwarding 仍然關閉時宣告路由,tailscale up 會當下發出警告,並顯示一行接近 Warning: IPv4 forwarding is disabled. Subnet routes and exit nodes may not work correctly. 的內容。請閱讀該命令的輸出,不要直接略過。

宣告路由

sudo tailscale up --advertise-routes=10.0.0.0/24

在已登入 tailnet 的 VPS 上,請直接變更現有設定:

sudo tailscale set --advertise-routes=10.0.0.0/24

後續每次變更都使用 tailscale set。再次執行 tailscale up 時,如果只帶入單一旗標,未再次指定的旗標會被重設;CLI 也會顯示錯誤,指出以這種方式變更設定時,必須列出所有非預設旗標。tailscale set只會變更指定設定,並保留其他設定不變。

多個範圍要放在同一個逗號分隔清單中,且不得包含空格:--advertise-routes=10.0.0.0/24,192.168.50.0/24。每個項目都必須是 CIDR 表示法中的網路位址(無類別網域間路由,亦即 10.0.0.0/24 格式)。如果誤填自己的主機位址,例如 10.0.0.5/24,系統會拒絕,因為前綴之後的位元不是 0;錯誤訊息會指出你可能想使用的前綴。若要停止宣告路由,請使用 sudo tailscale set --advertise-routes= 設定空清單。

在管理主控台核准路由

宣告路由是提出請求,不會立即變更設定。在管理員核准之前,不會有任何用戶端收到該路由,該範圍內的任何位址也都無法連線。這是刻意的設計,因為如果任何機器都能將自己加入所有人的路由表,就能攔截任意範圍的網路流量。

請在管理主控台的 Machines 頁面核准路由。VPS 會顯示子網路徽章。開啟該列,找到子網路區段,編輯路由設定,勾選該路由,然後儲存。

核准是以前綴為單位。今天宣告 10.0.0.0/24、下個月宣告 192.168.50.0/24 時,新前綴會維持未核准狀態,而舊前綴仍可正常運作。對 VPS 而言,已核准的路由與遭忽略的路由看起來完全相同,因此在進行其他除錯前,請先檢查主控台。

您可以在 tailnet policy 檔案中加入 autoApprovers 區塊,以略過手動步驟:

{
  "autoApprovers": {
    "routes": {
      "10.0.0.0/24": ["tag:subnet-router"]
    }
  }
}

接著使用該標籤、sudo tailscale up --advertise-routes=10.0.0.0/24 --advertise-tags=tag:subnet-router,啟動節點。路由一經宣告就會立即獲得核准。該標籤必須先存在於同一個 policy 檔案的 tagOwners 區段中。如果您透過指令碼重新建立 VPS,建議先完成這項設定,因為重新建立的節點會被視為新節點,其路由會再次從未核准狀態開始。

Linux 用戶端為何在未使用 --accept-routes 時忽略路由

路由現在已經公告並核准。你的手機和 Mac 可以連線至 10.0.0.20。你的 Linux 筆記型電腦卻無法連線,管理主控台也沒有顯示任何問題。

接受子網路路由,表示要將路由項目寫入用戶端的路由表。在 Android、iOS、macOS、tvOS 和 Windows 上,Tailscale 用戶端會代為處理。Linux 不會這樣做,因為 Linux 電腦通常是伺服器或路由器,其路由表可能是管理員刻意設定的;若系統無提示地插入從網路學習到的 /24,可能會中斷該電腦原本處理的流量。因此,在 Linux 上必須於每個用戶端個別選擇啟用:

sudo tailscale set --accept-routes

接著確認路由加入的位置:

ip route show table 52
ip route get 10.0.0.20

Linux 上的 Tailscale 不會將已接受的路由放入主要路由表,而是放入路由表 52,並安裝原則規則。使用 ip rule show 可查看優先順序介於 5210 至 5270 的規則;這些規則會將未符合其他規則的封包送往該路由表。因此,單獨執行 ip route show 永遠不會列出 10.0.0.0/24,只檢查這個指令的讀者就會以為 --accept-routes 沒有作用。ip route show table 52 才是顯示實際狀態的指令,其中應列出 tailscale0 上公告的範圍。

有一個例外需要注意。如果這個 Linux 節點本身也是其所在區域網路的第二台子網路路由器,--accept-routes 會使它將前往自身直接連線子網路的流量,經由另一台路由器送出,而不是從自己的介面送出。在高可用性配對中的備援路由器上,請停用 --accept-routes,只進行路由公告。

失效模式:兩台路由器公告重疊範圍

兩台子網路路由器不得公告完全相同的範圍。不同前綴長度的重疊範圍可以使用,Tailscale 會選擇最具體的匹配項目。若路由器 A 公告 10.0.0.0/24,路由器 B 公告 10.0.0.0/16,則前往 10.0.0.20 的流量會經由 A 傳送。

A 離線時的行為常令人困惑。Tailscale 不會改用較不具體的路由。前往 10.0.0.20 的流量會中斷,但前往 10.1.0.20 的流量仍可經由 B 傳送。表面上看起來像是私有網路有一半停止運作,實際原因是某個離線節點持有較具體的前綴。若要實作容錯移轉,請讓較寬的路由器也公告較窄的前綴,讓兩者涵蓋相同的位址。

另一種重疊發生在更接近用戶端的位置。當你在 192.168.1.0/24 的飯店網路上,而子網路路由器公告 192.168.1.0/24 時,兩者會爭用相同的目的地;實際採用哪一個,取決於平台。在 Linux 上,請在 Tailscale 自有規則之前安裝規則,讓本機位址使用 main table:

sudo ip rule add to 192.168.1.0/24 priority 2500 lookup main

該規則不會持久保存,下一次開機時便會消失。根本解決方法是選擇一個不會在外部網路遇到的私有範圍。大多數家用路由器預設使用 192.168.0.0/24 和 192.168.1.0/24,因此請在 10.0.0.0/8 內刻意選擇一段範圍。相同的衝突也會影響手動設定的純 WireGuard VPN,原因相同:較具體的本機路由會勝出,因此流量不會進入通道。

失效模式:DNS 解析到沒有任何路由涵蓋的位址

這種問題很難除錯,因為沒有任何元件回報錯誤。名稱可以解析,但連線會逾時。

假設 db.internal.example.com 透過您的私有 nameserver 解析為 10.0.5.20,而您公告了 10.0.0.0/24。查詢會成功,因為 DNS(domain name system)解析與 IP routing 是分開的步驟,兩者都不會互相檢查。接著,前往 10.0.5.20 的封包在 tailnet 上找不到符合的路由,因此會經由用戶端的預設 gateway 離開並消失。

使用以下兩個命令分別檢查這兩個部分:

nslookup db.internal.example.com
ip route get 10.0.5.20

如果查詢傳回位址,但 ip route get 沒有以 dev tailscale0 回應,表示名稱沒有問題,缺少的是路由。請公告涵蓋該位址的範圍,可以使用 10.0.0.0/16 或另外指定一個明確的 prefix,然後在主控台核准新的 prefix。

nameserver 本身也有一個相同的陷阱。如果您在管理主控台中,將全域 nameserver 設為 10.0.0.53 這類私有位址,該位址必須位於已核准的路由內,否則裝置根本無法連線到 resolver。若您在指向無法連線的 resolver 時,啟用覆寫本機 DNS server 的選項,整個 tailnet 的每台裝置都會立即失去名稱解析,包括前一秒仍能正常運作的裝置。請先公告並核准前往 resolver 的路由,再變更 DNS 設定。如果您一直在處理 tunnel 內的 DNS 問題,WireGuard tunnel 中 DNS 發生問題的原因說明了相同的機制,但不涉及上層的協調層。

來源 NAT 與站點對站點連線

根據預設,子網路路由器會將每個轉送封包的來源位址改寫為自己的私有位址。這就是 SNAT(來源網路位址轉換)。這樣做可讓回應正常返回,無須修改私有網路上的任何設定:10.0.0.20 的資料庫會回應 VPS,因為它原本就知道如何連線至 VPS。代價是資料庫會將所有 tailnet 連線視為來自 VPS,因此無法透過來源防火牆規則和存取日誌辨識個別來源。

如果要保留用戶端實際的 tailnet 位址,可在 Linux 上關閉這項功能:

sudo tailscale set --snat-subnet-routes=false

此時,私有網路上的主機需要新增返回 100.64.0.0/10 的路由。100.64.0.0/10 是 Tailscale 指派給裝置的位址範圍,路由的下一站必須指向子網路路由器。若沒有這條返回路由,主機的回應會送往預設閘道,無法抵達來源,因此連線會在送出第一個封包後停滯。請在私有網路的閘道上新增靜態路由,或維持 SNAT 啟用。

站點對站點連線會同時使用兩台子網路路由器。每台路由器都公告自己的網路,並接受對方公告的網路:

sudo tailscale up --advertise-routes=10.0.0.0/24 --snat-subnet-routes=false --accept-routes

在另一台路由器上執行對應的命令,並改用該路由器自己的位址範圍。兩個位址範圍必須不同。若 ssh 和 ping 都正常,但大型傳輸會停滯,原因通常是 MSS(最大分段大小)設定。MSS 是 TCP 封包可攜帶的最大資料區塊。通道額外的封裝開銷會使轉送封包過大,超過中間某個網路鏈路的限制。設定 MSS clamping 可修正此問題:

sudo iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

使用 iptables-persistent 儲存這條規則,否則下次開機時規則會消失。

維持服務運作的例行維護

截至 August 2026,Node key 預設會在 180 days 後到期。Subnet router 上的 key 到期時,該 node 會登出,整個廣告的路由範圍也會變得無法連線,而且其他地方沒有任何設定變更可解釋這個問題。請在管理主控台的 Machines 頁面停用這台機器的 key expiry,並記錄已完成此操作。

Tailscale 會優先在對等節點之間建立直接連線,無法建立時才會改用 relay server。Relay server 可以正常運作,但會增加延遲。使用具有公開位址的 VPS 時,情況最簡單:允許輸入 UDP 41641 後,大多數對等節點都能直接連線。當前往 private range 的流量比 VPS 連線理應提供的速度更慢時,首先應檢查 client 是否直接連到 subnet router,或是透過 relay 連線。如果由 ufw 管理防火牆,VPS 實際需要的 ufw 規則會說明所需語法。

存取規則是另一個部分。在預設的 tailnet 中,你的每台裝置都能連到其他裝置,因此核准的路由可直接運作。建立 ACL policy 後,規則的目的端必須指定 private range,因為 10.0.0.20 不是 tailnet 位址,也不受以 tailnet IP 或 tag 撰寫的規則涵蓋。

最後,請決定是否接受使用不由你管理的 coordination server。Tailscale 的 control plane 是代管服務。你的 key 會留在自己的機器上,但 account 與 policy file 會存放在該服務中。在讓它取得通往 private network 的路由前,應先評估 control plane 遭入侵或 identity login 被竊時,攻擊者實際能進行哪些操作;Tailscale 的 trust model 說明了這項信任邊界的位置。Cost 通常不是使用者離開 Tailscale 的主要原因,因為free plan 支援最多 six users,且每位使用者可使用 unlimited devices。不過,以 tag 啟動的 subnet router,與以你的身分登入的 subnet router 計算方式不同。超過該限制後,費用會依人數而非機器數量計算。因此,在新增會使你超出限制的 account 前,應先確認家庭或 five person team 在 free plan 用完後實際需要支付的費用。執行Headscale,也就是 self hosted 的 Tailscale control server,可將 control plane 維持在自己的 VPS 上,但必須自行維護。針對相同疑慮的另一個選擇,是連 Tailscale 的 client 也一併捨棄;self-hosting NetBird VPN server 可將 coordination layer 與其 mesh client 放在一台由你控制的機器上。如果你仍在這個模型與手動撰寫設定檔之間猶豫,WireGuard 與 Tailscale 的比較會說明 coordination layer 提供哪些功能,以及需要付出哪些代價。

FAQ

子網路由器與出口節點有何不同?

子網路由器會公告一段私有位址,讓 tailnet 裝置連線至未執行 Tailscale 的機器。出口節點則會公告自己是通往整個網際網路的路由,讓裝置將所有網路流量經由該節點的公開位址送出。同一台 VPS 可以同時擔任兩者。兩者使用不同的旗標:--advertise-routes 和 --advertise-exit-node,且各自都必須在管理主控台中核准。

為什麼 Linux 用戶端忽略公告的子網路路由?

Linux 用戶端不會接受子網路路由,除非明確要求它接受。在用戶端執行 sudo tailscale set --accept-routes。接著使用 ip route show table 52 檢查,不要使用 ip route show。Tailscale 會將已接受的路由安裝在 routing table 52,並透過政策規則存取這些路由。因此,主路由表不會列出它們,正常運作的路由看起來就像遺失了一樣。

我的子網路在重新開機後停止運作。哪裡出問題?

最可能是 IP forwarding。使用 sysctl -w 設定的值不會在重新開機後保留,因此請將它寫入 /etc/sysctl.d/99-tailscale.conf,再使用 sysctl net.ipv4.ip_forward 確認。如果 forwarding 已啟用,但該範圍仍無法連線,請在管理主控台中查看該節點。Node keys 預設會在 180 days 後過期,過期的子網路路由器看起來像是網路故障,而不是帳戶問題。

兩個子網路路由器可以公告相同的範圍嗎?

不能公告完全相同的範圍。前綴長度不同的重疊範圍沒有問題,系統會優先使用最具體的路由。但實作容錯移轉時需要特別注意:持有較具體前綴的路由器離線後,Tailscale 不會回退到較寬的路由,因此該流量會停止。若要建立真正的備援組,請讓兩台路由器都公告相同的具體前綴。

主機名稱能解析,但連線逾時。為什麼?

DNS 解析與路由是不同的步驟。名稱可能解析為沒有任何核准路由涵蓋的位址,封包接著會經由用戶端的預設閘道送出。在用戶端執行 ip route get <address>。如果回應不包含 dev tailscale0,請公告涵蓋該位址的範圍,並在管理主控台中核准新的前綴。