程式會自己判斷「網路壞了」該怎麼辦,但你要怎麼讓網路聽話地壞掉:認識 ghostwire
10 月 31 日,開發者 tarsxiaode 在 V2EX 的分享創作板發布了一個名為 ghostwire 的開源工具,標題寫得很直白:在 Linux 上偽造 ping、TCP、UDP、DNS 的回應,用來測試依賴網路狀態的程式。專案原始碼放在 GitHub(nanmuyao-tools/ghostwire),以 Go 撰寫,依賴只有標準庫加一個 YAML 解析庫。
它解決的問題,比聽起來更常見
很多程式的行為取決於網路狀態。連線資料庫前先 ping 一下、解析網域挑最快的節點、請求失敗就重試或切換備援、連不上就在介面上顯示「離線」。這些分支邏輯平時不會被觸發,因為開發環境的網路通常好好的。
要測這些邏輯,你得讓網路在你指定的時刻變慢、斷線或不可達,而且每次測試都要能重現同樣的條件,否則昨天修好的 bug 今天對不上號。這正是 ghostwire 針對的場景。
運作機制:接管一段位址,讓核心替你說謊
ghostwire 的做法是建立一個 TUN 裝置,接管你指定的位址段。TUN 是 Linux 的一種虛擬網路介面,可以想成在系統裡開了一扇「假門」:凡是目的地落在指定位址段的封包,都會被送到這個使用者空間的程式手上,由它決定怎麼回應。
因為攔截發生在網路層,程式完全不用改程式碼。不管它是呼叫系統的 ping 指令,還是自己組原始 ICMP 封包,看到的都是同一套被偽造的網路行為。規則可以按位址和埠設定,例如一條規則給某個 IP 加 50ms 延遲,另一條把某個 IP 設成不可達,執行中的規則還能透過 HTTP API 即時修改。它也支援設定隨機種子,讓丟包或延遲的隨機行為可以重現。
原帖給的例子長這樣:
ghostwire exec -rule 10.99.0.1=50ms -rule 10.99.0.2=unreachable — ./my-app
也就是帶著兩條規則啟動 my-app,一個目標變慢、一個目標直接不通。
和既有工具的差別在哪
Linux 上做網路模擬不是新鮮事,重點在攔截的位置不同。tc netem 是在網卡上做流量整形,影響的是經過那張卡的流量,粒度不在「目標位址」這一層。Toxiproxy 則是 TCP 代理,程式必須改成連到代理的位置,模擬才會生效。ghostwire 選的是第三條路:按目標位址接管、對程式完全透明、不需要改連線設定。這個差異對測試既有程式碼特別有用,因為大多數時候你沒辦法為了測試去改動程式的連線邏輯。
另外一個實務細節是權限:exec 模式不需要 root,這對 CI 環境和容器裡的測試流程友善許多。
對誰有用
如果你寫的程式有故障轉移、重試退避、節點選擇或離線偵測這類邏輯,這類工具的價值在於把「很難遇到的情況」變成一行指令就能重現的測試條件。以本案來說,文件提供了中英雙語版本,採用與否可以直接看 GitHub 上的說明自行判斷。至於它與 netem、Toxiproxy 的取捨,回到攔截位置那一段的比較即可:要按目標位址控制且不想改程式,TUN 路線是目前這個工具最明確的賣點。
發文當時該帖尚無回覆,後續的穩定性與社羣回饋,仍待時間累積。