如何在 QEMU 中运行 dnsmasq,为其他虚拟机提供网络启动服务

如何在 QEMU 中运行 dnsmasq,为其他虚拟机提供网络启动服务

编辑:WIP:下面解释的失败的核心原因是我没有在正确的时间启动主机 TAP 接口,如果我允许 QEMU 处理 TAP 设备的创建,一切都会按预期工作。我将更详细地调查失败原因,并在遇到问题时提供更清晰的解释。感谢 @anx 提供的提示!

目标:dnsmasq在主机 QEMU VM 内部运行,该 VM 为主机上运行的另一个 QEMU VM 提供网络启动服务。

我希望 dnsmasq VM 能够充当网关,其中一个 NIC 作为上游 WAN 接口,带有上游 DHCP 服务器,另一个接口作为私有 LAN 接口,其他 VM 将“插入”该接口,并将从侦听该私有 LAN 接口的 dnsmasq 进行网络启动。

首先,为了让虚拟机之间能够互相通信,我在主机上创建了自己的网桥,

ip link add name vivianbr0 type bridge
ip link set vivianbr0 up

为了使虚拟机通过主机桥相互通信,我需要两个 Tap 设备,一个用于网关虚拟机上的私有 LAN 接口,另一个用于私有虚拟机的单网络接口,

ip tuntap add mode tap tap0 user cturner
ip tuntap add mode tap tap1 user cturner
ip link set tap0 up
ip link set tap1 up
ip link set tap0 master vivianbr0
ip link set tap1 master vivianbr0

对于网关虚拟机,我使用 Arch Linux ISO 进行测试,虚拟机启动时带有两个 NIC,因此,

 qemu-system-x86_64 \
    -drive file=arch-disk.qcow2,if=none,id=nvm \
    -device nvme,serial=deadbeef,drive=nvm \
    -cdrom archlinux-2021.09.01-x86_64.iso \
    -boot d \
    -device virtio-net-pci,romfile=,netdev=net0,mac="DE:AD:BE:EF:00:11" \
    -device virtio-net-pci,romfile=,netdev=net1,mac="DE:AD:BE:EF:00:12" \
    `# Simulate the plugged in "upstream" cable with user-mode networking` \
    -netdev user,id=net0,hostfwd=tcp::60022-:22,hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:8000,hostfwd=tcp::2375-:2375 \
    `# And now the unplugged one with, with TAP networks` \
    -netdev tap,id=net1,ifname=tap0,script=no,downscript=no \
-net bridge,br=vivianbr0 \
    -m 4G \
    -enable-kvm

这台机器启动后,我在桥接配置中看到以下内容,

brctl show vivianbr0 

bridge name     bridge id               STP enabled     interfaces
vivianbr0               8000.46954a1ad851       no              tap0
                            tap1
                            tap2

我认为tap2是由 QEMU 创建的......

在此虚拟机中,有两个 iface。ens4一个是 MAC DE:AD:BE:EF:00:11,另一个ens5是 MAC DE:AD:BE:EF:00:12。在此虚拟机中,我启动dnsmasq

ip addr add 10.42.0.1/24 dev ens5
dnsmasq -d --dhcp-range=10.42.0.10,10.42.0.100 --dhcp-script=/bin/echo --enable-tftp=ens5 --interface=ens5

这将顺利启动。

现在我尝试通过网络启动另一台虚拟机,在主机上启动如下:

qemu-system-x86_64 \
-machine pc-q35-6.0,accel=kvm \
-m 1024 -smp 2,sockets=2,cores=1,threads=1 \
-netdev tap,id=net0,ifname=tap1,script=no,downscript=no \
-device virtio-net-pci,netdev=net0,bootindex=1,mac=DE:AD:BE:EF:00:13 \
-net bridge,br=vivianbr0 \
-enable-kvm \
-vga virtio

但它无法启动。我监控vivianbr0使用情况tcpdump,可以看到 DHCP 请求,但没有响应,没有任何东西到达第一个虚拟机内运行的 dnsmasq,

tcpdump -i vivianbr0 -nN
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on vivianbr0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:21:39.585229 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:40.587741 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:40.700038 IP6 fe80::6ce2:2aff:fe94:ba48.5353 > ff02::fb.5353: 0 [7q] PTR (QM)? _nfs._tcp.local. PTR (QM)? _ftp._tcp.local. PTR (QM)? _webdav._tcp.local. PTR (QM)? _webdavs._tcp.local. PTR (QM)? _sftp-ssh._tcp.local. PTR (QM)? _smb._tcp.local. PTR (QM)? _afpovertcp._tcp.local. (118)
12:21:42.619968 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:46.684448 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:22:30.609555 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289
12:23:33.796148 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289
12:24:38.673364 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289

de:ad:be:ef:00:13奇怪的是,我看到来自(网络启动虚拟机的 MAC 地址)的 BOOTP 请求以及来自 de:ad:be:ef:00:12(网关虚拟机的私有网卡),表明某些配置存在严重错误。

我怎样才能让它工作?

答案1

您为两位客人设置的步骤很好,我刚刚复制了您的设置直到租赁地址为止。我可以将 IP 从一台运行 dnsmasq 的 VM 分发到一台运行 dhcp 客户端的 VM。

检查这些:

  • 无法调出未连接的 Tap 设备
    • 从主机输出的DOWN状态可见(应该说或) ip a lUNKNOWNUP
      • 如果你让 qemu 创建 tap 设备,它将qemu-bridge-helper启动它
      • 如果你使用 script=,则在那里启动设备
      • 否则,你必须ip link set tapN up在虚拟机启动后等待一段时间
  • MAC 地址必须是唯一的
    • 在客人的ether地址中可见ip a l
    • 列出已学习到的(非主机)mac,例如brctl showmacs br0应该有具有非零老化计时器的条目
  • 通过 iptables 丢弃数据包
    • 检查模块/proc/sys/net/bridge/bridge-nf-call*是否br_netfilter已加载
    • 添加日志记录规则,对于 IPv4,类似于iptables -A FORWARD -j LOG --log-prefix "forward dropped"在删除之前或在 FORWARD 表上的 DROP 策略之前
    • 忽略/sys/class/net/br*/bridge/nf_call_*(我不知道为什么这些过滤开启时关闭)

我在测试中发现的其他值得注意的地方:

  • Qemuvnet_hdr在我的 tap 设备上添加了该选项。这似乎是合理的,如果需要,可以在 qemu 命令行上禁用它。
  • 有时我的(范围链接)桥梁路线会消失。我还没有确定这是怎么发生的。

关于您尝试通过绑定到 Tap 设备来简化测试。

dnsmasq 将在 QEMU VM 中运行

据我所知,持久性 Tap 设备在实际连接之前无法使用。因此,您只能对以下任一完整设置进行有意义的测试:

  • 您想在主机上运行 dnsmasq 吗?
    • 然后将其连接到桥接设备
  • 或者您想在 VM 内运行 dnsmasq?
    • 然后将其连接到相应的网络接口里面那个虚拟机

--接口=tap0

提示:用于--bind-interfaces指示 dnsmasq 从仅仅丢弃来自其他接口的流量切换到实际尝试绑定,从而在以无法使用的设置启动时详细退出。

相关内容