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).
This commit is contained in:
147
client-troubleshooting.md
Normal file
147
client-troubleshooting.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# 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 <peer-ip>` 結果像這樣:
|
||||
|
||||
```
|
||||
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 <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** | 永遠走 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 / 個人裝置之間互通,沒理由開**。
|
||||
Reference in New Issue
Block a user