# NetBird 客戶端 Troubleshooting 記錄一些不容易猜到的客戶端問題與解法。 ## P2P 永遠打不通:先檢查 `Force Relay Connection` ### 症狀 `netbird status --detail` 顯示: ``` Connection type: Relayed ICE candidate (Local/Remote): -/- ICE candidate endpoints (Local/Remote): -/- Relay server address: rels://... ``` 兩端 ICE candidate 都是 `-/-`、長時間不變,連線可用但永遠走 Relay。 ### 容易猜錯的方向 - 怪 STUN(DNAT、port 衝突、防火牆) - 怪「Block Inbound Connections」 - 怪 iOS 平台限制(NetworkExtension 不支援 P2P UDP) - 怪同 WiFi 下的 hairpin NAT - 怪 Mac 防火牆 以上都檢查無誤後仍然 `Relayed` → **檢查客戶端的 `Force Relay Connection`**。 ### 真正原因 NetBird 客戶端有一個 **「Force relay connection」** 開關。打開後 NetBird 完全跳過 ICE gathering,直接走 Relay。 #### 各平台位置 | 平台 | 路徑 | |------|------| | iOS | App → Settings → Advanced → 最下方「Force relay connection」 | | macOS | 選單列 NetBird → Settings → Advanced Settings(或 menu 內找 Force Relay) | | CLI / daemon | `netbird up` 沒有對應 flag;以 daemon 設定檔方式存在 | #### 修復 1. 把開關關掉 2. App 內 Disconnect → Connect(或 `netbird down && netbird up`) 3. 等 5-10 秒讓 ICE gathering 完成 ### 驗證 P2P 成功 `netbird status --detail` 應顯示: ``` Connection type: P2P ICE candidate (Local/Remote): host/prflx ← 或 srflx/srflx 等組合 ICE candidate endpoints (Local/Remote): 192.168.x.x:51820/192.168.x.x:51820 Latency: ~25 ms ← 同 LAN 應該 <50ms ``` `Connection type` 從 `Relayed` 變成 `P2P` 就成功。 ## 高 RTT 大幅波動:先排除 bufferbloat ### 症狀 `ping ` 結果像這樣: ``` round-trip min/avg/max/stddev = 220.423/2230.078/4238.380/1420.726 ms ``` 平均 2 秒、尖峰 4 秒。看起來像 NetBird 出問題。 ### 診斷 在 macOS 跑: ```bash networkQuality -v ``` 如果輸出: ``` Responsiveness: Low (703 milliseconds | 85 RPM) ``` → **這是你連的 WiFi/ISP 有 bufferbloat**,跟 NetBird 無關。 RPM (Round-trips Per Minute) 應該 >500,<100 算很糟。Bufferbloat 在路由器/modem 有大量佇列堆積時會讓任何流量延遲爆衝。 ### 修復方向 - 換更好的 WiFi AP(支援 SQM / fq_codel / cake) - ISP modem 啟用 SQM(OpenWrt 上裝 `luci-app-sqm`) - 短期:避免在背景下載大檔時測 NetBird 延遲 ## 客戶端配置驗證 checklist 當你覺得「明明設定都對,但 NetBird 行為怪怪的」,依序檢查: ```bash # 1. 客戶端有連到正確的 management server? netbird status | grep Management # 2. STUN 是 Available?(這個案例的 STUN port 是 3479) netbird status --detail | grep -E 'stun:|Relays:' # 3. 看到對方 peer? netbird status --detail | grep -A 1 # 4. Connection type 是 P2P 還是 Relayed? netbird status --detail | grep 'Connection type' # 5. ICE candidate 是什麼類型?(host/srflx/prflx/relay) netbird status --detail | grep 'ICE candidate' # 6. WireGuard 真的有 handshake? netbird status --detail | grep 'Last WireGuard handshake' # 7. 真的能 ping? ping -c 5 ``` 如果 7 通但 4 是 `Relayed` 且 5 是 `-/-` → 99% 是 Force Relay 開著(見上)。 ## 各平台 NetBird Settings 裡會踩雷的開關 | 開關 | 開啟後果 | |------|---------| | **Force relay connection** | 永遠走 Relay,P2P 失效 | | Block Inbound Connections | 對方主動連入會被擋,可能逼成單向 Relay | | Disable Client Routes | 此 peer 不路由到其他 peer | | Disable Server Routes | 此 peer 無法當別人的 router | | Disable LAN Access | 當 exit node 時不能存取 exit node 的本地網路 | | Lazy Connections | 連線延遲建立直到有流量才協商 | | Enable Rosenpass | 量子抗性握手(實驗性,可能與舊 peer 不相容) | 預設值通常是「全部關閉」 — 如果你或別人不小心開了某個,行為就會變得難解釋。 ## 為什麼客戶端版的 docs 不直接寫死「永遠關 Force Relay」 某些情境下強制 Relay 是合理的: - P2P 隱私顧慮(不想暴露真實 IP 給對方 peer) - 對方所在網路有 IDS 會偵測 P2P UDP 流量 - Debug 時希望流量都過 Relay 方便抓 log 所以 NetBird 把它做成可選。**自宅 mesh / 個人裝置之間互通,沒理由開**。