From f091499ff387c8b3175343e4145d9517c575b3a6 Mon Sep 17 00:00:00 2001 From: Timmy Date: Sat, 18 Apr 2026 23:39:36 +0800 Subject: [PATCH] docs: add NetBird exit nodes via CT100 (TW) and virmach-lax (US) Covers 0.0.0.0/0 route creation, opt-in client-side selection (different from subnet routes which auto-apply), and the extra trust exposure when routing through a third-party VPS. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 2 +- SUMMARY.md | 2 +- network-routes.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a4ed36..03f93a0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ | [client-troubleshooting.md](./client-troubleshooting.md) | 客戶端 P2P 失敗、bufferbloat、Force Relay 等坑 | | [peer-deployment-ops.md](./peer-deployment-ops.md) | 在 LXC 用 Docker 部署客戶端、改名、Mac daemon 重啟 | | [groups-and-policies.md](./groups-and-policies.md) | Groups 與 Access Control Policies 概念、設計、API 操作 | -| [network-routes.md](./network-routes.md) | Subnet Router:讓遠端 peer 存取 LAN 上沒裝 NetBird 的裝置 | +| [network-routes.md](./network-routes.md) | Subnet Router(`home-lan`)與 Exit Nodes(`exit-ct100`、`exit-virmach-lax`) | | [ssh-access.md](./ssh-access.md) | 一般 SSH vs NetBird 內建 SSH — 常見混淆點釐清 | | [SUMMARY.md](./SUMMARY.md) | 部署摘要與疑難排解記錄 | diff --git a/SUMMARY.md b/SUMMARY.md index 20a8f7e..c7d806d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -108,7 +108,7 @@ reopen fd 8: permission denied ├── client-troubleshooting.md ← 客戶端 Force Relay / bufferbloat 排錯 ├── peer-deployment-ops.md ← Docker 部署客戶端、改名、Mac daemon 重啟 ├── groups-and-policies.md ← Groups 與 Access Control 設計與操作 -├── network-routes.md ← Subnet Router 讓 peer 存取 LAN 非 NetBird 裝置 +├── network-routes.md ← Subnet Router (home-lan) 與 Exit Nodes (exit-ct100、exit-virmach-lax) └── ssh-access.md ← 一般 SSH vs NetBird 內建 SSH 的差別 ``` diff --git a/network-routes.md b/network-routes.md index 5975fee..bcfe69c 100644 --- a/network-routes.md +++ b/network-routes.md @@ -198,6 +198,99 @@ lxc.cgroup.devices.allow: a # 或其他合適設定 **本部署避開這問題的方式:選 CT100(Tailscale userspace)當 routing peer**,不選 CT124。 +## Exit Nodes(`0.0.0.0/0` 路由) + +Exit node 是 subnet router 的特例:CIDR 改成 `0.0.0.0/0`,讓選擇此路由的 peer 把**所有**網際網路流量經由該 routing peer 出去(等同 Tailscale 的 Exit Node、WireGuard 的 `AllowedIPs = 0.0.0.0/0`)。 + +### 本部署的 Exit Nodes + +| Network ID | Routing Peer | 出口 IP | 用途 | +|-----------|-------------|--------|------| +| `exit-ct100` | CT100 (`ct100.netbird.selfhosted`) | HiNet `125.229.110.50` (TW) | 家用、回家連 LAN 順便 | +| `exit-virmach-lax` | virmach-lax (`virmach-lax.netbird.selfhosted`) | VirMach `141.11.93.252` (US LAX) | 美國 IP、bypass 地理限制 | + +兩條設定一致(只差 `peer`): + +- CIDR: `0.0.0.0/0` +- Distribution Groups: `personal` — 只推給 Mac/iPhone。**不推給 `servers`**,避免 CT101 拿到 `0.0.0.0/0` 繞回自己或另一個 server +- Access Control Groups: `personal`, `servers` +- Masquerade: on +- Metric: 9999(與 home-lan 一致,僅限兜底) + +### 建立方式(API) + +跟 home-lan 流程一樣(需 routing peer 先開 IP forwarding),只是 `network` 改 `0.0.0.0/0`、`network_id` 改成識別用名稱: + +```bash +TOKEN=<你的 PAT> +CT100_PEER_ID="<從 GET /api/peers 查>" +VIRMACH_PEER_ID="<從 GET /api/peers 查>" +PERSONAL_GID="" +SERVERS_GID="" + +curl -X POST -H "Authorization: Token $TOKEN" -H "Content-Type: application/json" \ + -d "{ + \"description\": \"Exit node via CT100 (home, TW IP)\", + \"network_id\": \"exit-ct100\", + \"network\": \"0.0.0.0/0\", + \"peer\": \"$CT100_PEER_ID\", + \"masquerade\": true, + \"metric\": 9999, + \"enabled\": true, + \"groups\": [\"$PERSONAL_GID\"], + \"access_control_groups\": [\"$PERSONAL_GID\", \"$SERVERS_GID\"] + }" \ + https://netbird.timmy.us.kg/api/routes | jq + +# 同樣的 payload 把 network_id 換成 exit-virmach-lax、peer 換成 VIRMACH_PEER_ID 再打一次 +``` + +### Client 端:exit node 是 opt-in + +**關鍵差異**:subnet route(如 home-lan)收到就自動進路由表,`0.0.0.0/0` 不一樣 — client 收到後**不會自動啟用**,使用者要明確 select 才會把預設路由切過去: + +**macOS / Linux CLI**: +```bash +netbird routes list +# 看到兩條 exit-* 初始都是 "Not selected" + +netbird routes select exit-virmach-lax # 切到美國出口 +netbird routes select exit-ct100 # 或切回家裡出口 +netbird routes deselect exit-virmach-lax # 取消,回成直連上網 +``` + +**macOS App / iPhone App**:tray / App → **Exit Node** → 選一個或 `None`。UI 是 radio button(同時選兩條 `0.0.0.0/0` 沒意義,metric 一樣路由表只留一條)。 + +### 驗證出口 IP + +```bash +# 選 exit-virmach-lax 後 +curl -4 ifconfig.me +# → 141.11.93.252 + +# 選 exit-ct100 後 +curl -4 ifconfig.me +# → 125.229.110.50 + +# deselect 或 None +curl -4 ifconfig.me +# → 本地網路的出口 IP(咖啡店的、機場的等) +``` + +### 看不到 exit route 的排查 + +Client 已連線但 `netbird routes list` 沒有 `exit-*`: + +1. Daemon 啟動早於 route 建立 → 重啟 daemon(見 `peer-deployment-ops.md` 的 launchctl / systemctl 段) +2. 該 peer 不在 route 的 `groups`(distribution)裡 — 目前只 `personal` 拿得到,`servers` 看不到 +3. Policy 擋住 — `access_control_groups` 必須包含 client 所在 group + +### 額外風險(相對於 subnet router) + +- **Exit peer 看得到所有流量的元資料**:HTTPS 內容仍 E2E 加密,但 DNS 查詢、SNI、流量時序全部對 routing peer 可見 +- **virmach-lax 是第三方 VPS**:VirMach 營運者理論上可在 host 上 tcpdump `wt0`。比 CT100(自家硬體)多一層信任假設。敏感操作(銀行、公司 VPN)仍建議走 `None` 或 `exit-ct100` +- **不要讓 servers group 拿到 `0.0.0.0/0`**:伺服器自己繞 exit node 出網會產生 loop 或不必要延遲 + ## 安全考量 **Routing Peer 被攻破 = 攻擊者能透過 overlay 打進家裡所有 LAN 設備。**