Open vSwitch (OVS) es un switch virtual multicapa para Linux que se programa con OpenFlow y que sirve de base a plataformas como OpenStack, OVN o muchos plugins de red de Kubernetes. En este tutorial instalarás OVS en Ubuntu 24.04 y montarás un laboratorio con namespaces de red: separarás tráfico en VLAN, bloquearás tráfico con reglas OpenFlow, copiarás paquetes a un puerto de análisis y unirás dos servidores con un túnel VXLAN.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS y un usuario no root con privilegios
sudo. Para el paso 6 (VXLAN) necesitas un segundo servidor igual. - Conectividad IP entre los dos servidores, preferiblemente por una red privada. En los ejemplos, sus IP son
your_host_a_ipyyour_host_b_ip. - Nociones básicas de VLAN y de la orden
ip.
Advertenciano añadas la interfaz de red principal del servidor (la de tu sesión SSH) a un bridge de OVS. La IP deja de funcionar en la interfaz física y perderás la conexión. Este laboratorio usa solo interfaces virtuales, así que no afecta a la red del servidor.
Paso 1: Instalar Open vSwitch
El paquete openvswitch-switch de Ubuntu incluye el daemon ovs-vswitchd, la base de datos de configuración ovsdb-server y las herramientas ovs-vsctl y ovs-ofctl:
sudo apt update
sudo apt install openvswitch-switch
Comprueba que el servicio está activo y la versión instalada:
systemctl is-active openvswitch-switch
sudo ovs-vsctl --version
active
ovs-vsctl (Open vSwitch) 3.3.x
DB Schema 8.5.0
Paso 2: Crear un bridge y conectar namespaces
Un bridge de OVS es un switch virtual. Créalo:
sudo ovs-vsctl add-br br0
sudo ip link set br0 up
Para simular tres máquinas conectadas al switch, crea tres namespaces de red. Cada uno tiene su propia pila de red y se conecta al bridge con un par veth, que funciona como un cable virtual:
for i in 1 2 3; do
sudo ip netns add ns$i
sudo ip link add veth$i type veth peer name veth$i-br
sudo ip link set veth$i netns ns$i
sudo ip -n ns$i addr add 10.0.0.$i/24 dev veth$i
sudo ip -n ns$i link set veth$i up
sudo ip -n ns$i link set lo up
sudo ip link set veth$i-br up
done
Conecta el extremo -br de cada par al bridge como puerto de acceso. tag asigna el puerto a una VLAN: ns1 y ns2 van a la VLAN 10 y ns3 a la VLAN 20:
sudo ovs-vsctl add-port br0 veth1-br tag=10
sudo ovs-vsctl add-port br0 veth2-br tag=10
sudo ovs-vsctl add-port br0 veth3-br tag=20
Revisa la configuración del switch:
sudo ovs-vsctl show
a1b2c3d4-...
Bridge br0
Port veth1-br
tag: 10
Interface veth1-br
Port veth2-br
tag: 10
Interface veth2-br
Port veth3-br
tag: 20
Interface veth3-br
Port br0
Interface br0
type: internal
ovs_version: "3.3.x"
Paso 3: Comprobar el aislamiento entre VLAN
Aunque los tres namespaces están en la misma subred IP, solo los de la misma VLAN deben verse. Desde ns1, haz ping a ns2 (VLAN 10):
sudo ip netns exec ns1 ping -c 2 10.0.0.2
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
Y ahora a ns3 (VLAN 20):
sudo ip netns exec ns1 ping -c 2 -W 1 10.0.0.3
2 packets transmitted, 0 received, 100% packet loss, time 1024ms
El switch no reenvía tráfico entre VLAN distintas. Para comunicarlas necesitarías un router, igual que en un switch físico.
Además de puertos de acceso, OVS admite puertos troncales que transportan varias VLAN etiquetadas, por ejemplo hacia un switch físico o un hipervisor. Se crean con trunks:
sudo ovs-vsctl add-port br0 your_uplink_port trunks=10,20
No ejecutes esta orden en el laboratorio salvo que tengas una interfaz dedicada para ello.
Paso 4: Controlar el tráfico con reglas OpenFlow
Internamente, OVS decide qué hacer con cada paquete según una tabla de flujos OpenFlow. Un bridge recién creado tiene una sola regla que le hace funcionar como un switch normal con aprendizaje de MAC:
sudo ovs-ofctl dump-flows br0
cookie=0x0, duration=312.4s, table=0, n_packets=18, n_bytes=1428, priority=0 actions=NORMAL
Añade una regla de mayor prioridad que descarte el ICMP que envía ns2:
sudo ovs-ofctl add-flow br0 "priority=100,icmp,nw_src=10.0.0.2,actions=drop"
Comprueba que el ping de ns2 a ns1 ya no funciona. El de ns1 a ns2 también falla: la petición llega, pero la respuesta sale de 10.0.0.2 y la regla la descarta.
sudo ip netns exec ns2 ping -c 2 -W 1 10.0.0.1
2 packets transmitted, 0 received, 100% packet loss, time 1030ms
El contador n_packets de la nueva regla muestra los paquetes descartados:
sudo ovs-ofctl dump-flows br0
cookie=0x0, duration=21.7s, table=0, n_packets=2, n_bytes=196, priority=100,icmp,nw_src=10.0.0.2 actions=drop
cookie=0x0, duration=356.1s, table=0, n_packets=22, n_bytes=1764, priority=0 actions=NORMAL
Para entender qué regla se aplicaría a un paquete sin enviarlo, usa ofproto/trace. Simula un ICMP que entra por el puerto de ns2:
sudo ovs-appctl ofproto/trace br0 "in_port=veth2-br,icmp,nw_src=10.0.0.2,nw_dst=10.0.0.1"
La salida recorre la tabla y termina en Datapath actions: drop.
Elimina la regla indicando exactamente su prioridad y su match con --strict, para no borrar otras reglas:
sudo ovs-ofctl --strict del-flows br0 "priority=100,icmp,nw_src=10.0.0.2"
sudo ip netns exec ns2 ping -c 2 10.0.0.1
El ping vuelve a funcionar.
Notalas reglas añadidas con
ovs-ofctlno son persistentes: se pierden al reiniciar OVS. En producción las gestiona un controlador (por ejemplo OVN) o un script que se ejecuta al arrancar.
Paso 5: Copiar el tráfico a un puerto de análisis
El port mirroring duplica el tráfico del switch hacia otro puerto, donde puedes capturarlo con tcpdump o un IDS sin tocar el flujo original. Crea un puerto interno mon0 que servirá de destino:
sudo ovs-vsctl add-port br0 mon0 -- set interface mon0 type=internal
sudo ip link set mon0 up
Crea el mirror y asócialo al bridge en una sola transacción. select-all=true copia el tráfico de todos los puertos:
sudo ovs-vsctl -- --id=@p get port mon0 \
-- --id=@m create mirror name=m0 select-all=true output-port=@p \
-- set bridge br0 mirrors=@m
Comprueba que existe:
sudo ovs-vsctl list mirror
La salida muestra el mirror m0 con select_all: true y el UUID del puerto de salida.
Captura en mon0 mientras haces ping de ns1 a ns2 desde otra terminal (sudo ip netns exec ns1 ping 10.0.0.2):
sudo tcpdump -ni mon0 icmp
listening on mon0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:42:01.120331 IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 4121, seq 1, length 64
10:42:01.120380 IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 4121, seq 1, length 64
Para copiar solo el tráfico de un puerto concreto, sustituye select-all=true por select-src-port y select-dst-port apuntando a ese puerto. Cuando termines, elimina el mirror:
sudo ovs-vsctl clear bridge br0 mirrors
Paso 6: Unir dos servidores con un túnel VXLAN
VXLAN encapsula tramas Ethernet en paquetes UDP (puerto 4789), de modo que máquinas en servidores distintos comparten un mismo segmento de capa 2 aunque entre ellos solo haya conectividad IP. Instala OVS en el segundo servidor siguiendo el paso 1.
En los dos servidores, permite el tráfico VXLAN desde el otro extremo si usas UFW. En el servidor A:
sudo ufw allow from your_host_b_ip to any port 4789 proto udp
En el servidor B, la misma regla con your_host_a_ip.
En el servidor A, crea un bridge para la red overlay, añade el puerto VXLAN apuntando al servidor B y un puerto interno con una IP de la red overlay:
sudo ovs-vsctl add-br br-ov
sudo ovs-vsctl add-port br-ov vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=your_host_b_ip options:key=1000
sudo ovs-vsctl add-port br-ov ov0 -- set interface ov0 type=internal
sudo ip addr add 192.168.100.1/24 dev ov0
sudo ip link set ov0 mtu 1450 up
En el servidor B, lo mismo con la IP del servidor A y la dirección .2:
sudo ovs-vsctl add-br br-ov
sudo ovs-vsctl add-port br-ov vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=your_host_a_ip options:key=1000
sudo ovs-vsctl add-port br-ov ov0 -- set interface ov0 type=internal
sudo ip addr add 192.168.100.2/24 dev ov0
sudo ip link set ov0 mtu 1450 up
options:key=1000es el VNI (identificador de red VXLAN). Debe coincidir en ambos extremos y permite tener varias redes aisladas sobre los mismos servidores.- La MTU de 1450 compensa los 50 bytes de cabecera que añade VXLAN sobre una red con MTU 1500. Sin este ajuste, los paquetes grandes se pierden.
Comprueba la conectividad a través del túnel desde el servidor A:
ping -c 3 192.168.100.2
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
Para confirmar que el tráfico viaja encapsulado, captura en la interfaz física del servidor A mientras repites el ping:
sudo tcpdump -ni any udp port 4789
IP your_host_a_ip.51234 > your_host_b_ip.4789: VXLAN, flags [I] (0x08), vni 1000
IP 192.168.100.1 > 192.168.100.2: ICMP echo request, id 3, seq 1, length 64
NotaVXLAN no cifra el tráfico. Si los servidores se comunican por Internet en lugar de por una red privada, protege el túnel con IPsec o WireGuard.
Persistencia y limpieza
La configuración de bridges, puertos, VLAN, mirrors y túneles creada con ovs-vsctl se guarda en la base de datos de OVS (/etc/openvswitch/conf.db) y sobrevive a los reinicios. En cambio, no persisten los namespaces, los pares veth, las IP asignadas con ip addr ni las reglas OpenFlow. Para una configuración permanente de las IP en Ubuntu, Netplan permite definir bridges de OVS con la clave openvswitch en /etc/netplan/.
Para eliminar el laboratorio del servidor A:
sudo ovs-vsctl del-br br0
sudo ovs-vsctl del-br br-ov
for i in 1 2 3; do sudo ip netns del ns$i; done
Al borrar un bridge se eliminan también todos sus puertos. En el servidor B basta con sudo ovs-vsctl del-br br-ov.
Solución de problemas
ovs-vsctl se queda colgado o falla al conectar con la base de datos. El servicio no está en marcha. Revisa su estado y sus logs:
sudo systemctl status openvswitch-switch ovs-vswitchd ovsdb-server --no-pager
sudo tail -n 50 /var/log/openvswitch/ovs-vswitchd.log
Un puerto aparece con error en ovs-vsctl show (por ejemplo error: "could not open network device veth1-br (No such device)"). La interfaz que añadiste no existe o se borró. Elimina el puerto con sudo ovs-vsctl del-port br0 veth1-br y vuelve a crearlo.
No hay tráfico a través del túnel VXLAN. Comprueba que remote_ip y key son correctos en ambos lados (sudo ovs-vsctl list interface vxlan0), que el puerto UDP 4789 está permitido y, con tcpdump, si los paquetes encapsulados salen de un servidor y llegan al otro.
Los pings pequeños funcionan por el túnel pero las transferencias se cuelgan. Es un problema de MTU. Comprueba la MTU de ov0 con ip link show ov0 y bájala si la red entre los servidores tiene una MTU menor de 1500.
Conclusión
Has instalado Open vSwitch en Ubuntu 24.04, aislado tráfico con VLAN, controlado paquetes con reglas OpenFlow, duplicado tráfico a un puerto de análisis y unido dos servidores con un túnel VXLAN. Como siguientes pasos, puedes conectar máquinas virtuales KVM al bridge con libvirt, definir la configuración de OVS en Netplan para que sea persistente o explorar OVN para gestionar redes virtuales entre muchos hosts sin configurar túneles a mano.
