WireGuard es una VPN moderna integrada en el kernel de Linux desde la versión 5.6. Usa criptografía actual, tiene una configuración de pocas líneas y ofrece más rendimiento que OpenVPN o IPsec. En este tutorial convertirás un servidor Ubuntu 24.04 en un servidor VPN WireGuard que enruta todo el tráfico de sus clientes hacia Internet, y conectarás un cliente Linux y un móvil.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS y una IP pública, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo y UFW activo con SSH permitido.
  • Un cliente: otro equipo con Linux (los comandos son para Ubuntu o Debian) o un móvil con la app oficial de WireGuard para Android o iOS.

En esta guía se usan estos valores, que debes adaptar a tu caso:

ValorEjemplo
Subred de la VPN10.8.0.0/24
IP del servidor en la VPN10.8.0.1
IP del primer cliente10.8.0.2
Puerto UDP51820
IP pública del servidoryour_server_ip

Paso 1: Instalar WireGuard en el servidor

El paquete wireguard instala las herramientas wg y wg-quick. El módulo del kernel ya viene incluido en Ubuntu 24.04:

sudo apt update
sudo apt install wireguard

Comprueba que la herramienta responde:

wg --version
wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

Paso 2: Generar las claves del servidor

Cada extremo de WireGuard tiene un par de claves: la privada nunca sale de la máquina y la pública se comparte con los peers. Genera ambas en /etc/wireguard con permisos restrictivos gracias a umask 077:

umask 077
wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub

El comando muestra la clave pública. Comprueba que la clave privada solo la puede leer root:

sudo ls -l /etc/wireguard/
-rw------- 1 root root 45 Sep 25 10:12 server.key
-rw------- 1 root root 45 Sep 25 10:12 server.pub

Necesitarás la clave privada en el siguiente paso. Muéstrala con:

sudo cat /etc/wireguard/server.key

Paso 3: Activar el reenvío de IP

Para que el servidor reenvíe el tráfico de los clientes hacia Internet, el kernel debe tener activado el reenvío de paquetes IPv4. Crea un archivo propio en /etc/sysctl.d:

sudo nano /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1

Aplica la configuración sin reiniciar:

sudo sysctl --system

Verifica el valor:

sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Paso 4: Crear la configuración del servidor

Averigua el nombre de la interfaz pública, que usarás en la regla de NAT:

ip -o -4 route show to default | awk '{print $5}'
eth0

Crea el archivo de la interfaz wg0:

sudo nano /etc/wireguard/wg0.conf

Pega el siguiente contenido. Sustituye server_private_key por la clave del paso 2 y eth0 por el nombre de tu interfaz:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = server_private_key

# NAT: el tráfico de los clientes sale a Internet con la IP pública del servidor
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

PostUp y PostDown se ejecutan al levantar y bajar la interfaz, así la regla de NAT solo existe mientras la VPN está activa. Los clientes se añadirán como bloques [Peer] en el paso 7.

Paso 5: Configurar el firewall

Abre el puerto UDP de WireGuard:

sudo ufw allow 51820/udp

UFW bloquea por defecto el tráfico reenviado, así que también debes permitir que lo que entra por wg0 salga por la interfaz pública:

sudo ufw route allow in on wg0 out on eth0

Revisa las reglas:

sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
51820/udp                  ALLOW       Anywhere
Anywhere on eth0           ALLOW FWD   Anywhere on wg0
...

Paso 6: Arrancar el servidor WireGuard

wg-quick incluye una plantilla de systemd, [email protected]. Actívala para wg0 y arráncala:

sudo systemctl enable --now wg-quick@wg0

Comprueba el estado de la interfaz:

sudo wg show
interface: wg0
  public key: 3Fq0...Yk8=
  private key: (hidden)
  listening port: 51820

Si el servicio no arranca, revisa el motivo con sudo journalctl -u wg-quick@wg0.

Paso 7: Configurar el primer cliente Linux

En el equipo cliente, instala WireGuard y genera su par de claves:

sudo apt update
sudo apt install wireguard
umask 077
wg genkey | sudo tee /etc/wireguard/client.key | wg pubkey | sudo tee /etc/wireguard/client.pub

Crea la configuración del cliente:

sudo nano /etc/wireguard/wg0.conf

Sustituye client_private_key por el contenido de /etc/wireguard/client.key del cliente, server_public_key por el de /etc/wireguard/server.pub del servidor y your_server_ip por la IP pública del servidor:

[Interface]
Address = 10.8.0.2/32
PrivateKey = client_private_key
DNS = 1.1.1.1, 9.9.9.9

[Peer]
PublicKey = server_public_key
Endpoint = your_server_ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0 envía todo el tráfico IPv4 del cliente por la VPN. Si solo quieres llegar a la red de la VPN (túnel dividido), usa AllowedIPs = 10.8.0.0/24. PersistentKeepalive mantiene el túnel abierto cuando el cliente está detrás de NAT.

Ahora vuelve al servidor y añade el cliente al final de /etc/wireguard/wg0.conf, con la clave pública del cliente (/etc/wireguard/client.pub):

sudo nano /etc/wireguard/wg0.conf
[Peer]
# portatil-ana
PublicKey = client_public_key
AllowedIPs = 10.8.0.2/32

En el servidor, AllowedIPs indica qué IP de la VPN pertenece a ese cliente. Usa siempre una /32 distinta por cliente.

Aplica el cambio sin cortar las conexiones activas. wg-quick strip genera la configuración sin las directivas propias de wg-quick y wg syncconf la carga en caliente:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

Paso 8: Conectar el cliente y verificar el túnel

En el cliente, levanta la interfaz:

sudo wg-quick up wg0

Comprueba que hay intercambio de claves con el servidor:

sudo wg show
interface: wg0
  public key: pX9T...cQ=
  private key: (hidden)
  listening port: 48213
  fwmark: 0xca6c

peer: 3Fq0...Yk8=
  endpoint: your_server_ip:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 4 seconds ago
  transfer: 1.24 KiB received, 1.51 KiB sent
  persistent keepalive: every 25 seconds

La línea latest handshake confirma que el túnel funciona. Haz ping a la IP del servidor en la VPN:

ping -c 3 10.8.0.1

Por último, comprueba que tu IP de salida a Internet es la del servidor:

curl -4 https://ifconfig.me
your_server_ip

Para que el cliente se conecte automáticamente al arrancar, usa el servicio de systemd en lugar de wg-quick up:

sudo wg-quick down wg0
sudo systemctl enable --now wg-quick@wg0

Paso 9: Añadir un cliente móvil con código QR

Las apps de WireGuard para Android e iOS pueden importar la configuración escaneando un código QR. En este caso es práctico generar las claves del móvil en el servidor. Instala qrencode:

sudo apt install qrencode

Genera las claves del móvil en un directorio privado:

sudo mkdir -m 700 -p /etc/wireguard/clients
umask 077
wg genkey | sudo tee /etc/wireguard/clients/movil.key | wg pubkey | sudo tee /etc/wireguard/clients/movil.pub

Crea su configuración con la siguiente IP libre, 10.8.0.3:

sudo nano /etc/wireguard/clients/movil.conf
[Interface]
Address = 10.8.0.3/32
PrivateKey = movil_private_key
DNS = 1.1.1.1, 9.9.9.9

[Peer]
PublicKey = server_public_key
Endpoint = your_server_ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Añade el peer correspondiente al final de /etc/wireguard/wg0.conf del servidor:

[Peer]
# movil-ana
PublicKey = movil_public_key
AllowedIPs = 10.8.0.3/32

Recarga la configuración y muestra el código QR en la terminal:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'
sudo qrencode -t ansiutf8 < /etc/wireguard/clients/movil.conf

En la app, pulsa +, elige crear desde código QR y escanea la pantalla. Una vez importado el túnel, borra la clave privada del móvil del servidor, ya que no hace falta guardarla ahí:

sudo rm /etc/wireguard/clients/movil.key /etc/wireguard/clients/movil.conf

Paso 10 (opcional): Añadir una clave precompartida

Una clave precompartida (PresharedKey) añade una capa de cifrado simétrico al intercambio de claves y protege el tráfico grabado frente a futuros ataques con ordenadores cuánticos. Genera una por cada cliente:

wg genpsk

Añade la misma línea PresharedKey = ... dentro del bloque [Peer] de ese cliente en el servidor y en el bloque [Peer] de la configuración del cliente. Después recarga el servidor con wg syncconf como antes y reinicia el túnel en el cliente.

Solución de problemas

No aparece latest handshake en el cliente. El paquete UDP no llega al servidor o las claves no coinciden. Comprueba que 51820/udp está permitido en UFW, que la clave pública del cliente en el servidor es la correcta (y viceversa) y revisa sudo journalctl -u wg-quick@wg0 en el servidor.

Hay handshake pero no hay Internet a través de la VPN. Suele faltar el reenvío o el NAT. Verifica sysctl net.ipv4.ip_forward, la regla ufw route allow y que el nombre de interfaz de PostUp es el correcto:

sudo iptables -t nat -S POSTROUTING
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

wg-quick up falla con resolvconf: command not found. La directiva DNS necesita el comando resolvconf. En un cliente Ubuntu con systemd-resolved, resolvectl funciona como sustituto:

sudo ln -s /usr/bin/resolvectl /usr/local/sbin/resolvconf

Algunas webs cargan y otras se quedan colgadas. Es un problema de MTU, típico cuando el cliente está detrás de PPPoE u otra VPN. Añade MTU = 1380 en la sección [Interface] del cliente y vuelve a levantar el túnel.

Conclusión

Tu servidor Ubuntu 24.04 funciona ahora como servidor VPN WireGuard, con NAT hacia Internet, reglas de UFW para el tráfico reenviado y clientes Linux y móviles conectados. Para cada nuevo dispositivo basta con generar un par de claves, asignarle una IP /32 libre y añadir su bloque [Peer].

Como siguientes pasos puedes añadir IPv6 a la VPN con una subred ULA, usar el túnel para acceder a servicios internos (bases de datos, paneles de administración) sin exponerlos a Internet, o conectar dos servidores entre sí con una VPN de sitio a sitio usando el mismo formato de [Peer].