This article is not available in English yet. Showing the original.
Also available in: 繁體中文
這篇在寫什麼
記錄一次把家用虛擬機設成 NetBird(自架版)Exit Node 的完整除錯過程。表面症狀只有一個——「一開出口節點就斷網」,但底下其實疊了四層完全不同的問題,一層一層剝開才找到真正的兇手。最後也整理了「中繼連線 vs 直連」與「家用非對稱頻寬」這兩個常被忽略、但影響體感速度最大的概念。
起手式:三個必要條件
要讓某個節點成為 Exit Node,理論上只要做到三件事:
- 開啟 IP 轉發(Linux)
Bash echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf sudo sysctl -p - 後台 Routes → Exit Node:選 Routing Peer、Distribution Groups,保持 Masquerade 開啟。
- Access Control 放行:NetBird 是零信任架構,沒有明確允許的流量一律擋掉,而且方向要記得設成雙向,不然回程封包會被擋。
最常見的入門陷阱
這三步驟只要漏一步,一接上 Exit Node 就會直接斷網——這也是這次故事的開頭。
症狀只有一個,兇手有四個
斷網之後,除錯過程大致長這樣:
每一層單獨看都不難,但因為症狀表現完全一樣(斷網 / 打不開網頁),如果不先用唯讀指令確認現狀,很容易越改越亂。以下展開每一層。
sysctl net.ipv4.ip_forward 是 1,Access Control 也放行了,但還是斷網。
查 iptables -L FORWARD -n -v 發現 NetBird 進出的封包確實被 ACCEPT,流量真的有進來;但查 iptables -t nat -L POSTROUTING 卻完全沒有對外實體網卡的 MASQUERADE 規則,只有 Docker 自己容器網段的規則。
封包被轉發出去了,但沒有偽裝成出口節點自己的 IP,回程的路由器根本不認得 NetBird 的私有位址(100.x.x.x),封包有去無回。補上一行就好:
sudo iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE這台出口節點主機本身裝了 Docker。Docker 為了保護自己的容器網路,會把 Linux 核心的 FORWARD chain 預設策略改成 DROP,並插入自己的 DOCKER-USER / DOCKER-FORWARD 規則鏈——這會連帶影響到其他想借用這台主機轉發流量的服務。
排查方式很單純:sudo iptables -L FORWARD -n -v --line-numbers,直接看 policy 是 DROP 還是 ACCEPT,以及規則鏈裡有沒有 Docker 插入的東西。
IP 層打通後,瀏覽器變成「找不到伺服器 IP 位址」(ERR_NAME_NOT_RESOLVED)。流量雖然能送到外網,但客戶端不知道該用哪個 DNS 伺服器解析網域名稱。
解法:後台 Settings → DNS 新增 Nameserver(例如 8.8.8.8),並在 Domains 填入 .(代表根網域,等於「所有網址都走這個 DNS」)。
這層是整個除錯過程含金量最高的部分。
症狀:一開 Exit Node,netbird status -d 顯示 Management: Disconnected、Peers count: 0/5 Connected,整個 NetBird 直接失聯。
原理:自架版 NetBird 的客戶端,不論做什麼都得持續跟自架控制伺服器保持連線,才能同步金鑰與節點狀態。但只要一啟用 Exit Node,客戶端就會把所有流量(包含連去控制伺服器本身的流量)都導入 0.0.0.0/0 這條路由,塞進 NetBird 的虛擬網卡。於是「維持連線用的控制封包」自己也被導向了出口節點,形成邏輯死循環:要維持連線才能用 Exit Node,但用了 Exit Node 反而切斷了維持連線的通道。
官方雲端版本因為控制伺服器 IP 是寫死在程式裡的,客戶端會自動排除;但自架環境的伺服器 IP 是自訂的,程式不會自動避開,所以只有自架版才會踩到這個坑。
解法:在客戶端手動加一條路由,把「去控制伺服器的流量」強制排除在 Exit Node 之外,走原本的預設閘道:
route add <控制伺服器公網IP> <原本的預設閘道> metric 5 -p(-p 代表永久生效;要復原時 route delete <控制伺服器公網IP> 即可)
先確定現在的設定到底長怎樣,不要一直叫我盲猜著改指令。
這句話其實點出了整個除錯過程最重要的方法論:每一層都先用唯讀指令查現狀(iptables -L ... -n -v、netbird status -d、tcpdump),確認問題出在哪,再動手改,而不是憑猜測亂試。
打通之後:中繼連線 vs 直連
四層問題都解決後,NetBird 終於連上了,但速度很慢。這裡要分清楚兩種連線模式:
- Relayed(中繼):兩端因防火牆/NAT 限制無法直接握手,所有封包都要先上傳到中繼伺服器,再由中繼伺服器轉發給對方——流量繞遠路,還吃中繼伺服器本身的頻寬與 CPU(WebSocket 加解密很吃單核心)。
- Direct(P2P 直連):兩端成功打洞(NAT traversal),直接用原生 WireGuard(UDP)通道傳輸,延遲低、速度快。
要從 Relayed 變成 Direct,通常要在出口節點所在的路由器上做 Port Forwarding,把外部 UDP(WireGuard 預設 51820)轉發到出口節點的內網 IP。
最容易被忽略的一課:家用頻寬的「方向性」
這是整個過程裡最實用、也最容易被忽略的一點——上傳/下載頻寬不對稱時,Exit Node 擺在哪裡,會決定你被誰的哪個方向卡住。
以「家裡下載 300M / 上傳 50M」為例,同一句「透過 Exit Node 上網」在四種情境下,資料實際流動的方向完全不同:
紅色的三條箭頭都是從「家」指出去——不管是你自己上網、還是別人來抓你網站上的檔案,資料都得先從家裡送出去,走的是你家那條窄很多的上傳水管,所以全部卡在 50 Mbps。只有藍色那條箭頭是指進「家」——別人把檔案送進來,吃的是你家下載頻寬,才能跑到 300 Mbps。
一句話原則:只要資料是「離開你家」,不管是哪種應用情境,卡的都是你家的上傳頻寬;只要資料是「進入你家」,吃的才是下載頻寬。這也是為什麼正式對外服務(架站、當 VPN 出口)通常會選對等頻寬(symmetric bandwidth)的 VPS,而不是放在家用非對稱寬頻後面。
整體除錯思路
這次的順序其實是一個很典型也很值得記住的框架:先看有沒有連線(防火牆放行)→ 再看有沒有轉發(FORWARD policy)→ 再看有沒有偽裝(NAT MASQUERADE,讓回程封包找得到路)→ 再看有沒有解析(DNS)→ 最後才看效能(Relayed vs Direct、頻寬方向性)。每一層都先查現狀,再動手改。