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_ip y your_host_b_ip.
  • Nociones básicas de VLAN y de la orden ip.

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.

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=1000 es 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

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.