为什么 ICMP 经过 Linux 网桥后 IP Source 发生了变化?

为什么 ICMP 经过 Linux 网桥后 IP Source 发生了变化?

我创建了一个桥 br0 和 veth(v0 和 v1),但它们不能互操作。 tcpdump 显示 ICMP 的 IP 源已更改。当Mask为/24时,它们将可以互操作。感谢您的帮助。

[root@VM-12-6-centos ~]# ip netns exec n1 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
1147: v0@if1146: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 46:39:b5:cf:bd:b6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.0.2/16 scope global v0
       valid_lft forever preferred_lft forever
    inet6 fe80::4439:b5ff:fecf:bdb6/64 scope link 
       valid_lft forever preferred_lft forever

[root@VM-12-6-centos ~]# ip netns exec n2 ip addr 
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 
1149: v1@if1148: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 56:c0:82:05:6f:7d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.0.3/16 scope global v1
       valid_lft forever preferred_lft forever
    inet6 fe80::54c0:82ff:fe05:6f7d/64 scope link 
       valid_lft forever preferred_lft forever 

[root@VM-12-6-centos ~]# ip netns exec n2 ping 192.168.0.2 
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. ^C
--- 192.168.0.2 ping statistics --- 
3 packets transmitted, 0 received, 100% packet loss, time 81ms

[root@VM-12-6-centos ~]# ip netns exec n1 tcpdump -ni v0 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on v0, link-type EN10MB (Ethernet), capture size 262144 bytes 
23:49:35.395270 IP 10.0.12.6 > 192.168.0.2: ICMP echo request, id 7989, seq 1, length 64 23:49:40.562143 ARP, Request who-has
192.168.0.2 tell 192.168.0.3, length 28 23:49:40.562154 ARP, Reply 192.168.0.2 is-at 46:39:b5:cf:bd:b6, length 28

[root@VM-12-6-centos ~]# route -n Kernel IP routing table Destination  Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.12.1       0.0.0.0         UG    100    0        0 eth0
10.0.12.0       0.0.0.0         255.255.252.0   U     100    0        0 eth0
10.42.0.0       0.0.0.0         255.255.255.0   U     0      0        0 cni0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker_gwbridge
172.31.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-3f74298c82df
192.168.0.0     0.0.0.0         255.255.240.0   U     0      0        0 br-447c96a995be

[root@VM-12-6-centos ~]# brctl show bridge name     bridge id          STP enabled     interfaces br-3f74298c82df         8000.0242cacea67f   no              vethf4618dd br-447c96a995be         8000.024273831baf  no              vethbf5d89d br0             8000.7ae1f3216832       no br-v0
                                                        br-v1 cni0            8000.52bc6b3b510e       no              veth0f9960a8
                                                        veth1cd3811c
                                                        veth2a89c6ed
                                                        veth3aeb1ce7
                                                        vethca9494e3 docker0         8000.0242fcf19461       no docker_gwbridge        
8000.02420fc41a90       no              veth85a243e
                                                        vethd1cfb42

答案1

为了使一切正常工作,您需要创建两对veth管道。一方面,它们必须包含在桥中。网桥和 veth 接口的末端位于根网络命名空间中。管道 v1 和 v2 的另一端分别位于命名空间 n1 和命名空间 n2 中。例子:

ip netns add n1
ip netns add n2

桥中包含的两端称为 bv1 和 bv2:

ip link add v1 netns n1 type veth peer name bv1
ip link add v2 netns n2 type veth peer name bv2
ip link add br0 type bridge
ip link set br0 up
ip link set bv1 master br0
ip link set bv2 master br0
ip link set bv1 up
ip link set bv2 up
brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.d2dba1636571   no          bv1
                                        bv2

转到n1:

nsenter --net=/var/run/netns/n1
ip addr add 192.168.0.2/16 dev v1
ip link set v1 up
ip link set lo up
exit

转到n2:

nsenter --net=/var/run/netns/n2
ip addr add 192.168.0.3/16 dev v2
ip link set v2 up
ip link set lo up
exit

结果:

ip netns exec n1 ping -c2 -I v1 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.265 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.220 ms

ip netns exec n2 ping -c2 -I v2 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.195 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.227 ms

答案2

问题中没有足够的信息来给出明确的答案,但是:

桥接器中有大量其他接口,并且您提到了 Docker。您看到的 ping 数据包很可能来自 Docker 中的某些内容,而不是您发出的 ping。这就是为什么“源 IP 改变了”(它没有改变,这是一个完全不同的 ping)。

通过在没有 docker 的系统上创建网桥和 veth 来验证这一点。您还需要在第二个终端中运行 tcpdump,它必须在您执行 ping 操作时运行。

另一种选择是 Docker 的众多 iptables 规则之一实际上会影响您的 ping,并且无论出于何种原因更改源地址。


TL;DR:如果你正在运行 docker,尝试干扰网络。你将很难让任何东西正常工作,即使你让它正常工作,下次 Docker 更新其 iptables 规则时它也可能再次崩溃。

如果您需要两个容器之间的直接网络,请使用覆盖网络,并且需要五分钟才能完成码头工人组成


https://docs.docker.com/network/iptables/,根据评论,强调我的:

在 Linux 上,Docker 操纵 iptables 规则来提供网络隔离。虽然这是一个实施细节并且你不应该修改 Docker 插入的规则到你的 iptables 策略中,它确实对你需要做什么有一些影响,如果你想要另外你自己的政策那些由 Docker 管理的。

这意味着,特别是连接到 Docker 使用的桥的任何内容都将受到 Docker iptables 规则的约束,您可以使用这些规则不应该修改

您可以对完全独立于 Docker 网络的任何内容制定自己的策略,但我不建议干预 Docker 的网络方式。

这意味着如果你想在 Docker 容器之间建立网络,你应该以简单的方式实现,而不是困难的方式。

答案3

ip 源发生变化,因为数据包经过了网络地址转换设置为iptables由码头工人。

这样做是因为网络(和互联网)上的其他机器不知道在 docker 网络内哪里可以找到 IP 地址。因此,每个传出的数据包都会更改为包含您主机的 IP。

相关内容