虚拟机的 Linux 网桥不转发 IP 数据包(但转发 ARP)

虚拟机的 Linux 网桥不转发 IP 数据包(但转发 ARP)

内核:5.5.8-arch1-1

我正在尝试使用连接到我的物理接口的网桥来使虚拟网络正常工作。这是一个典型的设置,我什至没有尝试做任何事情诡异的

  • 桥:br0
  • 物理接口:enp6s0f0

问题在于 Linux 不会将任何 IP 流量转发出物理接口。正在转发ARP流量双向,因为 ARP 解析有效,但没有 IP 流量从 enp6s0f0 发出

我尝试过的事情:

  • 添加enp6s0f1到网桥,提供enp7s0f0给虚拟机,并使用电缆链接enp7s0f0enp6s0f1
    • 相同的结果(转发 ARP 流量,不转发 IP 流量)
  • 停止 docker 并刷新所有表
    • 不用找了
  • 禁用 rp_filter
    • 不用找了
  • 使用板载 NIC
    • 没有变化(这实际上是初始设置,我将这个四端口卡放入以查看板载网卡是否导致问题)
  • 从另一台机器 ping 虚拟机
    • 我可以看到回显请求来了我可以看到它,br0但它没有转发到 VM 端口(vnet 端口或enp6s0f1
  • 在网桥上启用 STP(最初被禁用)
    • 不用找了
○ → ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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: enp6s0f0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether 00:10:18:85:1c:c0 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::210:18ff:fe85:1cc0/64 scope link 
       valid_lft forever preferred_lft forever
3: enp6s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 00:10:18:85:1c:c2 brd ff:ff:ff:ff:ff:ff
4: enp7s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 00:10:18:85:1c:c4 brd ff:ff:ff:ff:ff:ff
5: enp7s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 00:10:18:85:1c:c6 brd ff:ff:ff:ff:ff:ff
6: enp9s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether b4:2e:99:a6:22:f9 brd ff:ff:ff:ff:ff:ff
7: wlp8s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 08:71:90:4e:e9:77 brd ff:ff:ff:ff:ff:ff
8: br-183e1a17d7f6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:ba:03:e1:9d brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-183e1a17d7f6
       valid_lft forever preferred_lft forever
9: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:02:61:00:66 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
10: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:10:18:85:1c:c0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.205/24 brd 192.168.1.255 scope global dynamic noprefixroute br0
       valid_lft 9730sec preferred_lft 7930sec
    inet6 fe80::210:18ff:fe85:1cc0/64 scope link 
       valid_lft forever preferred_lft forever
11: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000
    link/ether fe:54:00:be:eb:3e brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc54:ff:febe:eb3e/64 scope link 
       valid_lft forever preferred_lft forever

○ → brctl showstp br0
br0
 bridge id      8000.001018851cc0
 designated root    1000.44e4d9d88a00
 root port         1            path cost          4
 max age          19.99         bridge max age        19.99
 hello time        1.99         bridge hello time      1.99
 forward delay        14.99         bridge forward delay      14.99
 ageing time         299.99
 hello timer           0.00         tcn timer          0.00
 topology change timer     0.00         gc timer          25.78
 flags          


enp6s0f0 (1)
 port id        8001            state            forwarding
 designated root    1000.44e4d9d88a00   path cost          4
 designated bridge  1000.44e4d9d88a00   message age timer     19.21
 designated port    800d            forward delay timer    0.00
 designated cost       0            hold timer         0.00
 flags          

vnet0 (2)
 port id        8002            state            forwarding
 designated root    1000.44e4d9d88a00   path cost        100
 designated bridge  8000.001018851cc0   message age timer      0.00
 designated port    8002            forward delay timer    0.00
 designated cost       4            hold timer         0.22
 flags          

○ → bridge -d link show
2: enp6s0f0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 4 
    hairpin off guard off root_block off fastleave off learning on flood on mcast_flood on mcast_to_unicast off neigh_suppress off vlan_tunnel off isolated off enp6s0f0
8: br-183e1a17d7f6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 master br-183e1a17d7f6 br-183e1a17d7f6
9: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 master docker0 docker0
10: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 br0
11: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100 
    hairpin off guard off root_block off fastleave off learning on flood on mcast_flood on mcast_to_unicast off neigh_suppress off vlan_tunnel off isolated off vnet0

○ → sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1

○ → sysctl net.ipv4.conf.br0.forwarding
net.ipv4.conf.br0.forwarding = 1

答案1

码头工人负载br_netfilter模块(以获得系统控制属性net.bridge.bridge-nf-call-iptables=1)当它使用 iptables 时。这使得桥接的帧(以太网,第 2 层)受iptables过滤(IP,第 3 层):

什么是桥接网络过滤器?

从Linux内核3.18-rc1开始,您必须modprobe br_netfilter才能启用bridge-netfilter。

bridge-netfilter 代码启用以下功能:

{Ip,Ip6,Arp}表可以过滤桥接的IPv4/IPv6/ARP数据包,即使封装在 802.1Q VLAN 或 PPPoE 标头中也是如此。这启用了状态透明防火墙的功能。因此,这 3 个工具的所有过滤、日志记录和 NAT 功能都可以在桥接帧上使用。因此,bridge-nf 代码与 ebtables 相结合,使 Linux 成为一个非常强大的透明防火墙。这使得能够创建透明的伪装机(即所有本地主机都认为它们直接连接到互联网)。 可以使用适当的过程条目禁用或启用让 {ip,ip6,arp} 表查看桥接流量, 位于 /proc/sys/net/bridge/

  • bridge-nf-call-arptables

  • bridge-nf-call-iptables

  • bridge-nf-call-ip6tables

有文档解释了该模块引起的副作用。这些副作用是故意的当将其用于桥接透明防火墙时。另外,iptables physdev(它br_netfilter在自身加载时加载)如果没有它,匹配就无法正常工作(它根本就不再匹配)。它还解释了如何防止其影响,特别是在第7章

由于 br-nf 代码,帧/数据包可以通过 3 个给定的 iptables 链通过 2 种方式。第一种方式是当帧被桥接时,因此 iptables 链由桥接代码调用。第二种方式是当数据包被路由时。

而不是禁用调用iptablesbybr_netfilter的代码如下:

sysctl -w net.bridge.bridge-nf-call-iptables=0

一个人应该适应iptables规则无论它们在哪里(包括任何网络命名空间),如第 7 章中所述,以避免副作用,通过在 FORWARD 链中添加例如接受规则,其目的不是用于路由而是用于桥接。简单地禁用它来解决一个问题将会破坏依赖它的应用程序,首先是 Docker 的内部容器隔离。

直到最近 内核5.3此模块不具备命名空间感知能力,加载后会突然在所有网络命名空间上启用它,从而在意外情况下引发各种问题。从那时起,就可以按桥接 ( ip link set dev BRIDGE type bridge nf_call_iptables 1) 而不是按命名空间启用它。

一旦工具(Docker ...)和内核(> = 5.3)跟随发展,只需在选定的网络命名空间和桥中启用它就足够了,但今天可能还不够。另请注意内核5.3还继承了本机桥状态防火墙,可供使用nftables,这是淘汰此模块使用的一步(一旦桥接中对 VLAN 和 PPPoE 的直接封装/解封装支持可用):

网络过滤器

添加对桥的本机连接跟踪支持。在此补丁集之前,人们进行状态过滤的唯一机会是使用 br_netfilter 模拟层,这是弃用它的一个进步

相关内容