首先,我的问题类似于如何使用KVM(Virt-Manager)与虚拟机和主机建立桥接网络?但标记的答案对我不起作用,并且由于问题被标记为已解决,我认为最好发布一个新问题。
我会尝试简化我的设置。
- 我有一个
host
witheno1
(运行 Debian + KDE) - 我已经删除了所有
eno1
接口 - 我创建了一个桥接接口
br0
并添加eno1
为从属接口 - 我安装了 virt-manager
host
现在:
host
连接到br0
和做获取IP- virt-manager
VM
配置为使用br0
但它不做获取IP
无论我如何尝试,我都无法VM
获得 IP。我怎样才能解决这个问题?
这是一些屏幕截图。忽略 br1,因为那只是我在玩/测试。
连接br0
...
...带有以太网从站...
... 链接到eno1
。
VM
配置为桥接设备br0
答案1
Docker 使用iptables管理它的容器,就像库虚拟机也使用它。但通常 Docker 不能与同一系统上运行的其他网络相关工具很好地配合,原因有二:
Docker 负载这
br_netfilter
内核模块这使得桥接的帧遍历iptables(而不是仅仅ebtables)。Docker 还设置了iptables' 默认过滤器/FORWARD 策略为 DROP
Docker 还将链的策略设置
FORWARD
为DROP
.如果您的 Docker 主机还充当路由器,这将导致该路由器不再转发任何流量。如果您希望系统继续充当路由器,您可以ACCEPT
向链中添加明确的规则DOCKER-USER
以允许它。
这些的结合,以及事实br_netfilter
将此作为默认行为,系统上存在的任何网桥,无论是否与 Docker 相关,都会继承默认的 DROP 转发策略iptables,除了任何ebtables如果也存在的话可能会这样做:任何转发的帧都会被丢弃。
所以所有的桥都由库虚拟机受到影响:虚拟机因 Docker 运行而被隔离。如上所述,可以将例外添加(但实际上应该插入而不是添加)到DOCKER-USER
Docker 创建的链式规则(但如果需要,可以首先由管理员创建)。仅仅向链添加规则FORWARD
可能还不够,因为 Docker 总是在之前插入其规则(但DOCKER-USER
首先调用)。
允许任何非 Docker 桥不被过滤iptables,可以使用以下选择之一:
通过 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
或者通过非 Docker 接口进行匹配
除非自定义命名,否则 Docker 接口始终命名为
docker0
或br-...
。不要使用相同的命名约定并为它们添加例外。从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
或者改为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)。
虚拟机中的 Docker
不要将 Docker 与任何其他网络工具混合使用,它会在存在网桥的情况下扰乱它们的行为。相反,在正确隔离的虚拟机中运行 Docker 本身,不会影响主机或主机上的其他虚拟机和容器(例如:LXC)。然后,如果这个虚拟机本身与主网络桥接,正如当前主机的设置已经允许的那样,这不会对到达其容器的外部设置进行太大改变:Docker 将在物理 LAN 上拥有自己独立的 IP 地址,而不是主人的。
其他可能性(需要内核 >= 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具体答案反而。