Linux-Networking

Linux 透明網橋:dhclient 殺死所有流量

  • June 9, 2017

我在使用 Hypriot OS 時遇到了一個非常奇怪的情況。

網路配置:

+--------+  +------+-----+------+  +---------------------+  +-------+
+ laptop +--+ eth0 + br0 + eth1 +--+ router @ 10.98.76.1 +--+ tower +
+--------+  +------+-----+------+  +---------------------+  +-------+
                        |
                        +-------+     +----------------------+
                        + wlan0 +-----+ router @ 192.168.0.1 +
                        +-------+     +----------------------+

我實際上是在嘗試讓 Raspberry Pi 充當我的筆記型電腦和路由器之間的中間人。我將 eth0 和 eth1 連接到在啟動時創建的網橋 (br0)。eth0、eth1 和 br0 都在名為“foo”的網路命名空間中。wlan0 是預設命名空間中的主要競爭者——docker 目前被禁用,而它通常會在預設命名空間中創建一個 docker0 網橋。

我將 eth0 和 eth1 推送到不同的網路命名空間,以確保 wlan0 可以執行 ssh 客戶端,並且只有wlan0 正在執行所述客戶端——我不希望硬連線介面在任何情況下都使用 ssh 客戶端。

我正在使用“device-init.yaml”(device-init 的一部分)來啟動我的網路配置腳本。

我的網路配置腳本如下:

# Create a new namespace for the ethernet devices
ip netns add foo

# Create the bridge in the foo namespace and bring it up
ip netns exec foo ip link add name br0 type bridge
ip netns exec foo ip link set dev br0 up

# Bring down the ethernet devices
ip link set dev eth0 down
ip link set dev eth1 down

# Move the eth0/eth1 devices to the foo namespace
ip link set dev eth0 netns foo
ip link set dev eth1 netns foo

# Add the eth0/eth1 devices to the bridge
ip netns exec foo ip link set dev eth0 master br0
ip netns exec foo ip link set dev eth1 master br0

# Enable promiscuous mode
ip netns exec foo ip link set eth0 promisc on
ip netns exec foo ip link set eth1 promisc on

# Bring up the adapters within the foo namespace
ip netns exec foo ip link set dev lo up
ip netns exec foo ip link set dev eth0 up
ip netns exec foo ip link set dev eth1 up

# List the devices for posterity
netnsout=$(ip netns exec foo ip a)

echo "- Done running ip commands. Result: $netnsout"

啟動完成後,我可以從我的塔上 ping 我的筆記型電腦,從我的筆記型電腦上 ping 我的塔,沒有任何問題。我還可以毫無問題地在筆記型電腦上獲取 IP 地址——網橋正常執行,允許流量通過它。

問題:我無法在 eth1、eth0 或 br0 上執行 dhclient,也無法從 Raspberry Pi 訪問網路中的任何實體。

我執行以獲取 eth1 上的 IP 地址的程式碼:

$ ip netns exec foo dhclient eth1

執行dhclient後的結果:

$ ip netns exec foo ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
   inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
2: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
   link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
   inet6 fe80::60fc:16ff:fe9a:2e26/64 scope link
      valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
   link/ether b8:27:eb:9e:8d:63 brd ff:ff:ff:ff:ff:ff
   inet6 fe80::ba27:ebff:fe9e:8d63/64 scope link
      valid_lft forever preferred_lft forever
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
   link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
   inet 10.98.76.11/24 brd 10.98.76.255 scope global eth1
      valid_lft forever preferred_lft forever
   inet6 fe80::2e0:4cff:fe36:1efb/64 scope link
      valid_lft forever preferred_lft forever

eth1 配置了適當的 IP 地址。

如果我然後 ping 任何我收到“目標主機無法訪問”的內容:

$ ip netns exec foo ping 10.98.76.1 (or .44 for laptop, .55 for tower)

另外,此時我在 wlan0 上沒有外部訪問權限。我可以訪問無線路由器和無線網路上的其他機器,但似乎無法向外戳到網際網路。

作為參考,這裡有更多詳細資訊: arp 表:

$ ip netns exec foo arp
Address        HWtype  HWaddress      Flags Mask  Iface
10.98.76.1             (incomplete)               eth1

路線:

$ ip netns exec foo ip route show all
default via 10.98.76.1 dev eth1
10.98.76.0/24 dev eth1  proto kernel  scope link  src 10.98.76.11

然後我把橋放下:

$ ip netns exec foo ip link set dev br0 down
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
   inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
2: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
   link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
   link/ether b8:27:eb:9e:8d:63 brd ff:ff:ff:ff:ff:ff
   inet6 fe80::ba27:ebff:fe9e:8d63/64 scope link
      valid_lft forever preferred_lft forever
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
   link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
   inet 10.98.76.11/24 brd 10.98.76.255 scope global eth1
      valid_lft forever preferred_lft forever
   inet6 fe80::2e0:4cff:fe36:1efb/64 scope link
      valid_lft forever preferred_lft forever

但是在嘗試 ping 路由器或塔時,我仍然收到“無法訪問目標主機”。此時,由於橋已關閉,我顯然無法從筆記型電腦上做任何事情。

如果我然後刪除網橋,我可以按預期 ping 網路上的所有內容:

$ ip netns exec foo ip link delete dev br0
PING 10.98.76.1 (10.98.76.1) 56(84) bytes of data.
64 bytes from 10.98.76.1: icmp_seq=1 ttl=127 time=1.71 ms
64 bytes from 10.98.76.1: icmp_seq=2 ttl=127 time=0.894 ms
64 bytes from 10.98.76.1: icmp_seq=3 ttl=127 time=0.873 ms

在這一點上,我很難過。完全相同的設置適用於 Raspbian,但不適用於 Hypriot。以下 gitter看起來與我的情況幾乎相同,但是我沒有重複的設備:https ://gitter.im/hypriot/talk/archives/2016/06/02

我嘗試過的其他沒有結果的事情: - 關閉 eth0 和 eth1 promisc - 打開 br0 promisc - 在 /etc/netns/foo/resolv.conf 中創建自定義 resolv.conf - arping(見下文)

$ ip netns exec foo arping -A -I eth1 10.98.76.11
ARPING 10.98.76.11
Timeout
Timeout
Timeout
Timeout
Timeout

**我的主要目標是讓 Raspberry Pi 上的 eth1 採用與我的筆記型電腦相同的 IP 和 MAC。**這樣做時,它仍應將流量向內傳遞到我的筆記型電腦,並尊重我的筆記型電腦可能有的任何 dhcp 請求等。我最終將嘗試在我的 Raspberry Pi 和塔之間建立一個 vpn 隧道,並且仍然需要數據包讓它通過Raspberry Pi 進入我的筆記型電腦,但這將在我讓橋接器/設備正常工作之後發生。

重申一下:這在 Raspbian 上*確實有效,這讓我很困惑。*請讓我知道是否需要更多資訊,例如執行服務(除了 Hypriot 的預設設置,當然我確實禁用了 docker)等。

更新

根據wiebel的回答,我能夠解決最初無法解決的問題。我不知道它如何/為什麼在 Raspbian 上工作,因為它真的不應該工作。

如果它可能對未來的溢出者有用,我將在下面發布我想做的工作/正確的方法:

# Ensure the traffic we send to the laptop goes through the right device
ip netns exec foo route add 10.98.76.44 dev eth0

# Enable forwarding on both devices
ip netns exec foo sysctl net.ipv4.conf.eth0.forwarding=1
ip netns exec foo sysctl net.ipv4.conf.eth1.forwarding=1

# Enable arp proxying on both devices
ip netns exec foo sysctl net.ipv4.conf.eth0.proxy_arp=1
ip netns exec foo sysctl net.ipv4.conf.eth1.proxy_arp=1

# Reload
ip netns exec foo sysctl --system

# Flush arp
ip netns exec foo -s -s neigh flush all

# Aggressively flush arp (the one above would do it, but this seems to be quick and thorough):
ip netns exec foo ip link set arp off dev eth0
ip netns exec foo ip link set arp off dev eth1
ip netns exec foo ip link set arp on dev eth0
ip netns exec foo ip link set arp on dev eth1

執行上述操作後,我可以毫無問題地訪問/訪問網路上的所有設備。

一旦介面成為網橋中的成員,您就無法為介面本身分配 IP 地址,您需要為網橋設置地址。橋接-stp-howto

引用自:https://serverfault.com/questions/854563