主机正在从桥接设备获取 IP,但 virt-manager 虚拟机却未获取 IP

主机正在从桥接设备获取 IP,但 virt-manager 虚拟机却未获取 IP

首先,我的问题类似于如何使用KVM(Virt-Manager)与虚拟机和主机建立桥接网络?但标记的答案对我不起作用,并且由于问题被标记为已解决,我认为最好发布一个新问题。

我会尝试简化我的设置。

  • 我有一个hostwith eno1(运行 Debian + KDE)
  • 我已经删除了所有eno1接口
  • 我创建了一个桥接接口br0并添加eno1为从属接口
  • 我安装了 virt-managerhost

现在:

  • host连接到br0获取IP
  • virt-managerVM配置为使用br0但它不做获取IP

无论我如何尝试,我都无法VM获得 IP。我怎样才能解决这个问题?

这是一些屏幕截图。忽略 br1,因为那只是我在玩/测试。

连接br0...

在此输入图像描述

...带有以太网从站...

在此输入图像描述

... 链接到eno1

在此输入图像描述

VM配置为桥接设备br0

在此输入图像描述

答案1

Docker 使用iptables管理它的容器,就像库虚拟机也使用它。但通常 Docker 不能与同一系统上运行的其他网络相关工具很好地配合,原因有二:

这些的结合,以及事实br_netfilter将此作为默认行为,系统上存在的任何网桥,无论是否与 Docker 相关,都会继承默认的 DROP 转发策略iptables,除了任何ebtables如果也存在的话可能会这样做:任何转发的帧都会被丢弃。

所以所有的桥都由库虚拟机受到影响:虚拟机因 Docker 运行而被隔离。如上所述,可以将例外添加(但实际上应该插入而不是添加)到DOCKER-USERDocker 创建的链式规则(但如果需要,可以首先由管理员创建)。仅仅向链添加规则FORWARD可能还不够,因为 Docker 总是在之前插入其规则(但DOCKER-USER首先调用)。

允许任何非 Docker 桥不被过滤iptables,可以使用以下选择之一:

  1. 通过 IP 地址匹配允许转发的内容。使用 0.0.0.0 和 255.255.255.255 等地址很难与 DHCP 区分开来,还必须添加它们。对于 IP LAN 192.0.2.0/24 来说:

    iptables -N DOCKER-USER || true # doesn't matter if done before Docker or after (and thus already existing)
    iptables -I DOCKER-USER -s 192.0.2.0/24 -d 192.0.2.0/24 -j ACCEPT
    iptables -I DOCKER-USER -s 0.0.0.0/32 -d 255.255.255.255/32 -j ACCEPT
    
  2. 或者通过非 Docker 接口进行匹配

    除非自定义命名,否则 Docker 接口始终命名为docker0br-...。不要使用相同的命名约定并为它们添加例外。

    iptables从桥接端口转发的桥接帧诺1例如虚拟网0(虚拟机的点击接口)呈现为来自br0接口:看不到桥接端口,因此数据包来自br0并转发至br0

    顺序很重要。声明插入索引可以保持下面规则的自然顺序,就像添加了(但由于 Docker 添加了最后的)-A而必须插入它们。-j RETURN

    iptables -N DOCKER-USER || true
    iptables -I DOCKER-USER 1 -i docker0 -o docker0 -j RETURN
    iptables -I DOCKER-USER 2 -i br-+ -o br-+ -j RETURN
    

    允许br0并且br1

    iptables -I DOCKER-USER 3 -i br0 -o br0 -j ACCEPT
    iptables -I DOCKER-USER 4 -i br1 -o br1 -j ACCEPT
    

    让我们继续讨论 libvirt 和 LXC(也是常见的受害者)的其他常见名称:

    iptables -I DOCKER-USER 5 -i virbr0 -o virbr0 -j ACCEPT
    iptables -I DOCKER-USER 6 -i lxcbr0 -o lxcbr0 -j ACCEPT
    
  3. 或者改为iptables获取一些桥梁信息以做出决定

    即使它看起来更通用,也应该避免,因为使用physdev如果尚未加载,则match 模块会加载br_netfilter内核模块来工作,因此即使不使用 Docker,也会得到此信息,而其目标是保护自己免受 Docker 加载的影响br_netfilter。它更强大一点,因为它允许区分桥接的帧和路由的数据包(使用单臂路由,恰好使用网桥作为路由接口)。

    Docker 仍然需要例外,因为 Docker 在自己的链中进行自己的 LAN 过滤。任何非 Docker 和桥接(而不是路由)的东西都是允许的。

    iptables -N DOCKER-USER || true
    iptables -I DOCKER-USER 1 -i docker0 -o docker0 -j RETURN
    iptables -I DOCKER-USER 2 -i br-+ -o br-+ -j RETURN
    iptables -I DOCKER-USER 3 -m physdev --physdev-is-bridged -j ACCEPT
    

考虑到之前的选择可能不适用于所有可能的情况库虚拟机本身在 FORWARD 链中的规则可能无法正常工作或者可能被 Docker 的规则短路。虽然纳特对于这种情况,也受到影响的规则通常可以完全正确地处理库虚拟机(以及 LXC)。

  1. 虚拟机中的 Docker

    不要将 Docker 与任何其他网络工具混合使用,它会在存在网桥的情况下扰乱它们的行为。相反,在正确隔离的虚拟机中运行 Docker 本身,不会影响主机或主机上的其他虚拟机和容器(例如:LXC)。然后,如果这个虚拟机本身与主网络桥接,正如当前主机的设置已经允许的那样,这不会对到达其容器的外部设置进行太大改变:Docker 将在物理 LAN 上拥有自己独立的 IP 地址,而不是主人的。

  2. 其他可能性(需要内核 >= 5.3)

    预加载br_netfilter以确保获得系统控制设置可用,并禁用系统范围的设置iptables和:

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

    并在选定的 Docker 桥上重新启用它(可能使用运行 Docker 命令的脚本来检索其名称):

    ip link set dev docker0 type bridge nf_call_iptables 1
    ip link set dev br-5039242381f0 type bridge nf_call_iptables 1
    

    这将需要对创建的每个新桥进行操作。

    另一种方式可能是Docker 中的 Docker在仅禁用全局设置的容器中运行自身(默认情况下,在新的网络命名空间上仍启用此设置...)。这看起来越来越困难,因为与在虚拟机中运行 Docker 相比,需要额外的管理负担。

我会选择 4。(虚拟机:避免所有可能的 Docker 干扰)或者 2。(保持简单但足够好)

iptables注意:通过替换ip6tables上面的内容(包括) ,所有内容都适用于 IPv6 sysctl。为了nftables整合看这个nftables具体答案反而。

相关内容