EDITAR: WIP: La razón principal de las fallas que se explican a continuación se debe a que no abrí las interfaces TAP del host en el momento adecuado; si permito que QEMU maneje la creación de los dispositivos tap, todo funciona como se esperaba. Investigaré la falla con más detalle y brindaré una explicación más clara del problema cuando la tenga. ¡Gracias @anx por los consejos!
Objetivo: ejecutar una dnsmasq
máquina virtual QEMU dentro de un host, que dé servicio a los arranques de red desde otra máquina virtual QEMU que se ejecuta en el host.
Me gustaría que la máquina virtual dnsmasq actúe como una puerta de enlace, con una NIC como interfaz WAN ascendente, con un servidor DHCP ascendente y la otra interfaz como una interfaz LAN privada, a la que se "conectarán" otras máquinas virtuales y arrancarán en red desde dnsmasq escuchando en esta interfaz LAN privada.
Primero, para permitir que las máquinas virtuales se comuniquen entre sí, creo mi propio puente en el host,
ip link add name vivianbr0 type bridge
ip link set vivianbr0 up
Para que las máquinas virtuales se comuniquen entre sí a través del puente de host, necesitaré dos dispositivos tap, uno para la interfaz LAN privada en la máquina virtual de puerta de enlace y otro para la interfaz de red única de las máquinas virtuales 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 la máquina virtual de puerta de enlace, estoy usando una ISO de Arch Linux con fines de prueba, la máquina virtual se inicia con dos NIC, por lo tanto,
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
Una vez que esta máquina ha arrancado, veo lo siguiente en la configuración del puente,
brctl show vivianbr0
bridge name bridge id STP enabled interfaces
vivianbr0 8000.46954a1ad851 no tap0
tap1
tap2
Supongo tap2
que fue creado por QEMU...
Dentro de esta VM, hay dos interfaces. ens4
con MAC DE:AD:BE:EF:00:11 y ens5
con MAC DE:AD:BE:EF:00:12. Dentro de esta VM, empiezo 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
Esto comienza sin error.
Ahora intento arrancar en red otra VM, iniciada en el host de esta manera,
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
Pero no arranca. Superviso el vivianbr0
uso tcpdump
y puedo ver las solicitudes de DHCP, pero no hay respuestas, nada llega al dnsmasq que se ejecuta dentro de la primera 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
Curiosamente, veo solicitudes BOOTP de de:ad:be:ef:00:13
(la dirección MAC de las máquinas virtuales de arranque en red)y de de:ad:be:ef:00:12
(la NIC privada de la máquina virtual de puerta de enlace), lo que indica que algo está mal configurado.
¿Cómo puedo hacer que esto funcione?
Respuesta1
Tus pasos para dos invitados están bien, acabo de replicar tu configuración.hasta el momento de las direcciones de arrendamiento. Podría entregar direcciones IP de una máquina virtual que ejecute dnsmasq a una máquina virtual que ejecute un cliente dhcp.
Compruebe estos:
- no se pueden abrir dispositivos tap no conectados
- visible desde el
DOWN
estado enip a l
la salida del host (debería decirUNKNOWN
oUP
)- si dejas que qemu cree el dispositivo tap, lo
qemu-bridge-helper
abrirá - si usa un script =, abra el dispositivo allí
- de lo contrario, tendrá que hacerlo
ip link set tapN up
algún tiempo después del inicio de la máquina virtual.
- si dejas que qemu cree el dispositivo tap, lo
- visible desde el
- Las direcciones MAC deben ser únicas
- visible en la
ether
dirección enip a l
los invitados - enumerar las Mac aprendidas (no host), por ejemplo,
brctl showmacs br0
deberían tenerdosentradas con un temporizador de envejecimiento distinto de cero
- visible en la
- soltar paquetes a través de iptables
- comprobar
/proc/sys/net/bridge/bridge-nf-call*
y sibr_netfilter
el módulo está cargado - agregue una regla de registro, para IPv4, algo así como
iptables -A FORWARD -j LOG --log-prefix "forward dropped"
antes de descartar o antes de una política DROP en la tabla FORWARD - ignorar
/sys/class/net/br*/bridge/nf_call_*
(no sé por qué estospoderestar apagado cuando el filtrado está activado)
- comprobar
Otros notables que encontré durante las pruebas:
- Qemu agregó la
vnet_hdr
opción en mis dispositivos tap. Eso parece razonable y podría haberse deshabilitado en la línea cmdline de qemu si así lo hubiera deseado. - A veces mi ruta (enlace de alcance) para el puente se perdía. Todavía tengo que determinar cómo podría suceder eso.
Acerca de su intento de simplificar la prueba vinculándolo al dispositivo de grifo.
dnsmasq se ejecutará dentro de una VM QEMU
Los dispositivos de grifo persistente AFAIK no se pueden utilizar hasta que estén realmente conectados. Por lo tanto, sólo puedes probar de manera significativa cualquiera de las configuraciones completas:
- ¿Quieres ejecutar dnsmasq en el host?
- luego conéctelo al dispositivo puente
- ¿O quieres ejecutar dnsmasq dentro de una VM?
- luego conéctelo a la interfaz de red respectivaadentroesa máquina virtual
--interfaz=toque0
Sugerencia: Úselo --bind-interfaces
para indicarle a dnsmasq que pase de simplemente descartar el tráfico de otras interfaces a intentar vincularse, saliendo así detalladamente cuando se inicia con configuraciones inutilizables.