Files
netbird-selfhosted/client-troubleshooting.md
timmy c5a8757da4 docs: add client-side troubleshooting (Force Relay, bufferbloat)
Document the 'Force relay connection' switch that silently disables
ICE gathering on iOS NetBird (and similar on macOS), which was the
real cause of all peers showing Connection type: Relayed despite
STUN being correctly configured.

Also document bufferbloat diagnosis via macOS networkQuality, which
was a red herring during the P2P investigation (large RTT spikes
were the WiFi/ISP, not NetBird).
2026-04-18 10:40:04 +08:00

4.4 KiB
Raw Blame History

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。

容易猜錯的方向

  • 怪 STUNDNAT、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 → Connectnetbird 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 typeRelayed 變成 P2P 就成功。

高 RTT 大幅波動:先排除 bufferbloat

症狀

ping <peer-ip> 結果像這樣:

round-trip min/avg/max/stddev = 220.423/2230.078/4238.380/1420.726 ms

平均 2 秒、尖峰 4 秒。看起來像 NetBird 出問題。

診斷

在 macOS 跑:

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 啟用 SQMOpenWrt 上裝 luci-app-sqm
  • 短期:避免在背景下載大檔時測 NetBird 延遲

客戶端配置驗證 checklist

當你覺得「明明設定都對,但 NetBird 行為怪怪的」,依序檢查:

# 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 <peer-fqdn>

# 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 <peer-netbird-ip>

如果 7 通但 4 是 Relayed 且 5 是 -/- → 99% 是 Force Relay 開著(見上)。

各平台 NetBird Settings 裡會踩雷的開關

開關 開啟後果
Force relay connection 永遠走 RelayP2P 失效
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 / 個人裝置之間互通,沒理由開