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 dnsmasq
dentro 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 tap2
que tenha sido criado pelo QEMU ...
Dentro desta VM, existem dois ifaces. ens4
com MAC DE:AD:BE:EF:00:11 e ens5
com 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 vivianbr0
uso tcpdump
e 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
DOWN
estado naip a l
saída do host (deveria dizerUNKNOWN
ouUP
)- se você deixar o qemu criar o dispositivo de toque, ele
qemu-bridge-helper
será exibido - se você usar um script=, abra o dispositivo lá
- caso contrário, você precisará de
ip link set tapN up
algum tempo após o início da VM
- se você deixar o qemu criar o dispositivo de toque, ele
- visível do
- Os endereços MAC precisam ser exclusivos
- visível no
ether
endereçoip a l
nos convidados - listar macs aprendidos (não host), por exemplo,
brctl showmacs br0
deveria terdoisentradas com um temporizador de envelhecimento diferente de zero
- visível no
- descartando pacotes via iptables
- verifique
/proc/sys/net/bridge/bridge-nf-call*
e sebr_netfilter
o 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)
- verifique
Outros notáveis que encontrei durante o teste:
- Qemu adicionou a
vnet_hdr
opçã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-interfaces
para 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.