WireGuard es una VPN integrada en el kernel de Linux que crea túneles cifrados con muy poca configuración. En una red mesh completa cada servidor es peer directo de todos los demás, así que el tráfico entre dos nodos nunca pasa por un tercero y no hay un punto central de fallo. En este tutorial conectarás tres servidores Ubuntu 24.04 en una red privada 10.8.0.0/24, abrirás el firewall solo a los otros nodos, les darás nombres internos y aprenderás a añadir un cuarto nodo sin cortar el tráfico.
Requisitos previos
- Tres servidores con Ubuntu 24.04 LTS, por ejemplo VPS de CubePath, con una IP pública (o privada) alcanzable entre ellos.
- Un usuario no root con privilegios
sudoen cada servidor. - El puerto UDP
51820libre en todos los nodos. - Una subred para la mesh que no se solape con ninguna red que ya uses. Este tutorial usa
10.8.0.0/24.
A lo largo de la guía se usa este plan de direcciones. Sustituye las IP públicas de ejemplo por las de tus servidores:
| Nodo | IP pública | IP en la mesh |
|---|---|---|
| nodo1 | 203.0.113.10 | 10.8.0.1 |
| nodo2 | 203.0.113.20 | 10.8.0.2 |
| nodo3 | 203.0.113.30 | 10.8.0.3 |
Paso 1: Instalar WireGuard en todos los nodos
El módulo de WireGuard ya viene en el kernel de Ubuntu 24.04; solo necesitas las herramientas de espacio de usuario (wg y wg-quick). Ejecuta en los tres servidores:
sudo apt update
sudo apt install wireguard
Comprueba que el comando wg está disponible:
wg --version
wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/
Paso 2: Generar las claves de cada nodo
Cada nodo necesita su propio par de claves. La clave privada nunca sale del servidor; la pública se copia en la configuración de los demás nodos. Ejecuta en cada servidor:
wg genkey | sudo tee /etc/wireguard/private.key > /dev/null
sudo chmod 600 /etc/wireguard/private.key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
El último comando imprime la clave pública, una cadena de 44 caracteres terminada en =:
q6Xk0mZr5wH0V0vM2Jb8u3yF3nT1cQ7aP4sL9dE2hGk=
Anota la clave pública de cada nodo junto a su nombre. Para ver la clave privada cuando la necesites en el siguiente paso:
sudo cat /etc/wireguard/private.key
Paso 3: Crear la configuración de cada nodo
La configuración vive en /etc/wireguard/wg0.conf. La sección [Interface] describe el nodo local y hay una sección [Peer] por cada uno de los otros nodos. El campo AllowedIPs es clave: indica qué direcciones se envían por ese peer y qué direcciones de origen se aceptan de él. En una mesh cada peer solo tiene su propia IP /32.
En nodo1 crea el archivo:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = CLAVE_PRIVADA_NODO1
[Peer]
# nodo2
PublicKey = CLAVE_PUBLICA_NODO2
Endpoint = 203.0.113.20:51820
AllowedIPs = 10.8.0.2/32
[Peer]
# nodo3
PublicKey = CLAVE_PUBLICA_NODO3
Endpoint = 203.0.113.30:51820
AllowedIPs = 10.8.0.3/32
En nodo2:
[Interface]
Address = 10.8.0.2/24
ListenPort = 51820
PrivateKey = CLAVE_PRIVADA_NODO2
[Peer]
# nodo1
PublicKey = CLAVE_PUBLICA_NODO1
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.8.0.1/32
[Peer]
# nodo3
PublicKey = CLAVE_PUBLICA_NODO3
Endpoint = 203.0.113.30:51820
AllowedIPs = 10.8.0.3/32
En nodo3:
[Interface]
Address = 10.8.0.3/24
ListenPort = 51820
PrivateKey = CLAVE_PRIVADA_NODO3
[Peer]
# nodo1
PublicKey = CLAVE_PUBLICA_NODO1
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.8.0.1/32
[Peer]
# nodo2
PublicKey = CLAVE_PUBLICA_NODO2
Endpoint = 203.0.113.20:51820
AllowedIPs = 10.8.0.2/32
Sustituye CLAVE_PRIVADA_... y CLAVE_PUBLICA_... por las claves reales del paso 2. Como el archivo contiene la clave privada, restringe sus permisos en los tres nodos:
sudo chmod 600 /etc/wireguard/wg0.conf
Notano hace falta activar
net.ipv4.ip_forward. En una mesh completa cada nodo habla directamente con los demás y ninguno reenvía tráfico ajeno. Solo lo necesitarías si un nodo enruta hacia una LAN que hay detrás de él.
Si algún nodo está detrás de NAT (por ejemplo, un equipo en una oficina), añade PersistentKeepalive = 25 en la sección [Peer] que apunta a él desde los demás nodos, y también en los [Peer] de ese mismo nodo, para que el NAT mantenga abierta la asociación UDP.
Paso 4: Abrir el firewall a los otros nodos
Si usas UFW, permite el puerto UDP 51820 solo desde las IP públicas de los otros nodos. En nodo1:
sudo ufw allow from 203.0.113.20 to any port 51820 proto udp
sudo ufw allow from 203.0.113.30 to any port 51820 proto udp
Repite en nodo2 y nodo3 con las IP de sus respectivos peers. UFW también filtra el tráfico que entra por la interfaz wg0, así que permite el tráfico procedente de la mesh:
sudo ufw allow in on wg0 from 10.8.0.0/24
Si prefieres abrir solo servicios concretos dentro de la mesh, sustituye esta regla por otras más específicas, por ejemplo sudo ufw allow in on wg0 to any port 5432 proto tcp.
Comprueba las reglas:
sudo ufw status
Paso 5: Levantar la interfaz y activarla al arrancar
El servicio wg-quick@wg0 lee /etc/wireguard/wg0.conf, crea la interfaz, asigna la dirección y añade las rutas. Actívalo en los tres nodos:
sudo systemctl enable --now wg-quick@wg0
Comprueba que está activo:
sudo systemctl status wg-quick@wg0
● [email protected] - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; preset: enabled)
Active: active (exited) since ...
Paso 6: Verificar la mesh
Desde nodo1, haz ping a los otros dos nodos por su IP de la mesh:
ping -c 3 10.8.0.2
ping -c 3 10.8.0.3
64 bytes from 10.8.0.2: icmp_seq=1 ttl=64 time=0.912 ms
64 bytes from 10.8.0.2: icmp_seq=2 ttl=64 time=0.845 ms
WireGuard solo establece la sesión (el handshake) cuando hay tráfico, así que después del ping consulta el estado:
sudo wg show
interface: wg0
public key: q6Xk0mZr5wH0V0vM2Jb8u3yF3nT1cQ7aP4sL9dE2hGk=
private key: (hidden)
listening port: 51820
peer: 3pWq...Zx0=
endpoint: 203.0.113.20:51820
allowed ips: 10.8.0.2/32
latest handshake: 8 seconds ago
transfer: 1.02 KiB received, 1.13 KiB sent
peer: Hn7r...Lk4=
endpoint: 203.0.113.30:51820
allowed ips: 10.8.0.3/32
latest handshake: 5 seconds ago
transfer: 948 B received, 1.05 KiB sent
Cada peer debe mostrar un latest handshake reciente. Repite la prueba desde nodo2 hacia nodo3 para confirmar que todos los pares funcionan, no solo los que pasan por nodo1.
Paso 7: Dar nombres a los nodos
Para no depender de las IP, añade los nombres de la mesh a /etc/hosts en cada nodo:
sudo nano /etc/hosts
# Red mesh WireGuard
10.8.0.1 nodo1.mesh nodo1
10.8.0.2 nodo2.mesh nodo2
10.8.0.3 nodo3.mesh nodo3
Comprueba la resolución:
getent hosts nodo3.mesh
ping -c 2 nodo3.mesh
10.8.0.3 nodo3.mesh nodo3
Con pocos nodos, /etc/hosts es suficiente y no añade dependencias. Si la mesh crece, gestiona este archivo con tu herramienta de automatización (Ansible, cloud-init) o monta un DNS interno escuchando en la mesh.
Paso 8: Añadir un nuevo nodo sin cortar el tráfico
Para añadir nodo4 (203.0.113.40, 10.8.0.4), instala WireGuard y genera sus claves como en los pasos 1 y 2. Su wg0.conf incluye un [Peer] por cada uno de los tres nodos existentes, igual que en el paso 3.
Después, en cada nodo existente, añade al final de /etc/wireguard/wg0.conf la entrada del nuevo nodo:
[Peer]
# nodo4
PublicKey = CLAVE_PUBLICA_NODO4
Endpoint = 203.0.113.40:51820
AllowedIPs = 10.8.0.4/32
Aplica los cambios sin reiniciar la interfaz. wg-quick strip convierte el archivo al formato que entiende wg, y wg syncconf añade el peer sin tocar las sesiones activas:
sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'
Recuerda abrir el puerto UDP a la IP del nuevo nodo en cada servidor y añadir su nombre a /etc/hosts. Arranca la interfaz en nodo4 con sudo systemctl enable --now wg-quick@wg0 y verifica con sudo wg show que aparece como peer en todos los nodos.
Nota
wg syncconfsolo actualiza peers y claves. Si cambiasAddressu otros campos de[Interface], reinicia el servicio consudo systemctl restart wg-quick@wg0.
Solución de problemas
No aparece latest handshake para un peer. El tráfico UDP no llega o las claves no coinciden. Comprueba que el servicio escucha:
sudo ss -ulnp | grep 51820
Captura en la interfaz pública (cámbiala por la tuya, que puedes ver con ip -br addr) mientras haces ping desde el otro nodo:
sudo tcpdump -ni eth0 udp port 51820
Si ves paquetes salir pero no entrar, revisa el firewall del otro nodo. Si ves paquetes en ambos sentidos pero no hay handshake, la clave pública configurada en un lado no corresponde a la clave privada del otro: compara sudo cat /etc/wireguard/public.key en el nodo remoto con su PublicKey en tu wg0.conf.
El ping funciona pero las transferencias grandes se cuelgan. Es un problema de MTU, habitual si la red subyacente ya tiene túneles. wg-quick usa 1420 por defecto; bájalo añadiendo MTU = 1380 en [Interface] en todos los nodos y reinicia wg-quick@wg0.
Hay handshake pero un servicio no responde. El tráfico llega pero UFW lo bloquea en wg0. Revisa sudo ufw status verbose y consulta los rechazos con sudo journalctl -k | grep UFW.
Conclusión
Tienes tres servidores Ubuntu 24.04 conectados en una mesh WireGuard donde cada par se comunica directamente y cifrado, con el firewall limitado a los nodos conocidos y un procedimiento para crecer sin cortes. La parte que más cuidado exige es mantener las claves y los AllowedIPs coherentes en todos los nodos. Como siguientes pasos puedes mover los servicios internos (bases de datos, Redis, réplicas) para que escuchen solo en la IP de la mesh, generar los wg0.conf desde Ansible a partir de un único inventario o anunciar redes adicionales añadiéndolas al AllowedIPs del nodo que las enruta.
