Como executar um dnsmasq dentro do QEMU, fornecendo serviço netboot para outras VMs

Como executar um dnsmasq dentro do QEMU, fornecendo serviço netboot para outras VMs

EDIT: WIP: O principal motivo das falhas explicadas abaixo é porque eu não trouxe as interfaces TAP do host no momento certo, se eu permitir que o QEMU cuide da criação dos dispositivos tap, tudo funcionará conforme o esperado. Investigarei a falha com mais detalhes e fornecerei uma explicação mais clara do problema quando o tiver. Obrigado @anx pelas dicas!

Objetivo: Executar dnsmasqdentro de uma VM QEMU host, que atende netboots de outra VM QEMU em execução no host.

Eu gostaria que a VM dnsmasq funcionasse como um gateway, com uma NIC como interface WAN upstream, com um servidor DHCP upstream e a outra interface como uma interface LAN privada, à qual outras VMs serão "conectadas" e inicializarão pela rede a partir de o dnsmasq escutando nesta interface LAN privada.

Primeiro, para permitir que as VMs se comuniquem entre si, crio minha própria ponte no host,

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

Para que as VMs se comuniquem entre si por meio da ponte de host, precisarei de dois dispositivos de toque, um para a interface LAN privada na VM do gateway e outro para a interface de rede única das VMs privadas.

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

Para a VM gateway, estou usando um ISO do Arch Linux para fins de teste, a VM é inicializada com duas NICs, portanto,

 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

Depois que esta máquina for inicializada, vejo o seguinte na configuração da ponte,

brctl show vivianbr0 

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

Presumo tap2que tenha sido criado pelo QEMU ...

Dentro desta VM, existem dois ifaces. ens4com MAC DE:AD:BE:EF:00:11 e ens5com MAC DE:AD:BE:EF:00:12. Dentro desta VM, eu começo 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

Isso começa sem erros.

Agora tento inicializar outra VM pela rede, iniciada no host assim,

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

Mas não consegue inicializar. Eu monitoro o vivianbr0uso tcpdumpe consigo ver as solicitações de DHCP, mas não há respostas, nada chega ao dnsmasq rodando dentro da primeira VM,

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

Estranhamente, vejo solicitações BOOTP de de:ad:be:ef:00:13(o endereço MAC das VMs de inicialização pela rede)e de de:ad:be:ef:00:12(a NIC privada da VM do gateway), indicando que algo está mal configurado.

Como posso fazer isso funcionar?

Responder1

Suas etapas para dois convidados estão corretas, acabei de replicar sua configuraçãoaté o ponto de locação de endereços. Eu poderia distribuir IPs de uma VM executando dnsmasq para uma VM executando um cliente DHCP.

Verifique estes:

  • não é possível exibir dispositivos de toque não conectados
    • visível do DOWNestado na ip a lsaída do host (deveria dizer UNKNOWNou UP)
      • se você deixar o qemu criar o dispositivo de toque, ele qemu-bridge-helperserá exibido
      • se você usar um script=, abra o dispositivo lá
      • caso contrário, você precisará de ip link set tapN upalgum tempo após o início da VM
  • Os endereços MAC precisam ser exclusivos
    • visível no etherendereço ip a lnos convidados
    • listar macs aprendidos (não host), por exemplo, brctl showmacs br0deveria terdoisentradas com um temporizador de envelhecimento diferente de zero
  • descartando pacotes via iptables
    • verifique /proc/sys/net/bridge/bridge-nf-call*e se br_netfiltero módulo está carregado
    • adicione uma regra de registro, para IPv4 algo como iptables -A FORWARD -j LOG --log-prefix "forward dropped"antes de descartar ou antes de uma política DROP na tabela FORWARD
    • ignorar /sys/class/net/br*/bridge/nf_call_*(não sei por que essespodeestar desativado quando a filtragem estiver ativada)

Outros notáveis ​​que encontrei durante o teste:

  • Qemu adicionou a vnet_hdropção em meus dispositivos de toque. Isso parece razoável e poderia ter sido desativado no cmdline do qemu, se desejado.
  • Às vezes, minha rota (link do escopo) para a ponte desaparecia. Ainda não determinei como isso poderia acontecer.

Sobre sua tentativa de simplificar o teste vinculando-se ao dispositivo de toque.

dnsmasq estará rodando dentro de uma VM QEMU

Os dispositivos de toque persistente AFAIK ficam inutilizáveis ​​até serem realmente conectados. Portanto, você só pode testar significativamente a configuração completa:

  • Você deseja executar o dnsmasq no host?
    • em seguida, conecte-o ao dispositivo de ponte
  • ou você deseja executar o dnsmasq dentro de uma VM?
    • em seguida, conecte-o à respectiva interface de rededentroaquela VM

--interface=tap0

Dica: Use --bind-interfacespara instruir o dnsmasq a mudar de simplesmente descartar o tráfego de outras interfaces para realmente tentar vincular, encerrando assim detalhadamente quando iniciado com configurações inutilizáveis.

informação relacionada