libvirt gestiona las redes de las máquinas virtuales KVM con redes virtuales: cada una es un bridge de Linux en el anfitrión (virbr0, virbr1...) con, opcionalmente, DHCP y DNS servidos por dnsmasq y reglas de firewall para NAT o enrutamiento. Elegir el modo adecuado decide si tus VMs pueden salir a Internet, si son accesibles desde fuera y si pueden hablar entre ellas.
En este tutorial revisarás la red NAT por defecto, reservarás IPs fijas por DHCP, crearás una red aislada y una enrutada, y conectarás VMs directamente a la red física mediante un bridge configurado con netplan, todo en Ubuntu 24.04.
Requisitos previos
- Un anfitrión con Ubuntu 24.04 LTS con KVM y libvirt instalados, y tu usuario en el grupo
libvirtconLIBVIRT_DEFAULT_URI=qemu:///system. La guía de instalación de KVM/QEMU en Linux explica cómo prepararlo. - Al menos una VM. Los ejemplos usan
vm1. - Para la red en puente: acceso a la consola del servidor (IPMI, KVM remoto o consola del proveedor), porque un error en netplan puede cortar la conexión SSH.
Modos de red de libvirt
| Modo | Salida a Internet | Accesible desde fuera | Uso típico |
|---|---|---|---|
| NAT (por defecto) | Sí, con la IP del anfitrión | No | Laboratorios, VMs que solo necesitan salir |
| Aislada | No | No | Redes internas entre VMs, bases de datos, pruebas |
| Enrutada | Sí, sin NAT | Sí, si la red externa tiene ruta hacia la subred | Subredes propias enrutadas al anfitrión |
| Puente (bridge) | Sí, como un equipo más de la LAN | Sí | VMs con IP de la red física |
Paso 1: Revisar la red NAT por defecto
Al instalar libvirt se crea la red default: NAT sobre 192.168.122.0/24, con el anfitrión en 192.168.122.1 haciendo de puerta de enlace, DHCP y DNS. Lista las redes:
virsh net-list --all
Name State Autostart Persistent
--------------------------------------------
default active yes yes
Muestra su definición:
virsh net-dumpxml default
<network>
<name>default</name>
<uuid>2b9f4c1e-6d0a-4f7e-9c3b-8a1d5e2f7c60</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:6e:21:4a'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
En el anfitrión, la red es el bridge virbr0:
ip -brief addr show virbr0
virbr0 UP 192.168.122.1/24
Las concesiones DHCP muestran qué IP tiene cada VM:
virsh net-dhcp-leases default
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID
-----------------------------------------------------------------------------------------------------------
2026-09-25 12:41:05 52:54:00:3b:8a:12 ipv4 192.168.122.57/24 vm1 ff:56:50:4d:98:...
libvirt activa por sí mismo el reenvío IP (net.ipv4.ip_forward) y añade las reglas de NAT al arrancar la red; no hace falta configurarlas a mano.
Paso 2: Reservar una IP fija por DHCP
Para que una VM tenga siempre la misma IP sin configurarla dentro del invitado, crea una reserva DHCP ligada a su MAC. Obtén la MAC de la VM:
virsh domiflist vm1
Interface Type Source Model MAC
-------------------------------------------------------------
vnet0 network default virtio 52:54:00:3b:8a:12
Añade la reserva a la red default. --live la aplica a la red en marcha y --config la guarda de forma persistente:
virsh net-update default add ip-dhcp-host "<host mac='52:54:00:3b:8a:12' name='vm1' ip='192.168.122.10'/>" --live --config
Comprueba que aparece en la definición:
virsh net-dumpxml default | grep "host mac"
<host mac='52:54:00:3b:8a:12' name='vm1' ip='192.168.122.10'/>
La VM recibirá la nueva IP cuando renueve la concesión. Reiníciala o renueva DHCP desde dentro, y verifica con virsh domifaddr vm1. Elige IPs fijas que no choquen con otras reservas; si quieres separarlas del rango dinámico, reduce el <range> de la red con virsh net-edit default.
Paso 3: Crear una red aislada
Una red aislada conecta VMs entre sí y con el anfitrión, sin salida a Internet. Es útil para el tráfico interno, por ejemplo entre una aplicación y su base de datos. Crea el archivo XML:
nano ~/red-interna.xml
<network>
<name>interna</name>
<bridge name='virbr10' stp='on' delay='0'/>
<ip address='10.10.10.1' netmask='255.255.255.0'>
<dhcp>
<range start='10.10.10.100' end='10.10.10.200'/>
</dhcp>
</ip>
</network>
Al no tener elemento <forward>, libvirt no crea reglas de NAT ni de reenvío. Define la red, iníciala y márcala para arrancar con el sistema:
virsh net-define ~/red-interna.xml
virsh net-start interna
virsh net-autostart interna
Verifica que está activa:
virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active yes yes
interna active yes yes
Añade a vm1 una segunda interfaz conectada a esta red, en caliente y de forma persistente:
virsh attach-interface vm1 network interna --model virtio --live --config
Dentro de la VM aparecerá una nueva interfaz (por ejemplo enp7s0). En las imágenes cloud de Ubuntu, netplan solo configura por DHCP la interfaz inicial, así que añade la nueva en el invitado:
sudo nano /etc/netplan/60-interna.yaml
network:
version: 2
ethernets:
enp7s0:
dhcp4: true
dhcp4-overrides:
use-routes: false
use-routes: false evita que esta interfaz añada una ruta por defecto que compita con la de la red NAT. Aplica la configuración en la VM y comprueba la IP:
sudo chmod 600 /etc/netplan/60-interna.yaml
sudo netplan apply
ip -brief addr
Sustituye enp7s0 por el nombre real que muestre ip link en tu VM. Repite con otra VM y comprueba que se ven con ping entre sus IPs 10.10.10.x.
Paso 4: Crear una red enrutada
En modo enrutado, el anfitrión reenvía el tráfico de la subred de las VMs sin NAT: las VMs salen con sus propias IPs. Tiene sentido cuando dispones de una subred que tu router o proveedor enruta hacia la IP del anfitrión. Si nadie en la red externa sabe llegar a esa subred, el tráfico de vuelta se perderá.
Crea la definición, sustituyendo 10.20.0.0/24 por tu subred:
nano ~/red-enrutada.xml
<network>
<name>enrutada</name>
<forward mode='route'/>
<bridge name='virbr20' stp='on' delay='0'/>
<ip address='10.20.0.1' netmask='255.255.255.0'>
<dhcp>
<range start='10.20.0.100' end='10.20.0.200'/>
</dhcp>
</ip>
</network>
Define e inicia la red:
virsh net-define ~/red-enrutada.xml
virsh net-start enrutada
virsh net-autostart enrutada
En el router de tu red, añade una ruta estática hacia 10.20.0.0/24 con la IP del anfitrión como siguiente salto. Si el router es otro servidor Linux, sería:
sudo ip route add 10.20.0.0/24 via your_server_ip
Para comprobarlo, conecta una VM a la red enrutada y haz ping a su IP 10.20.0.x desde un equipo de la red externa.
Paso 5: Conectar las VMs a la red física con un bridge
En modo puente, las VMs se conectan a la misma red que la interfaz física del anfitrión y obtienen IPs de esa red, como cualquier otro equipo. Hay que convertir la interfaz física en miembro de un bridge br0 que pasa a tener la IP del anfitrión.
Importantemuchos proveedores de hosting solo aceptan tráfico de la MAC de la interfaz física del servidor y descartan las MAC de las VMs. Antes de usar un bridge en un servidor alojado, confirma con tu proveedor cómo se asignan IPs adicionales a VMs. En una LAN propia funciona sin más.
Identifica la interfaz física y la configuración actual de netplan:
ip -brief link
ls /etc/netplan/
Haz una copia de seguridad del archivo actual (el nombre puede variar, por ejemplo 50-cloud-init.yaml):
sudo cp /etc/netplan/50-cloud-init.yaml ~/50-cloud-init.yaml.bak
Edita la configuración para que la IP pase de la interfaz física al bridge. Este ejemplo usa la interfaz eno1 y una IP estática; sustituye las direcciones por las tuyas:
sudo nano /etc/netplan/50-cloud-init.yaml
network:
version: 2
ethernets:
eno1:
dhcp4: false
bridges:
br0:
interfaces:
- eno1
addresses:
- 192.168.1.50/24
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses:
- 1.1.1.1
- 9.9.9.9
parameters:
stp: false
forward-delay: 0
Si el archivo lo genera cloud-init, evita que lo sobrescriba en el siguiente arranque:
echo 'network: {config: disabled}' | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
Aplica los cambios con netplan try, que revierte la configuración automáticamente si no confirmas con Enter en 120 segundos. Así no te quedas sin acceso si algo falla:
sudo netplan try
Verifica que la IP está ahora en br0:
ip -brief addr show br0
br0 UP 192.168.1.50/24
Crea una red de libvirt que use ese bridge, para poder conectar VMs por nombre de red:
nano ~/red-puente.xml
<network>
<name>puente</name>
<forward mode='bridge'/>
<bridge name='br0'/>
</network>
virsh net-define ~/red-puente.xml
virsh net-start puente
virsh net-autostart puente
En este modo libvirt no ofrece DHCP: la VM obtendrá la IP del DHCP de tu red o tendrás que configurarla estática dentro del invitado. Conecta una VM:
virsh attach-interface vm1 network puente --model virtio --live --config
Comprueba desde otro equipo de la LAN que llegas a la IP que haya recibido la VM.
Paso 6: Gestionar y eliminar redes
Para editar una red persistente, usa net-edit. La mayoría de los cambios se aplican al reiniciar la red, lo que desconecta momentáneamente las VMs que la usan:
virsh net-edit interna
virsh net-destroy interna
virsh net-start interna
Tras reiniciar una red, las VMs en marcha pierden su conexión con el bridge. Reconéctalas apagándolas y arrancándolas con virsh shutdown y virsh start.
Para eliminar una red, detenla y borra su definición:
virsh net-destroy enrutada
virsh net-undefine enrutada
Antes, desconecta las interfaces de las VMs que la usen con virsh detach-interface vm1 network --mac 52:54:00:xx:xx:xx --live --config, usando la MAC que muestre virsh domiflist vm1.
Solución de problemas
error: Failed to start network ... Network is already in use by interface: la subred de la red choca con otra interfaz del anfitrión. Elige otra subred en el XML.virsh net-startfalla por el bridgebr0en modo puente: el bridge no existe en el sistema. Comprueba conip link show br0que netplan lo creó.- Las VMs no obtienen IP en una red NAT o aislada: comprueba que la red está
activeconvirsh net-listy que dnsmasq está en marcha conps aux | grep dnsmasq. Revisa si el invitado usa DHCP en esa interfaz. - Las VMs en NAT no salen a Internet tras instalar un firewall: libvirt añade sus reglas al arrancar la red; si recargaste el firewall después, reinicia libvirt con
sudo systemctl restart libvirtdpara que vuelva a crearlas. - Te quedas sin conexión al configurar el bridge: si no confirmaste
netplan try, la configuración se revierte sola. Si usastenetplan apply, entra por la consola del servidor y restaura la copia de seguridad.
Conclusión
Has revisado la red NAT de libvirt, fijado IPs por DHCP, creado una red aislada para tráfico interno, una red enrutada sin NAT y un bridge para conectar VMs a la red física. Como siguientes pasos:
- Publica servicios de VMs en red NAT con un proxy inverso (Nginx o HAProxy) en el anfitrión.
- Combina una red aislada para el tráfico interno con NAT o puente solo en las VMs que lo necesiten.
- Consulta la documentación de formato de redes de libvirt (
https://libvirt.org/formatnetwork.html) para IPv6, DNS y otras opciones.
