Как запустить dnsmasq внутри QEMU, предоставляя службу сетевой загрузки другим виртуальным машинам

Как запустить dnsmasq внутри QEMU, предоставляя службу сетевой загрузки другим виртуальным машинам

EDIT: WIP: Основная причина сбоев, описанных ниже, заключается в том, что я не поднял интерфейсы TAP хоста в нужное время. Если я позволю QEMU обрабатывать создание устройств TAP, все будет работать так, как и ожидалось. Я изучу сбой более подробно и предоставлю более четкое объяснение проблемы, когда она у меня появится. Спасибо @anx за советы!

Цель: запустить dnsmasqвнутри хоста виртуальную машину QEMU, которая обслуживает сетевую загрузку с другой виртуальной машины QEMU, работающей на хосте.

Я хотел бы, чтобы виртуальная машина dnsmasq действовала как шлюз, с одной сетевой картой в качестве интерфейса WAN верхнего уровня, с сервером DHCP верхнего уровня, а другой интерфейс был бы частным интерфейсом LAN, к которому были бы «подключены» другие виртуальные машины, и выполняла бы сетевую загрузку с dnsmasq, прослушивающего этот частный интерфейс LAN.

Во-первых, чтобы позволить виртуальным машинам общаться друг с другом, я создаю собственный мост на хосте,

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

Чтобы виртуальные машины могли взаимодействовать друг с другом через хост-мост, мне понадобятся два ответвителя: один для интерфейса частной локальной сети на шлюзовой виртуальной машине, а другой — для единого сетевого интерфейса частной виртуальной машины.

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 для целей тестирования, виртуальная машина загружается с двух сетевых карт, таким образом,

 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...

Внутри этой виртуальной машины есть два интерфейса. 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

Странно, но я вижу запросы BOOTP отde:ad:be:ef:00:13 (MAC-адрес виртуальной машины сетевой загрузки)и из de:ad:be:ef:00:12(частная сетевая карта шлюзовой виртуальной машины), что указывает на наличие серьезной ошибки в настройках.

Как мне это реализовать?

решение1

Ваши действия для двух гостей вполне приемлемы, я только что повторил вашу установку.вплоть до момента аренды адресов. Я мог бы раздавать IP-адреса с одной виртуальной машины, на которой запущен dnsmasq, на другую виртуальную машину, на которой запущен клиент dhcp.

Проверьте это:

  • невозможно вызвать неприсоединенные устройства для подключения
    • видно из DOWNсостояния в ip a lвыводе хоста (следует указать UNKNOWNили UP)
      • если вы позволите qemu создать устройство tap, оно qemu-bridge-helperбудет запущено
      • если вы используете скрипт=, вызовите устройство там
      • в противном случае вам придется 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"before dropping или перед политикой DROP в таблице FORWARD
    • игнорировать/sys/class/net/br*/bridge/nf_call_* (я не знаю, почему этиможетбыть выключенным при включенной фильтрации)

Другие примечательные моменты, которые я обнаружил во время тестирования:

  • Qemu добавил эту vnet_hdrопцию на моих устройствах tap. Это кажется разумным и могло быть отключено в командной строке qemu, если бы это было необходимо.
  • Иногда мой (ссылка на область) маршрут для моста пропадал. Мне еще предстоит выяснить, как это вообще могло произойти.

О вашей попытке упростить тестирование путем привязки к устройству tap..

dnsmasq будет работать внутри виртуальной машины QEMU

Насколько мне известно, устройства постоянного подключения не могут использоваться до фактического подключения. Поэтому вы можете осмысленно протестировать только одну из следующих полных установок:

  • Хотите запустить dnsmasq на хосте?
    • затем прикрепите его к мостовому устройству
  • или вы хотите запустить dnsmasq внутри виртуальной машины?
    • затем подключите его к соответствующему сетевому интерфейсувнутричто ВМ

--interface=tap0

Совет: используйте, --bind-interfacesчтобы указать dnsmasq переключиться с простого отбрасывания трафика с других интерфейсов на фактическую попытку привязки, тем самым завершая работу со строгим сообщением при запуске с непригодными для использования настройками.

Связанный контент