在添加或刪除新設備的情況下,網橋上的網路連接中斷
我目前正在跟踪自定義橋接網路上 docker 容器的連接問題,我可以在不涉及 docker 的情況下將其簡化為 Linux 網路堆棧。
我觀察到的情況如下:我有一個網橋設備,它使用轉發和偽裝連接到外部世界(因此網橋不包含主機的傳出網路介面)。該網橋用於通過長時間執行的程序執行網路操作,該程序僅限於使用網路命名空間和 veth 設備的該網橋(正是 docker 內部所做的)。我們看到的是,每次將(虛擬)網路設備添加到網橋或從網橋中移除時,長時間執行的程序的通信都會中斷。
為了重現我們看到的行為,您可以使用以下程式碼:
#!/bin/bash set -e # teardown function cleanup { set +e brctl delif brtest vethtest0 ip link del vethtest0 iptables -t nat -D POSTROUTING -j MASQUERADE -s 10.12.10.0/24 -d 0.0.0.0/0 iptables -D FORWARD -i brtest -o enp0s31f6 -j ACCEPT iptables -D FORWARD -o brtest -i enp0s31f6 -j ACCEPT ip link delete veth0 ip link set down brtest brctl delbr brtest ip netns del test } trap cleanup EXIT ip netns add test brctl addbr brtest ip addr add 10.12.10.1/24 dev brtest ip link set up dev brtest ip link add veth0 type veth peer name veth1 ip link set veth1 netns test brctl addif brtest veth0 ip link set up dev veth0 ip netns exec test ip addr add 10.12.10.42/24 dev veth1 ip netns exec test ip link set up dev veth1 ip netns exec test ip route add default via 10.12.10.1 dev veth1 # change external interface name iptables -A FORWARD -o brtest -i enp0s31f6 -j ACCEPT iptables -A FORWARD -i brtest -o enp0s31f6 -j ACCEPT iptables -t nat -A POSTROUTING -j MASQUERADE -s 10.12.10.0/24 -d 0.0.0.0/0 while true; do ip netns exec test python3 -c "import socket; socket.gethostbyname('example.org')" && echo success; sleep 1; done
這設置了網橋、veth 設備、網路命名空間和 iptables 規則以復製網路設置,並通過在 while 循環中定期執行(易失性)UDP DNS 請求來模擬長時間執行的過程。
啟動此腳本時,所有 DNS 請求都應該成功,並且您應該
success
定期看到消息。要模擬設備加入和離開網橋,您可以在第二個 bash 中啟動以下程式碼:
while true do echo "next" ip link add vethtest0 type veth peer name vethtest1 brctl addif brtest vethtest0 sleep 2 brctl delif brtest vethtest0 ip link del vethtest0 sleep 1 done
一旦執行,您可以觀察到 DNS 請求會經常延遲,其中一些甚至會失敗。在並行 pcap 中,您會看到有時來自 DNS 查找的 UDP 包不會路由到外部世界,而是最終到達橋接設備而不會離開主機系統。
有人可以解釋這裡發生了什麼以及為什麼向網橋添加和刪除設備會導致連接問題嗎?如何避免它們?
在聯繫了 Linux 核心的 netdev 郵件列表後,Ido Schimmel 提供了解開這個謎團的重要資訊:
網橋的 MAC 地址(在您的範例中為“brtest”)是從具有“最小”MAC 地址的網橋埠繼承的。因此,當您生成具有隨機 MAC 的 veth 設備並將它們從屬於網橋時,您有時也會更改網橋的 MAC 地址。由於網橋是預設網關,因此有時數據包會發送到錯誤的 MAC 地址。