我正在尝试在 Linux 上设置一个隔离的虚拟网络,其中有 2 个虚拟设备通过桥接器连接(在 wsl2 上的 ubuntu linux 中运行)。
我的最终目标是教育:学习更多关于第 3 层网络的知识。现在,我正在尝试编写在原始套接字上运行的 C 代码:我希望有一个应用程序发送数据包,另一个应用程序接收数据包。在我运行我自己的 C 代码之前(我不知道是否写得正确),我想通过使用和tcpdump
(ping -I test_eth1 -b
在以太网套接字上广播 ping -I test_eth1)证明我的 linux 虚拟设备设置正确。我的假设是该ping
命令将放置一个数据包test_eth1
,并且tcpdump
应该接收它,test_eth0
因为test_eth0
和test_eth1
已连接到虚拟交换机。
我已经创建了 2 个通过网桥(test_switch)连接的 tap 设备(test_eth0、test_eth1),如下所示:
ip tuntap add dev test_eth0 mode tap
ip tuntap add dev test_eth1 mode tap
ip link set dev test_eth0 address 00:11:22:33:44:55
ip link set dev test_eth1 address 00:11:22:33:44:56
ip link add name test_switch type bridge
ip link set dev test_eth0 master test_switch
ip link set dev test_eth1 master test_switch
ip link set dev test_eth0 up
ip link set dev test_eth1 up
ip link set dev test_switch up
为了测试此设置,我在 test_eth0 上启动了 tcpdump
tcpdump -i test_eth0 -p -e -A -vv
并在 test_eth1 上运行 ping 广播
ping -I test_eth1 -b 255.255.255.255
我希望 tcpdump 能够看到 ping 数据包。但是 tcpdump 没有捕获任何内容。
brctl show test_switch 输出显示
bridge name bridge id STP enabled interfaces
test_switch 8000.001122334455 no test_eth0
test_eth1
看来开关已启用=否,但是为什么呢?
brctl showstp test_swtich 的输出:
$ sudo brctl showstp test_switch
test_switch
bridge id 8000.001122334455
designated root 8000.001122334455
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 0.00 bridge forward delay 0.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 146.05
flags
test_eth0 (1)
port id 8001 state disabled
designated root 8000.001122334455 path cost 100
designated bridge 8000.001122334455 message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
test_eth1 (2)
port id 8002 state disabled
designated root 8000.001122334455 path cost 100
designated bridge 8000.001122334455 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
答案1
真正的问题是您试图向错误的方向发送数据包。
网络接口自然有两端——例如,以太网接口一端是“eth0”,另一端是 RJ45 插孔;到达 RJ45 连接器的数据包通过 eth0 释放。通过 eth0 发送数据包会让它们通过 RJ45 连接器离开——它们是不是通过同一个 eth0 环回。
TUN/TAP 接口也是如此,它们用于连接到程序(例如某种 VPN 工具),而不是物理电缆。通过“test_eth0”或“test_eth1”接口发送的任何内容都会不是去桥上,因为那已经是面向桥的一侧了——相反,数据包会去通过接口,朝向在另一端等待的程序(在您的情况下,没有。)
如果数据包来自程序连接到 TAP 接口(或者从物理 RJ45 端口,如果 eth0 已在桥接中),那么它们确实会到达桥接器并被转发到另一个桥接端口。
换句话说,TAP 接口不能以这种方式使用。您很可能想要两veth
对 - 因为它们成对出现,并且“电缆”已连接,因此通过 veth0A 发送的任何数据包都将到达 veth0B 并进入网桥。(不过,请参阅 Tom Yan 的评论以了解更多详细信息,尤其是有关网络命名空间的部分。)
看来开关已启用=否,但是为什么呢?
因为桥上实际上没有启用 STP(生成树协议)。
STP 只是一种避免环路的协议(而且是过时的版本;现代网络将使用 RSTP)——它对于桥接器的功能来说并非必需。大多数“仅虚拟”桥接器实际上都禁用 STP,尤其是 Linux 实现的过时版本使用非常长的学习超时(端口可用前的 30 秒延迟)。
更重要的是独立端口显示为“已禁用”。它们被禁用是因为您正在尝试使用“tap”接口,并且正如评论中已经提到的那样,“tap”接口旨在连接到一些处理数据包的程序 - 没有任何处理程序,它相当于没有连接电缆的以太网接口,即无法将数据包发送到任何地方,因此它将在中报告“NO-CARRIER” ip link
。