Red del host y SDN: bridges, VLAN, bonding, NAT y overlays
Red del host y SDN: bridges, VLAN, bonding, NAT y overlays
Hasta ahora casi todo lo que has hecho vive dentro del nodo. Creaste VMs en el capítulo 3, contenedores en el capítulo 6 y les colgaste discos del almacenamiento del capítulo 7. Todos comparten una cosa que aún no has tocado en serio: el vmbr0 que dejó el instalador, con la IP de gestión encima y la primera NIC como único puerto.
Ese vmbr0 funciona hasta que deja de funcionar. Deja de funcionar cuando necesitas separar gestión de guests, cuando el hoster te corta el puerto porque ve cinco MAC en una interfaz, cuando quieres redundancia de enlace sin romper corosync, cuando dos clientes necesitan la misma VLAN 100 sin verse, o cuando quieres una red L2 que atraviese tres nodos en subredes IP distintas.
Este capítulo cubre las dos capas que resuelven todo eso. Primero la red clásica de Linux, que es la que realmente usa Proxmox: un fichero de texto, ifupdown2, bridges, bonds y VLANs. Después el stack SDN, que no sustituye a la anterior sino que se apoya en ella para generar bridges, túneles VXLAN y configuración de FRRouting en todos los nodos a la vez.
Advertencia: tocar red en un nodo remoto es la forma más habitual de dejarte fuera de tu propio servidor. Todo lo que sigue asume que tienes IPMI, iKVM o acceso físico. Si no lo tienes, lee primero la sección de orden seguro del final.
/etc/network/interfaces, el fichero .new y pvenetcommit
Proxmox VE no inventa un stack de red propio: usa el estándar de Debian, un fichero en formato interfaces(5). Lo que sí añade es un mecanismo de staging, y esta cita literal es la clave del capítulo entero:
“Proxmox VE does not write changes directly to
/etc/network/interfaces. Instead, we write into a temporary file called/etc/network/interfaces.new, this way you can do many related changes at once.”
Cuando editas la red en Nodo → System → Network, nada se aplica. Se acumula en /etc/network/interfaces.new y la GUI muestra el aviso de cambios pendientes con los botones Apply Configuration y Revert.
Hay un tercer camino: reiniciar. El servicio systemd pvenetcommit activa el .new antes de que arranque networking.service. Es útil y peligroso a partes iguales: si dejas cambios a medias en staging y meses después alguien reinicia el nodo, la red cambia sin previo aviso.
flowchart TD
A["Editas la red en la GUI"] --> B["Se escribe en /etc/network/interfaces.new"]
B --> C{"Como aplicas"}
C -->|"Boton Apply Configuration"| D["Mueve el .new al fichero real y ejecuta ifreload -a"]
C -->|"Reboot del nodo"| E["pvenetcommit activa el .new antes de networking.service"]
C -->|"Boton Revert"| F["Borra interfaces.new y no cambia nada"]
G["Editas el fichero a mano"] --> H["ifreload -a"]
D --> Z["Red activa"]
E --> Z
H --> Z
Comprobar si tienes cambios colgando es una orden:
ls -l /etc/network/interfaces.new
diff -u /etc/network/interfaces /etc/network/interfaces.new
Las herramientas de PVE se esfuerzan en conservar las modificaciones manuales, pero la documentación recomienda la GUI porque valida antes de escribir.
ifupdown2 e ifreload: recarga sin cortar a los guests
Proxmox usa ifupdown2, que viene por defecto en instalaciones nuevas desde PVE 7.0. Si instalaste sobre Debian a mano, comprueba que está: apt install ifupdown2.
La diferencia con las herramientas clásicas importa mucho. Aviso literal:
“It’s discouraged to use the traditional Debian tools
ifupandifdownif unsure, as they have some pitfalls like interrupting all guest traffic onifdown vmbrXbut not reconnecting those guest again when doingifupon the same bridge later.”
En la práctica: haces ifdown vmbr0 && ifup vmbr0, el bridge vuelve, pero los tap de las VMs y los veth de los contenedores no se reenganchan. Todos tus guests quedan sin red hasta que los reinicias uno a uno.
La orden correcta es ifreload -a, que reconcilia en caliente: “It is non-disruptive. It will fix running config to match what is configured in the interfaces file without bringing the interface down.” Su sinopsis es ifreload [-h] (-a|-c) [-v] [-d] [-f] [-n] [-s], con -a para todas las interfaces auto, -c para las actualmente levantadas, -s para syntax-check, -n para dry-run, -d para depuración y -X para excluir interfaces.
La secuencia de validación que evita disgustos:
ifreload -a -s && ifreload -a -n # syntax check y dry-run: no tocan nada
ifreload -a # aplicar
journalctl -b -u networking -u pvenetcommit
Gotcha del SDN: al final de /etc/network/interfaces tiene que existir esta línea, en todos los nodos: source /etc/network/interfaces.d/*. PVE la instala, pero se pierde en instalaciones manuales sobre Debian, y sin ella las VNets del SDN no se crean nunca sin que ningún error te lo diga.
Nombres de interfaz: esquema systemd, pinning y ficheros .link
Desde PVE 5.0 las instalaciones nuevas usan el esquema de nombres predecibles de systemd con prefijo en*; los hosts anteriores conservan eth0 y compañía incluso tras actualizar. Los bridges suelen ser vmbr[N] con 0 <= N <= 4094, aunque vale cualquier cadena alfanumérica que empiece por letra y tenga como máximo 10 caracteres. Las VLANs añaden el ID tras un punto: eno1.50, bond1.30.
Los patrones systemd para Ethernet son o<index> para on-board, s<slot> para hotplug, [P<domain>]p<bus>s<slot>[f<function>] por bus PCI y x<MAC> por dirección MAC; eno1 es la primera NIC integrada y enp3s0f1 la función 1 de la tarjeta en el bus 3, slot 0. Referencia completa en systemd.net-naming-scheme(7).
El problema aparece en los upgrades: un systemd nuevo puede renombrarte las interfaces. Se puede fijar la versión del esquema con el parámetro de kernel net.naming-scheme=v252 y un reboot, pero aun así los nombres pueden cambiar por kernel o driver nuevos. La guía de upgrade de 8 a 9 lo dice: el kernel nuevo reconoce más funciones del hardware, como virtual functions, y como el nombre deriva de la dirección PCI, algunas NIC cambian de nombre y hay que adaptar la configuración.
pve-network-interface-pinning
PVE 9 trae una herramienta que fija los nombres generando ficheros .link de systemd en /usr/local/lib/systemd/network:
pve-network-interface-pinning generate # todas, prefijo nic1, nic2, ...
pve-network-interface-pinning generate --prefix myprefix
pve-network-interface-pinning generate --interface enp1s0
pve-network-interface-pinning generate --interface enp1s0 --target-name if42
Reescribe automáticamente el nombre viejo en /etc/network/interfaces, /etc/pve/nodes/<nodename>/host.fw, /etc/pve/sdn/controllers.cfg y /etc/pve/sdn/fabrics.cfg.
Gotcha: como el mapeo es local al nodo, los nombres de /etc/pve/firewall/cluster.fw no se actualizan. Ese fichero lo editas tú, y si no lo haces, las reglas del datacenter que referencian interfaces dejan de coincidir. El firewall completo está en el capítulo 10.
Por cada fichero tocado se genera uno con sufijo .new, revisable con diff -y /etc/network/interfaces /etc/network/interfaces.new. Para revertir antes del reboot, borra los .new y los .link; para aplicar, reinicia el nodo.
Ficheros .link manuales
Van en /etc/systemd/network/ con nombre <n>-<id>.link, con n menor que 99:
# /etc/systemd/network/10-enwan0.link
[Match]
MACAddress=aa:bb:cc:dd:ee:ff
Type=ether
[Link]
Name=enwan0
Uno. Type=ether es obligatorio en la práctica: sin él la regla captura bridges, bonds o VLANs que comparten MAC con la física. Dos. Los .link se copian al initramfs, así que tras crear, modificar o borrar uno hace falta update-initramfs -u -k all y reboot. Tres. Nombra empezando por en o eth para que PVE lo reconozca como dispositivo físico, pero eligiendo algo que no colisione con ningún patrón systemd; enwan0 sirve.
El bridge vmbrX como switch virtual
Un bridge Linux es un switch en software. Cada host admite hasta 4094; el instalador crea uno, vmbr0, con la primera Ethernet como puerto:
auto lo
iface lo inet loopback
iface eno1 inet manual
auto vmbr0
iface vmbr0 inet static
address 192.168.10.2/24
gateway 192.168.10.1
bridge-ports eno1
bridge-stp off
bridge-fd 0
| Atributo | Descripción | Default |
|---|---|---|
bridge-ports | puertos del bridge; obligatorio, none para bridge sin uplink | — |
bridge-stp | activa Spanning Tree | no |
bridge-fd | forward delay | 15, PVE pone 0 |
bridge-vlan-aware | activa el filtrado VLAN | — |
bridge-vids | VLAN IDs permitidos; bajo el bridge o bajo el puerto | — |
bridge-pvid / bridge-access | PVID y VLAN de acceso; solo bajo el puerto | — |
bridge-mcquerier | multicast querier | no |
mtu | MTU de la interfaz | 1500 |
Los bridge-vids puestos bajo el bridge los heredan sus puertos salvo que el puerto declare los suyos.
El comportamiento visible desde fuera es la raíz de media docena de problemas posteriores: “the network sees each virtual machine as having its own MAC, even though there is only one network cable connecting all of these VMs to the network”. Perfecto en una LAN propia, letal en un hoster con binding IP/MAC.
Desde PVE 7.3 existe un anti-spoofing L2: añadiendo bridge-disable-mac-learning 1 al bridge, PVE inserta manualmente en la FDB la MAC configurada de cada VM y contenedor y el bridge deja de aprender. Consecuencia: un guest solo puede emitir con su MAC real, así que un bridge propio o un contenedor anidado dentro de la VM se quedan sin red.
Bridge VLAN-aware frente al modelo tradicional
La documentación enumera cuatro formas de hacer VLAN para guests, y se mezclan mal:
| Modo | Cómo funciona | Cuándo |
|---|---|---|
| VLAN awareness en el bridge Linux | cada NIC virtual lleva su tag, el bridge filtra de forma transparente; también admite modo trunk | el default razonable hoy |
| VLAN tradicional | crea un dispositivo VLAN y un bridge por VLAN; una VM en VLAN 5 genera eno1.5 y vmbr0v5, que permanecen hasta el siguiente reboot | compatibilidad con setups antiguos |
| VLAN de Open vSwitch | usa la función VLAN de OVS | si ya estás en OVS |
| VLAN dentro del guest | el guest etiqueta y no se puede influir desde fuera | varias VLANs en una sola NIC virtual |
La regla oficial de dónde poner la VLAN del host: “In general, you should configure the VLAN on the interface with the least abstraction layers between itself and the physical NIC.”
Con bridge tradicional, dejar la gestión en la VLAN 5 obliga a un bridge extra, vmbr0v5, colgado de eno1.5, mientras vmbr0 queda inet manual sobre eno1. Con bridge VLAN-aware todo eso desaparece:
auto lo
iface lo inet loopback
iface eno1 inet manual
auto vmbr0.5
iface vmbr0.5 inet static
address 10.10.10.2/24
gateway 10.10.10.1
auto vmbr0
iface vmbr0 inet manual
bridge-ports eno1
bridge-stp off
bridge-fd 0
bridge-vlan-aware yes
bridge-vids 2-4094
Tres detalles. Uno. El bridge padre queda sin IP; la dirección va en la subinterfaz vmbr0.5. Dos. bridge-vids 2-4094 es exactamente lo que escribe la GUI al marcar “VLAN aware”. Tres. La VLAN 1 no está en ese rango porque es el PVID untagged por defecto.
VLAN en el guest: tag, trunks y las opciones de net[n]
El etiquetado de una VM va en su clave net[n] de /etc/pve/qemu-server/<VMID>.conf:
net[n]: [model=]<enum> [,bridge=<bridge>] [,firewall=<1|0>] [,host-tunnel=<1|0>]
[,link_down=<1|0>] [,macaddr=<XX:XX:XX:XX:XX:XX>] [,mtu=<integer>]
[,queues=<integer>] [,rate=<number>] [,tag=<integer>]
[,trunks=<vlanid[;vlanid...]>] [,<model>=<macaddr>]
| Clave | Rango | Qué significa |
|---|---|---|
bridge= | vmbr0, … | bridge al que se engancha. Si lo omites, la VM cae en la red kvm user NATeada |
tag= | 1 – 4094 | VLAN tag aplicado a los paquetes de esa interfaz |
trunks= | vlanid[;vlanid...] | VLANs que pasan sin tocar; etiqueta el guest |
firewall= | 0/1 | si la interfaz la protege el firewall |
mtu= | 1 – 65520 | fuerza el MTU, solo VirtIO; 1 o vacío hereda el del bridge |
queues= | 0 – 64 | multiqueue; se recomienda igualarlo al número de vCPUs |
rate= | número | límite de tasa en mbps, que la doc define como megabytes por segundo |
model= | virtio, e1000, vmxnet3, … | virtio rinde mejor; e1000 es el default de la GUI |
host-tunnel= | 0/1 | GSO over UDP tunnel offload en VirtIO; requiere QEMU > 10.2 y está deshabilitado por defecto desde machine version 11.0+pve1 por un problema del driver virtio-net en kernels guest |
En LXC la clave lleva además la IP: net[n]: name=<string> [,bridge=<bridge>] [,firewall=<1|0>] [,gw=<GatewayIPv4>] [,hwaddr=...] [,ip=<(IPv4/CIDR|dhcp|manual)>] [,ip6=...] [,mtu=...] [,rate=<mbps>] [,tag=<integer>] [,trunks=...] [,type=<veth>].
# VM en VLAN 100, virtio, firewall activo en la NIC
qm set 100 --net0 virtio,bridge=vmbr0,tag=100,firewall=1
# Trunk de VLANs 10, 20 y 30: la VM etiqueta por su cuenta
qm set 100 --net0 virtio,bridge=vmbr0,trunks=10;20;30
# Contenedor con IP estatica en VLAN 50
pct set 200 --net0 name=eth0,bridge=vmbr0,tag=50,ip=10.50.0.10/24,gw=10.50.0.1,firewall=1
Sobre omitir bridge=: la VM recibe la red de usuario de QEMU, con gateway 10.0.2.2, DNS 10.0.2.3, SMB 10.0.2.4 y DHCP desde 10.0.2.15. La doc es tajante: “The NAT mode is much slower than the bridged mode, and should only be used for testing. This mode is only available via CLI or the API, but not via the web UI.”
Bonding: los siete modos y los avisos para corosync
| Modo | Nombre ifupdown2 | Qué hace | Requiere switch |
|---|---|---|---|
| Round-robin | balance-rr | transmite en orden secuencial del primer slave al último; balanceo y tolerancia a fallos | sí, etherchannel estático |
| Active-backup | active-backup | un solo slave activo, otro releva al fallar; la MAC del bond solo se ve en un puerto para no distorsionar el switch. Solo tolerancia a fallos | no |
| XOR | balance-xor | (MAC origen XOR MAC destino) mod nº slaves; mismo slave por MAC destino | sí |
| Broadcast | broadcast | transmite por todos los slaves | sí |
| LACP | 802.3ad | IEEE 802.3ad; agrupa enlaces de igual velocidad y duplex y usa todos los del aggregator activo | sí, con LACP |
| Adaptive TX LB | balance-tlb | reparte el saliente según la carga de cada slave; el entrante lo recibe un slave designado | no |
| Adaptive LB | balance-alb | balance-tlb más balanceo de entrada IPv4 reescribiendo la source hardware address de las ARP Replies | no |
Recomendación oficial: “If your switch supports the LACP (IEEE 802.3ad) protocol, then we recommend using the corresponding bonding mode (802.3ad). Otherwise you should generally use the active-backup mode.”
Advertencia sobre corosync. La doc recomienda para el clúster configurar varias redes en vez de un bond, porque corosync conmuta entre ellas por sí solo, y añade que “Some bond modes are known to be problematic for Corosync”. Eso descarta balance-rr, balance-xor, balance-tlb y balance-alb para la red de corosync. Si usas LACP ahí, pon bond-lacp-rate fast en el nodo y en el switch: baja el failover de 90 segundos a unos 3, que es la diferencia entre un parpadeo y un fence. El quorum está en el capítulo 11.
Defaults de ifupdown2 que no conviene heredar por descuido: bond-mode es balance-rr, bond-miimon es 0 con rango 0-255, bond-xmit-hash-policy es layer2 (valores layer2, layer2+3, layer3+4), bond-lacp-rate es 0, es decir slow cada 30 s, y bond-min-links es 0. Que el modo por defecto sea balance-rr significa que un bond sin bond-mode explícito no es el que crees.
La combinación que acaba en producción casi siempre es bond LACP más bridge VLAN-aware con la gestión en su propia VLAN:
auto bond0
iface bond0 inet manual
bond-slaves eno1 eno2
bond-miimon 100
bond-mode 802.3ad
bond-xmit-hash-policy layer3+4
bond-lacp-rate 1
auto vmbr0
iface vmbr0 inet manual
bridge-ports bond0
bridge-stp off
bridge-fd 0
bridge-vlan-aware yes
bridge-vids 2-4094
auto vmbr0.10
iface vmbr0.10 inet static
address 10.10.10.2/24
gateway 10.10.10.1
Sin switch gestionado, el bloque del bond se sustituye por bond-mode active-backup más bond-primary eno1, y se quitan bond-xmit-hash-policy y bond-lacp-rate. Diagnóstico: cat /proc/net/bonding/bond0 para ver modo, slaves y partner LACP, e ip -d link show bond0 para los detalles del driver.
MTU y jumbo frames: qué restar en cada encapsulación
El default es 1500 en todo. Para jumbo frames hay que subir el MTU en la NIC física, el bond y el bridge, los tres: si te olvidas de uno, la trama grande muere ahí. En OVS el atributo se llama ovs_mtu. En una VM, mtu=1 en net[n] hereda el del bridge y solo funciona con VirtIO.
| Escenario | Bytes que se restan | MTU con físico 1500 |
|---|---|---|
| Ethernet normal | 0 | 1500 |
| QinQ / 802.1ad | 4 | 1496 |
| VXLAN | 50 | 1450 |
| IPsec sobre VXLAN, IPv4 | 50 + 60 | 1390 |
| IPsec sobre VXLAN, IPv6 | 50 + 80 | 1370 |
La documentación del SDN usa 1370 como referencia para VXLAN cifrado con strongSwan, porque 1370 + 80 + 50 = 1500.
Gotcha de hardware documentado: “Some newer Intel Gigabit NICs have a hardware limitation which means the maximum MTU they can support is 8996 (instead of 9000). If your interfaces aren’t coming up and you are trying to use 9000, this is likely the reason and can be difficult to debug.” Si pones 9000 y la interfaz no sube, prueba 8996 antes de perder la tarde.
Verificación de extremo a extremo, con el bit de no fragmentar:
ip link show vmbr0 | grep mtu
ping -M do -s 8972 10.55.0.11 # 9000 menos 20 de IP y 8 de ICMP
ping -M do -s 1422 10.0.3.101 # prueba de 1450, tipico VXLAN
Open vSwitch: cuándo compensa y el error número uno
Se instala aparte con apt install openvswitch-switch. La justificación oficial: “Open vSwitch supports most of the features you would find on a physical switch, providing some advanced features like RSTP support, VXLANs, OpenFlow, and supports multiple vlans on a single bridge. If you need these features, it makes sense to switch to Open vSwitch.”
Como el bridge Linux VLAN-aware ya te da multi-VLAN en un solo bridge, hoy OVS aporta valor sobre todo si necesitas RSTP, OpenFlow o topologías mesh directas entre nodos.
Regla absoluta, sin excepciones:
“Open vSwitch and Linux bonding and bridging or vlans MUST NOT be mixed. For instance, do not attempt to add a vlan to an OVS Bond, or add a Linux Bond to an OVSBridge or vice-versa.”
Los tipos de puerto son OVSBridge (el switch, que debe contener los ethernet crudos, los bonds y los puertos internos), OVSBond (agregación, que debe referirse a dispositivos ethernet crudos), OVSIntPort (interfaz interna del host para una VLAN concreta del bridge) y OVSPort (configuración de una interfaz individual con tags y vlan_mode).
Y ahora el error número uno, que la wiki repite dos veces con mayúsculas:
“NOTE: All interfaces must be listed under
ovs_portsthat are part of the bridge even if you have a port definition (e.g. OVSIntPort) that cross-references the bridge!!!”
El síntoma es exacto: la interfaz existe en /etc/network/interfaces, declara su ovs_bridge, y nunca sube; ovs-vsctl show no la lista. Ejemplo correcto, con bond LACP y dos puertos internos, uno de gestión y otro para Ceph con jumbo frames:
auto bond0
iface bond0 inet manual
ovs_bridge vmbr0
ovs_type OVSBond
ovs_bonds eth0 eth1
ovs_options bond_mode=balance-tcp lacp=active other_config:lacp-time=fast
ovs_mtu 9000
auto vmbr0
iface vmbr0 inet manual
ovs_type OVSBridge
ovs_ports bond0 vlan50 vlan55
ovs_mtu 9000
auto vlan50
iface vlan50 inet static
ovs_type OVSIntPort
ovs_bridge vmbr0
ovs_options tag=50
address 10.50.10.44
netmask 255.255.255.0
gateway 10.50.10.1
ovs_mtu 1500
El segundo puerto interno, vlan55 para Ceph, es idéntico salvo por ovs_options tag=55, su dirección y ovs_mtu 9000, y también tiene que estar listado en ovs_ports.
Sin switch gestionado, el modo del bond pasa a balance-slb en lugar de balance-tcp con LACP. Dos avisos más: RSTP no se puede activar con ovs_options ni ovs_extra, hace falta un script up ovs-vsctl set Bridge ${IFACE} rstp_enable=true, y un bond no puede participar en RSTP; y sobre multicast, “Right now Open vSwitch doesn’t do anything in regards to multicast… you should instead set up your querier at your router or switch”. Para diagnosticar: ovs-vsctl show, ovs-vsctl list-ports vmbr0, ovs-appctl bond/show bond0 y ovs-appctl lacp/show bond0.
Redes routed y masquerading: el caso del hoster
Todo lo anterior asume que puedes emitir tramas con MACs arbitrarias por tu puerto. En un servidor dedicado alquilado casi nunca es cierto:
“Most hosting providers do not support the above setup. For security reasons, they disable networking as soon as they detect multiple MAC addresses on a single interface.”
flowchart TD
A["Donde vive el nodo"] --> B{"LAN privada con gateway propio"}
B -->|"Si"| C["Bridged: vmbr0 con la NIC como puerto"]
B -->|"No"| D{"El hoster da rango publico para los guests"}
D -->|"Si y permite varias MAC"| E["Bridged con MAC virtuales registradas"]
D -->|"Si pero con binding IP y MAC"| F["Routed: bridge-ports none mas proxy_arp y rutas /32"]
D -->|"Solo una IP publica"| G["Masquerading con SNAT para la salida"]
G --> H["Port forwarding con DNAT para la entrada"]
Configuración routed
Escenario de la documentación: IP pública 198.51.100.5, bloque adicional para VMs 203.0.113.16/28.
auto eno0
iface eno0 inet static
address 198.51.100.5/29
gateway 198.51.100.1
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up echo 1 > /proc/sys/net/ipv4/conf/eno0/proxy_arp
auto vmbr0
iface vmbr0 inet static
address 203.0.113.17/28
bridge-ports none
bridge-stp off
bridge-fd 0
Uno. bridge-ports none significa que el bridge no toca la NIC física: el tráfico pasa por routing L3 y hacia el switch del hoster solo sale una MAC, la del host. Dos. proxy_arp en la física es lo que hace que el host responda ARP por las IPs del bloque enrutado. Nota oficial: 203.0.113.17 es la primera dirección utilizable del bloque, porque la dirección de red no se puede asignar a una interfaz.
Masquerading con una sola IP pública
auto vmbr0
#private sub network
iface vmbr0 inet static
address 10.10.10.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o eno1 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o eno1 -j MASQUERADE
Para publicar un servicio interno se añade DNAT en el mismo bloque, con su post-down simétrico: post-up iptables -t nat -A PREROUTING -i eno1 -p tcp --dport 8443 -j DNAT --to 10.10.10.20:443.
El gotcha de las conntrack zones
Cuesta horas de depuración y es una sola cita:
“In some masquerade setups with firewall enabled, conntrack zones might be needed for outgoing connections. Otherwise the firewall could block outgoing connections since they will prefer the POSTROUTING of the VM bridge (and not MASQUERADE).”
El síntoma: con el firewall de Proxmox activado, las VMs NATeadas dejan de salir a internet y las reglas parecen correctas. La solución oficial va también en /etc/network/interfaces:
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
El fwbr+ referencia los bridges de firewall que Proxmox intercala por guest cuando activas el firewall en la NIC.
Breaking change de PVE 9 con sysctl
Advertencia: en PVE 9 /etc/sysctl.conf ya no lo honra systemd-sysctl. Los ajustes van a /etc/sysctl.d/<NN>-<nombre>.conf. Afecta directamente a ip_forward en setups routed y a rp_filter en EVPN con varios exit nodes. Si vienes de PVE 8 con el forwarding en sysctl.conf, tras el upgrade el NAT deja de funcionar sin explicación aparente.
printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' > /etc/sysctl.d/99-forward.conf
systemctl restart systemd-sysctl
sysctl net.ipv4.ip_forward
Escenarios reales: Hetzner y OVH
Hetzner lo explica sin rodeos: “Hetzner has a strict IP/MAC binding to ensure security and prevent spoofing. In some scenarios, only a routed setup is possible. For example, additional subnets, single failover IPs and failover subnets are always MAC-bound and statically routed on the main IP address of the server, and can only be configured in a routed setup.”
Lo concreto que hay que respetar. Durante la instalación, marcar “Pin network interface names”. Las IPs adicionales se ponen con máscara /32 sobre vmbr0, con una ruta por cada una; la razón textual es que “devices such as vmbr0 inherently route traffic only for IP addresses that fall within the same subnet. By using a /32 mask, each additional IP is treated as its own unique network entity”. Con vSwitch, MTU 1400 es obligatorio. Y si vas por bridged, hay que pedir una MAC virtual por cada IP adicional en el Robot Panel: si el router no reconoce la MAC de origen, el tráfico se marca como abuso y el servidor puede acabar bloqueado.
auto vmbr0
iface vmbr0 inet static
address 198.51.100.10/32 # IP principal
bridge-ports none
bridge-stp off
bridge-fd 0
post-up ip route add 192.0.2.20/32 dev vmbr0 # IP adicional de otra subred
post-up ip route add 198.51.100.30/32 dev vmbr0 # IP adicional de la misma subred
post-up ip route add 172.17.234.100/32 dev vmbr0 # IP failover
Con vSwitch y subred pública el bridge cuelga de una subinterfaz VLAN (enp0s31f6.4009 en un vmbr4009 con mtu 1400), sin necesidad de bridge VLAN-aware ni de etiquetar dentro de la VM.
Gotcha operativo, literal: “you will have to restart the network after applying the network configuration for the Proxmox host to add the static routes. If virtual machines or containers are running during the network restart, you will need to stop (not just restart) and then start them again.” Parar y arrancar, no reiniciar: solo así se recrean las conexiones punto a punto de cada guest con el host.
OVH. Dos datos que evitan la mayoría de los fallos: el gateway sigue el patrón x.y.z.254 de la subred del servidor y se consulta en el panel o por API; y como en el guest la máscara es /32 con el gateway fuera de la subred, en netplan hay que declararlo on-link.
network:
ethernets:
ens18:
addresses:
- 192.0.2.1/32
routes:
- to: 0.0.0.0/0
via: 203.0.113.254
on-link: true
version: 2
Las alternativas de OVH al bridging con MAC virtual son vRack o el modo routed.
SDN: estado de soporte, instalación y modelo pending/apply
Todo lo anterior es por nodo. El SDN define redes a nivel de datacenter y las materializa en cada nodo: bridges, subinterfaces VLAN, túneles VXLAN y configuración de FRRouting. Su estado de soporte en agosto de 2026, que conviene saber antes de apoyarse en él:
| Capa | Estado |
|---|---|
| Core SDN: gestión de VNets e integración con el stack de PVE | fully supported |
| IPAM, incluida la gestión DHCP para guests | technology preview |
| Routing complejo vía FRRouting e integración de controladores | technology preview |
El core viene por defecto desde PVE 8.1; el resto es opt-in:
# DHCP e IPAM
apt install dnsmasq
systemctl disable --now dnsmasq # la instancia por defecto NO se usa
# FRRouting: necesario para EVPN y para los fabrics
apt install frr frr-pythontools
systemctl enable frr.service
Y de nuevo: verifica que exista source /etc/network/interfaces.d/* al final de /etc/network/interfaces en todos los nodos.
Toda la configuración vive en /etc/pve/sdn/, replicada por pmxcfs a todo el clúster tal como viste en el capítulo 2: zones.cfg, vnets.cfg, subnets.cfg, controllers.cfg, fabrics.cfg, ipams.cfg, dns.cfg, prefix-lists.cfg, route-maps.cfg, firewall/<vnet>.fw, más .running-config con el estado realmente desplegado y .version con la versión aplicada. Las claves privadas de WireGuard de los fabrics van aparte, en /etc/pve/priv/wg-keys.cfg.
El modelo de aplicación es el mismo espíritu que el interfaces.new del principio:
“New changes are not immediately applied but recorded as pending first. You can then apply a set of different changes all at once in the main SDN overview panel on the web interface. This system allows to roll-out various changes as single atomic one.”
La configuración de FRR resultante se escribe en /etc/frr/frr.conf de cada nodo, y lo que pongas en /etc/frr/frr.conf.local se anexa encima.
Zonas: simple, VLAN, QinQ, VXLAN y EVPN
Una zona define aislamiento y transporte. De ella cuelgan VNets, y de cada VNet subnets.
flowchart LR
Z["Zona SDN"] --> S["Simple: bridge aislado y routing L3 con NAT"]
Z --> V["VLAN: 802.1q sobre un bridge existente"]
Z --> Q["QinQ: 802.1ad con VLAN apilada"]
Z --> X["VXLAN: L2 sobre UDP 4789"]
Z --> E["EVPN: VXLAN mas BGP para L3 enrutable"]
S --> VN["VNets"]
V --> VN
Q --> VN
X --> VN
E --> VN
VN --> SB["Subnets con CIDR gateway SNAT y rango DHCP"]
Opciones comunes a todas: Nodes, IPAM (opcional, default pve), DNS, ReverseDNS y DNSZone.
Simple. “It will create an isolated VNet bridge. This bridge is not linked to a physical interface, and VM traffic is only local on each the node. It can be used in NAT or routed setups.” Es la única zona con DHCP automático.
VLAN. Una sola opción, Bridge: el bridge Linux u OVS ya configurado en cada nodo que permite la conexión entre nodos. El tag va en la VNet.
QinQ. Requiere bridge local VLAN-aware, un Service VLAN que es el tag externo, un Service VLAN Protocol que puede ser 802.1q (default) o 802.1ad, y MTU reducido a 1496 si el físico es 1500. Los switches deben soportar VLANs apiladas. Su caso canónico es aislar dos clientes que usan internamente la misma VLAN 100 y el mismo rango IP: con S-VLAN 20 y 30 no se ven entre sí.
VXLAN. Encapsula tramas L2 en UDP con puerto destino 4789 por defecto. Requiere una Peers Address List con las IPs de todos los nodos de la zona, o un SDN Fabric que la genere, y el underlay lo montas tú: “You have to configure the underlay network yourself to enable UDP connectivity between all peers.” Aviso explícito: VXLAN no cifra nada, y para unir sitios hay que establecer una conexión segura aparte, por ejemplo una VPN site-to-site.
EVPN. Red L3 enrutable que puede abarcar varios clústeres, usando BGP para distribuir rutas. La VNet tiene IP y MAC anycast: el bridge tiene la misma IP en todos los nodos, así que un guest la usa como gateway esté donde esté, y el routing entre VNets pasa por una interfaz VRF.
| Opción de zona EVPN | Detalle |
|---|---|
VRF VXLAN ID | VXLAN-ID dedicado a interconectar VNets; debe diferir de los VXLAN-ID de las VNets |
Primary Controller | controlador EVPN principal; se usa para autoderivar las IPs VTEP |
Additional Controllers | controladores extra que anuncian las rutas L2VPN EVPN de la zona |
VNet MAC Address | MAC anycast común a todas las VNets; se autogenera si no la das |
Exit Nodes | nodos que hacen de gateway hacia la red real y anuncian ruta por defecto |
Primary Exit Node | fuerza el tráfico por un nodo en vez de balancear. Necesario con SNAT o si el router upstream no soporta ECMP |
Exit Nodes Local Routing | necesario para alcanzar un servicio de un guest desde el propio exit node |
Advertise Subnets | anuncia la subred completa; necesario con VMs silenciosas o con varias IPs |
Disable ARP ND Suppression | requerido con floating IPs, donde IP y MAC se mueven entre máquinas |
Route-target Import | importar route targets EVPN externos, para cross-DC |
MTU | 50 bytes menos que el físico. Default 1450 |
VNets, subnets, IPAM y DHCP con dnsmasq
Una VNet acaba viéndose como un bridge con el mismo nombre en cada nodo, listo para poner en el net0 de un guest. Su ID admite como máximo 8 caracteres; tiene Alias, Zone, Tag (el VLAN ID o VXLAN ID único), VLAN Aware para configurar VLANs dentro del guest e Isolate Ports, que marca como aislados los puertos de guest de esa interfaz y exige reiniciar el guest afectado. Ese aislamiento es local a cada host: para aislar también entre nodos hay que usar el firewall de la VNet.
Las subnets restringen qué IPs son configurables, asignan gateway en zonas L3, habilitan SNAT, permiten autoasignar IPs vía IPAM y registrar en DNS. Sus opciones son ID (el CIDR, por ejemplo 10.0.0.0/8), Gateway, SNAT y DNS Zone Prefix.
El IPAM por defecto es el plugin pve, con panel en Datacenter → SDN, y es el único que hoy permite crear, editar y borrar mapeos de IP. Los otros son NetBox y phpIPAM, con URL y token; NetBox pide además un fingerprint SHA-256 que se obtiene con openssl x509 -in /etc/ssl/certs/netbox.crt -noout -fingerprint -sha256.
El DHCP tiene un solo backend, dnsmasq, y su ciclo de vida es automático: al añadir una NIC a un guest se reserva una IP en el IPAM de la zona, al arrancar el guest se crea el mapeo MAC-IP en el plugin DHCP, y al quitar la NIC o destruir el guest se borran ambas entradas. Los rangos se definen por subnet:
pvesh set /cluster/sdn/vnets/<vnet>/subnets/<subnet> \
-dhcp-range start-address=10.0.1.100,end-address=10.0.1.200 \
-dhcp-range start-address=10.0.2.100,end-address=10.0.2.200
Gotcha: “You also need to have a gateway configured for the subnet - otherwise automatic DHCP will not work.” Rango sin gateway es DHCP que no reparte nada.
Los ficheros generados viven en /etc/dnsmasq.d/<zone>/: 00-default.conf con la config global de esa instancia, 10-<zone>-<subnet_cidr>.conf con las opciones de la subred, 10-<zone>-<subnet_cidr>.ranges.conf con los rangos y ethers con los mapeos MAC-IP tomados del IPAM. No los edites, se regeneran: para personalizar, añade en la misma carpeta un 90-custom.conf, que se lee después por orden alfabético. Hay un servicio systemd por zona, dnsmasq@<zone>, y las concesiones se guardan en /var/lib/misc/dnsmasq.<zone>.leases.
Controladores EVPN y BGP, y las reglas del ASN
El controlador EVPN traduce tu zona a sesiones BGP en FRR.
| Opción | Detalle |
|---|---|
ASN # | ASN de BGP. Privados recomendados: 64512-65534 o 4200000000-4294967294 |
SDN Fabric | fabric con todos los nodos de la zona, usado como underlay |
Peers | IPs de todos los nodos de la zona, más route reflectors o nodos externos |
Nodes | nodos donde el controlador está activo |
Peer Group Name | por defecto VTEP; con varios controladores EVPN cada uno necesita el suyo |
BGP Mode | auto, el histórico, que usa iBGP salvo que exista un BGP controller; o explícito |
ebgp-multihop | saltos extra para peers no directamente conectados, solo en modo external |
La regla del ASN es dura y su violación se rechaza: “Every router can be member of exactly one Autonomous System, so any iBGP sessions on a given node (irregardless of address family) need to have the same ASN configured. Any configuration that has two iBGP sessions with different ASNs is rejected and an error thrown.” Y en la misma línea: “Every EVPN controller configured on a node must have the same ASN configured.”
El orden en que FRR deriva el ASN local está documentado: si solo existe un controlador BGP o EVPN, se usa el suyo; por compatibilidad, si hay controladores EVPN en modo auto y además un BGP controller, gana el ASN del BGP controller; en su defecto, el del EVPN controller. La IP VTEP se autogenera con su propio orden: la del loopback si hay un controlador BGP o IS-IS con interfaz loopback; si no, una IP de la lista de peers que esté configurada localmente; si no, la source IP de la ruta hacia el primer peer, cosa que puede fallar si esa ruta se anuncia dinámicamente, por ejemplo a través de un fabric.
El BGP Controller no lo usa una zona directamente: configura FRR para gestionar peers BGP, y sirve para definir un ASN distinto por nodo con eBGP o exportar rutas EVPN a un peer externo. Cita útil: “By default, for a simple full mesh EVPN, you don’t need to define a BGP controller.” El ISIS Controller cubre exportar rutas EVPN a un dominio IS-IS.
Ejemplo completo de la documentación con tres nodos y dos VNets: controlador myevpnctl con ASN 65000 y peers 192.168.0.1,192.168.0.2,192.168.0.3; zona myevpnzone con VRF VXLAN Tag 10000, MTU 1450, MAC 32:F4:05:FE:6C:0A y exit nodes node1,node2; y dos VNets, myvnet1 con tag 11000 y subnet 10.0.1.0/24 gateway 10.0.1.1, y myvnet2 con tag 12000 y subnet 10.0.2.0/24 gateway 10.0.2.1. Dentro del guest:
auto eth0
iface eth0 inet static
address 10.0.1.100/24
gateway 10.0.1.1
mtu 1450
Gotcha crítico: “You need to add reverse routes for the 10.0.1.0/24 and 10.0.2.0/24 networks to node1 and node2 on your external gateway, so that the public network can reply back.” Sin ellas, el tráfico sale y no vuelve. La excepción es tener un router BGP externo que reciba las rutas anunciadas.
Segundo gotcha: con varios exit nodes los paquetes pueden entrar por un nodo y salir por otro, y el reverse path filter los descarta. Hay que desactivarlo, recordando el cambio de PVE 9:
# /etc/sysctl.d/99-rp-filter.conf
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
Fabrics de PVE 9: OpenFabric, OSPF, BGP y WireGuard
Los fabrics llegaron en PVE 9.0 y se ampliaron en 9.2. Automatizan el routing entre nodos del clúster: son el underlay natural de EVPN y VXLAN, y sirven también como full-mesh para Ceph, tema del capítulo 12.
Se configuran en Datacenter → SDN → Fabrics → Add Fabric y requieren apt install frr frr-pythontools. Permisos: SDN.Audit o SDN.Allocate para ver, SDN.Allocate para crear o modificar, y Sys.Modify sobre cada nodo concreto para añadirlo o actualizarlo, porque eso escribe en su /etc/network/interfaces.
Dos conceptos transversales. El Loopback Prefix es un CIDR que valida que todos los router-ID caigan dentro. El Router-ID es una IPv4 en notación decimal, y por cada uno se crea automáticamente una interfaz dummy, pasiva por defecto; además se generan una access-list y un route-map que reescriben la source address de los paquetes salientes hacia la IP de esa dummy local.
| Protocolo | Notas |
|---|---|
| OpenFabric | basado en IS-IS, optimizado para spine-leaf. Nombre del fabric: máximo 8 caracteres. Hello Interval default 3 s, CSNP Interval default 10 s, Hello Multiplier por interfaz default 10. Único que soporta IPv6 hoy |
| OSPF | Area como entero de 32 bits o IP, donde 0 o 0.0.0.0 es el backbone. Redistribute desde bgp, connected, kernel o static, con route-map opcional. La dummy queda passive y toda interfaz sin IP se trata como point-to-point |
| BGP (9.2) | eBGP unnumbered: cada nodo con su ASN, peering por interfaces físicas sin IP usando link-local IPv6. BFD para detección rápida de fallos, Route Filter, route maps de entrada y salida, Redistribute. Al menos uno de IPv4/IPv6 Prefix es obligatorio. Nodos que peerean directamente deben tener ASN distintos |
| WireGuard (9.2) | VPN entre nodos PVE y externos. No aporta routing dinámico por sí mismo, pero transporta EVPN o VXLAN cifrado bajo OSPF o BGP |
Con IPv6, que solo soporta OpenFabric, hace falta forwarding IPv6 global en todos los nodos del fabric, con post-up sysctl -w net.ipv6.conf.all.forwarding=1. Aviso repetido en OSPF y OpenFabric: “When you remove an interface with an entry in /etc/network/interfaces that has manual set, then the IP will not get removed on applying the SDN configuration.”
flowchart TB
subgraph UNDER["Underlay: fabric BGP o OpenFabric"]
N1["node1 con router-id en dummy"] --- N2["node2 con router-id en dummy"]
N2 --- N3["node3 con router-id en dummy"]
N1 --- N3
end
UNDER --> VTEP["Sesiones BGP entre VTEPs del peer group VTEP"]
VTEP --> VRF["VRF de la zona EVPN con su VRF VXLAN ID"]
VRF --> V1["VNet myvnet1 con subnet 10.0.1.0/24"]
VRF --> V2["VNet myvnet2 con subnet 10.0.2.0/24"]
VRF --> EX["Exit nodes node1 y node2"]
EX --> GW["Gateway externo con rutas inversas hacia las subnets"]
BGP fabric como underlay de EVPN
Por defecto las sesiones VTEP del overlay corren como iBGP con el ASN del EVPN controller, mientras que el ASN de fabric de cada nodo se aplica con local-as en el grupo de vecinos del underlay. Por tanto el ASN del controlador y los ASN de fabric por nodo tienen que ser distintos: por ejemplo 65001, 65002 y 65003 en el underlay y 65000 en el controlador. Con BGP Mode = external las sesiones VTEP pasan a eBGP con el ASN de fabric del nodo, y el del controlador se sigue usando para derivar los route-targets. Requisito adicional: “Using a BGP fabric for an EVPN underlay requires each node to have an IPv4 address, since EVPN uses it as the VTEP address.”
Fabric WireGuard
Requiere apt install wireguard-tools y distingue nodos Internal (nodos PVE) y External (peers reutilizables de fuera). Los campos que importan: el Endpoint interno es la IP o hostname que otros nodos usan para conectar y se combina con el Listen Port, cuyo default es 51820; el Endpoint externo lleva puerto explícito, con IPv6 entre corchetes como [2001:db8::1]:51820; Allowed IPs es a la vez filtro de origen entrante y destino de routing saliente; el Name de la interfaz admite de 1 a 8 caracteres empezando por alfanumérico; Persistent Keepalive ayuda con NAT y firewalls stateful; y Skip Route Generation evita insertar rutas en la tabla del kernel para ese peer.
La clave privada se autogenera en /etc/pve/priv/wg-keys.cfg al guardar la interfaz, y la configuración resultante se escribe en /etc/wireguard/proxmox/<iface>.conf:
[Interface]
PrivateKey = EpP9R0kqNA1UjGGeDL0/y9Ok66G44dqa2ALYJ0jTWwQ=
ListenPort = 51820
[Peer]
PublicKey = xIlHE6ZA25Qnpa+HYT1un3fbjO5/0A9YUbbRmTyLWW4=
AllowedIPs = 198.51.100.10/32, 203.0.113.0/24
Endpoint = 192.0.2.10:51820
Un bloque [Peer] por cada nodo del fabric, con la clave pública que PVE guardó junto a ese nodo en la configuración.
Prefix lists, route maps e IPSets automáticos del firewall
PVE 9.2 añadió prefix lists y route maps como entidades cluster-wide bajo /etc/pve/sdn/, gestionables desde Datacenter → SDN, que se traducen a stanzas de FRR. La semántica es la de FRR, Cisco y Juniper: evaluación por número de secuencia, parada en la primera coincidencia y deny implícito al final.
Una prefix list tiene Sequence Nr. único y mayor o igual que 1 (si lo dejas vacío PVE asigna max + 5), Action, Prefix y los modificadores ge y le. PVE valida que ge no exceda a le, que ninguno sea menor que la longitud del propio prefijo y que ambos estén dentro del límite de la familia, /32 en IPv4 y /128 en IPv6. Nombres reservados: only_default, only_default_v6 y loopbacks_ips.
Un route map tiene Order de 0 a 65535, Action, Match, Set, Exit Action y Call. Entre las claves de Match están route-type, vni, las cuatro variantes de prefix-list sobre dirección y next-hop, metric, local-preference, peer y tag; entre las de Set, los distintos ip-next-hop, local-preference, tag, weight, metric y src, donde metric acepta N, +N, -N, rtt, igp o aigp y tag acepta un entero o el literal untagged. Nombres reservados: MAP_VTEP_IN, MAP_VTEP_OUT, correct_src y cualquiera que empiece por pve_.
# /etc/pve/sdn/prefix-lists.cfg
prefix-list: internal-subnets
entries action=permit,prefix=10.0.0.0/8,ge=16,le=24,seq=10
entries action=deny,prefix=10.0.0.0/8,le=32,seq=20
# /etc/pve/sdn/route-maps.cfg
route-map-entry: bgp-out_10
action permit
match key=ip-address-prefix-list,value=internal-subnets
set key=local-preference,value=50
route-map-entry: bgp-out_20
action permit
Esa segunda entrada sin match es el patrón de FRR para “permite todo lo demás”. Sin ella, el deny implícito descartaría todas las rutas que no coincidieron.
Por cada VNet, el firewall genera automáticamente cuatro IPSets en el scope SDN: <vnet>-all con los CIDRs de todas sus subnets, <vnet>-gateway con las IPs de gateway, <vnet>-no-gateway con los CIDRs excluyendo los gateways mediante entradas negadas, y <vnet>-dhcp con todos los rangos DHCP. Con el IPAM pve se genera además guest-ipam-<VMID>, por ejemplo guest-ipam-100, con todas las IPs del guest en todas sus VNets.
Advertencia: “When removing all entries for a guest and there are firewall rules still referencing the auto-generated IPSet then the firewall will fail to update the ruleset, since it references a non-existing IPSet.” Borrar las entradas IPAM de un guest cuyas reglas siguen referenciando su IPSet deja el firewall entero sin poder recargarse.
Diagnóstico de red y orden seguro para tocar producción
# --- Red base ---
ip -br addr
ip -br link
cat /etc/network/interfaces.new # hay cambios pendientes?
ifreload -a -s # syntax check
journalctl -b -u networking -u pvenetcommit
# --- Bridge, VLAN y bonding ---
bridge link show
bridge vlan show # VLANs por puerto en bridges VLAN-aware
bridge fdb show br vmbr0 # tabla MAC
cat /proc/net/bonding/bond0
# --- SDN ---
cat /etc/pve/sdn/.running-config # y .version para la config aplicada
vtysh -c "show bgp l2vpn evpn summary"
vtysh -c "show bgp l2vpn evpn route"
vtysh -c "show ip route"
ip -d link show type vxlan
systemctl status dnsmasq@<zone>
cat /var/lib/misc/dnsmasq.<zone>.leases
El procedimiento que evita quedarte fuera del nodo, en este orden exacto. Uno. Abre una sesión SSH persistente y ten IPMI o iKVM disponible antes de empezar. Dos. Copia de seguridad: cp /etc/network/interfaces /root/interfaces.$(date +%F). Tres. Edita por GUI, que deja el staging en .new, o a mano. Cuatro. ifreload -a -s y luego ifreload -a -n. Cinco. Aplica; si el cambio es arriesgado y estás en remoto, programa antes un rollback automático:
echo 'cp /root/interfaces.backup /etc/network/interfaces && ifreload -a' | at now + 5 minutes
Seis. Verifica con ip -br addr y un ping al gateway, y abre una segunda sesión SSH nueva antes de cerrar la primera. Si la segunda entra, el cambio es bueno.
Errores comunes y diagnóstico
| Síntoma | Causa probable | Diagnóstico y solución |
|---|---|---|
| Los cambios hechos en la GUI no surten efecto | siguen en staging | ls -l /etc/network/interfaces.new; pulsar Apply Configuration o ejecutar ifreload -a |
Tras ifdown vmbr0 && ifup vmbr0 las VMs pierden la red | los tap y veth no se reenganchan al bridge | usar ifreload -a; si ya ocurrió, reiniciar los guests |
| Tras un upgrade cambian los nombres de NIC y el nodo queda sin red | nuevo esquema systemd o kernel y driver nuevos | consola IPMI, ip -br link, pve-network-interface-pinning generate o un .link manual más update-initramfs -u -k all |
| Las VNets del SDN no aparecen en el nodo | falta source /etc/network/interfaces.d/* al final del fichero | añadir la línea y ifreload -a |
| Un OVSIntPort está configurado pero nunca sube | no aparece en ovs_ports del bridge | añadirlo a ovs_ports; comprobar con ovs-vsctl show |
Interfaces con mtu 9000 que no levantan en NIC Intel Gigabit | límite de hardware de 8996 | bajar a 8996 todas las MTU implicadas |
| VXLAN funciona pero se pierden los paquetes grandes | MTU sin restar los 50 bytes | 1450 en la zona y en el guest; verificar con ping -M do -s 1422 |
| QinQ con problemas de MTU | faltan 4 bytes | 1496 |
| Las conexiones salientes de VMs NATeadas se bloquean con el firewall activo | falta la zona de conntrack | añadir iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1 y su post-down |
| El NAT deja de funcionar tras actualizar de PVE 8 a 9 | ip_forward estaba en /etc/sysctl.conf, que ya no se honra | moverlo a /etc/sysctl.d/99-forward.conf y systemctl restart systemd-sysctl |
| EVPN con varios exit nodes: tráfico asimétrico descartado | rp_filter estricto | /etc/sysctl.d/99-rp-filter.conf con rp_filter=0 en all y default |
| Los guests EVPN salen pero nadie les responde | faltan rutas inversas en el gateway externo | añadir rutas hacia las subnets apuntando a los exit nodes, o usar un router BGP |
| El SDN rechaza la configuración con error de ASN | dos sesiones iBGP con ASN distintos en el mismo nodo | unificar el ASN de los controladores EVPN; separar el ASN del fabric del ASN del controlador |
| El DHCP del SDN no reparte direcciones | la subnet no tiene gateway configurado | definir el gateway; revisar systemctl status dnsmasq@<zone> y el fichero de leases |
| Tras el upgrade 8 a 9 la red no arranca y FRR bloquea | post-up systemctl restart frr.service provoca deadlock | sustituir por post-up /usr/bin/systemctl is-active --quiet frr.service && /usr/bin/systemctl restart frr.service || true |
La configuración de /etc/frr/frr.conf.local deja de aplicarse | el SDN desactiva daemons en /etc/frr/daemons | crear /etc/default/frr con ospfd=yes o fabricd=yes |
| El firewall falla al actualizar el ruleset tras borrar entradas de IPAM | hay reglas que referencian un guest-ipam-<VMID> inexistente | quitar la referencia o restaurar la entrada del IPAM |
| El hoster corta la red en cuanto arrancan las VMs | varias MAC en una sola interfaz | pasar a modo routed, o registrar MACs virtuales en el panel del proveedor |
Los cambios de pve-network-interface-pinning no llegan al firewall del clúster | cluster.fw no se actualiza automáticamente | editar /etc/pve/firewall/cluster.fw a mano |
Lo que queda funcionando
Tienes la red del nodo bajo control: sabes que la GUI escribe en /etc/network/interfaces.new y que solo Apply o pvenetcommit lo activan, que ifreload -a recarga sin desconectar a los guests mientras ifup/ifdown los deja aislados, cómo montar un bridge VLAN-aware con la gestión en su propia VLAN sobre un bond LACP, qué restar al MTU en cada encapsulación, y cómo sobrevivir en un hoster con binding IP/MAC usando routed o masquerading con sus conntrack zones.
Del lado SDN tienes el modelo completo: zonas Simple, VLAN, QinQ, VXLAN y EVPN, VNets con subnets e IPAM, DHCP con dnsmasq, controladores con sus reglas de ASN y los fabrics de PVE 9 con OpenFabric, OSPF, BGP unnumbered y WireGuard.
Lo que ha ido apareciendo sin desarrollarse es el firewall: las reglas FORWARD, los flags que hay que activar para que una regla de VM tenga efecto, los IPSets management y local_network, y los bridges fwbr que se cuelan en el camino del NAT. Eso, junto con usuarios, permisos, realms de autenticación y 2FA, es el contenido del capítulo 10.