如果我在 kvm guest 虚拟机上添加以下设置:
net.ipv4.conf.all.arp_ignore=1
客人网络停止(高度间歇)。
kvm 主机使用桥接网络:
auto lo
iface lo inet loopback
iface lo inet6 loopback
auto {{ vbox_interface }}
iface {{ vbox_interface }} inet static
address {{ vbox_main_ipv4 }}
netmask {{ vbox_ipv4_netmask }}
gateway {{ vbox_ipv4_gw }}
pointopoint {{ vbox_ipv4_gw }}
iface {{ vbox_interface }} inet6 static
address {{ vbox_main_ipv6 }}
netmask 128
gateway {{ vbox_ipv6_gw }}
auto br0
iface br0 inet static
address {{ vbox_main_ipv4 }}
netmask 255.255.255.255
bridge_ports none
bridge_stp off
bridge_fd 0
bridge_maxwait 0
{% for ip in vbox_addtl_ipv4 %}
up route add -host {{ ip }} dev br0
{% endfor %}
iface br0 inet6 static
address {{ vbox_main_ipv6 }}
netmask 64
这是为什么?
正如迈克尔在评论中指出的那样,一些背景如下:
- 我确实理解
arp_ignore
(http://kb.linuxvirtualserver.org/wiki/Using_arp_announce/arp_ignore_to_disable_ARP)——我主要想保留该设置,因为我处于不受信任的网络中 - 我确实知道网络设置可能不标准,这是因为我遵循了这一点:https://wiki.hetzner.de/index.php/KVM_mit_Nutzung_aller_IPs_-_the_easy_way/en- 这使我能够使用给定子网的所有 IP
- 我确实知道在客户虚拟机上进行设置
arp_ignore=0
可以解决问题。但是我想知道为什么(因为我不需要在主机本身上这样做),我不能接受这个答案,因为我不认为设置它会导致网络离线(例如,我想在不使该设置成为依赖项的情况下解决问题) - 我假设(感谢 Peter Zhabin)网络掩码为 255.255.255.255 足够安全,以至于不受信任的网络中的任何人都无法利用 arp?
所以我想我的问题是:
当 kvm-guest 使用 pointopoint/255.255.255.255 时,为什么会arp_ignore=1
破坏 kvm-guest <> kvm-host 网络?
编辑 2018/10/23:访客接口配置
# The loopback network interface
auto lo
iface lo inet loopback
auto ens7
iface ens7 inet static
address IP from the pool {{ vbox_addtl_ipv4 }}
netmask 255.255.255.255
gateway {{ vbox_main_ipv4 }}
pointopoint {{ vbox_main_ipv4 }}
iface ens7 inet6 static
address xxx::xxx
netmask 64
gateway {{ vbox_main_ipv6 }}
答案1
我已经在没有任何网桥、KVM 或 Hetzner 的 Ubuntu 18.04 上验证了此行为,我认为这实际上是与处理arp_ignore
点对点以太网接口有关的内核错误。验证步骤:
- 确保
netplan
完全禁用它不会造成干扰。 设置两个系统,使以太网接口相互连接,并按如下方式分配 IP 地址:
服务器A:
ip addr add 192.168.100.1/32 peer 192.168.100.2 dev ens33
ip link set ens33 up
服务器B:
ip addr add 192.168.100.2/32 peer 192.168.100.1 dev ens33
ip link set ens33 up
观察从服务器 A 到服务器 B 的正常 ping 以及
ip addr show
包含以下行的输出:inet 192.168.100.1 peer 192.168.100.2/32 scope global ens33
arp_ignore=1
在服务器 A 上启用sysctl net.ipv4.conf.all.arp_ignore=1
,并观察 ARP 条目超时后 ping 是否停止。在一定短时间内 ping将恢复一段时间后又结束。这个过程将以这种方式无限期地持续下去。在服务器 B 上运行
tcpdump
,观察来自who-has
服务器 B 的对服务器 A IP 地址的入站 ping 和无响应的出站请求。有时,服务器 A 会发出who-has
对服务器 B IP 的请求,并会得到回复,而服务器 B 会暂时缓存从此 ARP 请求中获得的源 MAC 地址,此时 ping 会恢复。
现在,事情是这样的。点对点和标准广播接口在如何iproute2
(以及类似工具)填充in_ifaddr
中定义的结构方面存在内核差异include/linux/inetdevice.h
。
对于普通接口,其ifa_address
字段填充为本地接口地址;对于点对点接口,ifa_address
填充远程对等地址并ifa_local
填充本地接口地址。
这是正常且预期的行为,因为在过去,任何点对点接口都被视为连接的远程设备本身;与其对应的本地端点地址甚至可能不存在。所以这里没有什么问题。
真正有问题的是,arp_ignore()
定义的处理程序net/ipv4/arp.c
间接使用了confirm_addr_indev()
定义的函数,net/ipv4/devinet.c
该函数迭代尝试将 ARP 请求的目标 IP 地址(即本地接口地址)与ifa_address
接口上所有配置的 IP 地址记录的字段进行匹配。
这在标准接口上运行良好,因为它们确实在字段中记录了其本地 IP 地址ifa_address
,但是对于点对点接口,它会失败,因为它们在此字段中记录了对等 IP 地址。
现在,真正的问题是这个问题是否真的需要修复,因为已经有人指出arp_ignore
在 p2p 链接上使用是没有意义的。我认为需要,因为可能存在这样的情况,即相关主机有多个接口(并且这些接口不是 p2p 接口),并且有人可能conf.all
只使用前缀启用此功能,结果发现他的 p2p 链接毫无原因地关闭了。
答案2
答案就在定义中:
arp_ignore - 0 - (default): reply for any local target IP address, configured on any interface 1 - reply only if the target IP address is local address configured on the incoming interface 2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface 3 - do not reply for local addresses configured with scope host, only resolutions for global and link addresses are replied 4-7 - reserved 8 - do not reply for all local addresses
本质上,由于点对点接口本身没有分配 IP 地址,因此不存在“传入接口上的目标 IP”。IP 被分配给桥接接口……而不是实际的链路接口。因此,不会处理任何 ARP。