WireGuard es un protocolo VPN moderno integrado en el núcleo de Linux: usa criptografía actual, tiene muy poco código y suele ser más rápido y sencillo de configurar que OpenVPN o IPsec. En este tutorial montarás un servidor WireGuard en Ubuntu 24.04 configurado a mano, sin scripts de terceros, para que sepas exactamente qué hace cada línea. Al terminar, tus dispositivos saldrán a Internet a través del servidor y podrás añadir clientes nuevos cuando quieras.

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. En Debian 12 los pasos son los mismos.
  • Un usuario no root con privilegios sudo.
  • UFW activo con SSH permitido. Si aún no lo tienes, sigue una guía de configuración de UFW antes de empezar.
  • Un dispositivo cliente con la aplicación oficial de WireGuard (Windows, macOS, Android, iOS) o el paquete wireguard en Linux.

En la guía se usa la red interna 10.8.0.0/24 para la VPN: el servidor tendrá la 10.8.0.1 y el primer cliente la 10.8.0.2.

Paso 1: Instalar WireGuard

WireGuard está en los repositorios oficiales de Ubuntu. Instala también qrencode, que usarás para pasar la configuración al móvil:

sudo apt update
sudo apt install wireguard qrencode

Comprueba que las herramientas están disponibles:

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

Paso 2: Generar las claves del servidor

Cada extremo de un túnel WireGuard tiene un par de claves: una privada, que nunca sale del equipo, y una pública, que compartes con el otro extremo. Genera las del servidor dentro de /etc/wireguard con permisos restrictivos (umask 077 hace que solo root pueda leer los archivos):

sudo -i
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub
exit

Muestra la clave privada, que necesitarás en el siguiente paso:

sudo cat /etc/wireguard/server.key

Paso 3: Configurar la interfaz wg0

Averigua el nombre de la interfaz pública del servidor, la que tiene la ruta por defecto:

ip route show default
default via 203.0.113.1 dev eth0 proto static

En este ejemplo es eth0. Crea el archivo de configuración del túnel:

sudo nano /etc/wireguard/wg0.conf

Pega el siguiente contenido, sustituyendo clave_privada_del_servidor por el contenido de server.key:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = clave_privada_del_servidor
  • Address es la IP del servidor dentro de la VPN.
  • ListenPort es el puerto UDP en el que escucha WireGuard. 51820 es el habitual.

Los clientes (secciones [Peer]) se añaden más adelante.

Paso 4: Activar el reenvío de paquetes

Para que el servidor encamine el tráfico de los clientes hacia Internet, el núcleo debe reenviar paquetes entre interfaces. Crea un archivo de sysctl:

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

Aplica el cambio y compruébalo:

sudo sysctl --system
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Paso 5: Configurar UFW y el NAT

Hay que hacer tres cosas en el cortafuegos: abrir el puerto de WireGuard, permitir el tráfico reenviado desde el túnel y enmascarar (NAT) las IPs de la VPN tras la IP pública del servidor.

Abre el puerto UDP:

sudo ufw allow 51820/udp

Permite que el tráfico que entra por wg0 salga por la interfaz pública (UFW bloquea el tráfico reenviado por defecto). Sustituye eth0 si tu interfaz tiene otro nombre:

sudo ufw route allow in on wg0 out on eth0

Para el NAT, edita las reglas previas de UFW:

sudo nano /etc/ufw/before.rules

Añade este bloque al principio del archivo, antes de la línea *filter:

# NAT para la VPN WireGuard
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

Recarga UFW y comprueba las reglas:

sudo ufw reload
sudo ufw status verbose
To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW IN    Anywhere
51820/udp                  ALLOW IN    Anywhere

Anywhere on eth0           ALLOW FWD   Anywhere on wg0

Paso 6: Arrancar el servidor WireGuard

WireGuard incluye la unidad de systemd wg-quick@, que levanta la interfaz a partir del archivo wg0.conf. Actívala para que arranque también tras cada reinicio:

sudo systemctl enable --now wg-quick@wg0

Comprueba el estado del servicio y de la interfaz:

sudo systemctl status wg-quick@wg0
sudo wg show
interface: wg0
  public key: Qd3xT0...=
  private key: (hidden)
  listening port: 51820

Paso 7: Crear el primer cliente

Genera las claves del cliente en el servidor. Es más cómodo para un móvil; si prefieres que la clave privada no pase nunca por el servidor, genera el par en el propio cliente y copia solo la clave pública.

sudo -i
mkdir -p /etc/wireguard/clients
cd /etc/wireguard/clients
umask 077
wg genkey | tee movil.key | wg pubkey > movil.pub
exit

Añade el cliente al servidor como [Peer]. AllowedIPs indica qué IP de la VPN corresponde a este cliente:

sudo nano /etc/wireguard/wg0.conf

Añade al final del archivo, sustituyendo clave_publica_del_cliente por el contenido de movil.pub:

[Peer]
# movil
PublicKey = clave_publica_del_cliente
AllowedIPs = 10.8.0.2/32

Aplica el cambio sin cortar las conexiones activas. wg-quick strip convierte el archivo al formato que entiende wg syncconf:

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

Crea ahora el archivo de configuración del cliente:

sudo nano /etc/wireguard/clients/movil.conf

Sustituye clave_privada_del_cliente (contenido de movil.key), clave_publica_del_servidor (contenido de /etc/wireguard/server.pub) e ip_del_servidor:

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

[Peer]
PublicKey = clave_publica_del_servidor
Endpoint = ip_del_servidor: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 acceder a la red de la VPN, usa 10.8.0.0/24.
  • PersistentKeepalive = 25 mantiene el túnel abierto cuando el cliente está detrás de un NAT, como el de un router doméstico o una red móvil.

Paso 8: Conectar el cliente

En un móvil, abre la aplicación de WireGuard, pulsa en añadir túnel, elige escanear código QR y escanea el que muestra este comando:

sudo qrencode -t ansiutf8 < /etc/wireguard/clients/movil.conf

En Windows o macOS, copia el archivo movil.conf al equipo por un canal seguro (por ejemplo con scp) e impórtalo desde la aplicación con la opción de importar túnel desde archivo.

En Linux, instala wireguard, guarda el archivo como /etc/wireguard/wg0.conf y levanta el túnel con sudo wg-quick up wg0. Si al levantarlo aparece resolvconf: command not found, crea el enlace de compatibilidad con systemd-resolved, que acepta la sintaxis de resolvconf:

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

Activa el túnel en el cliente y comprueba en el servidor que hay un saludo (handshake) reciente:

sudo wg show
peer: 7bH2kL...=
  endpoint: 198.51.100.23:53012
  allowed ips: 10.8.0.2/32
  latest handshake: 5 seconds ago
  transfer: 45.21 KiB received, 102.84 KiB sent

Desde el cliente, comprueba que tu IP pública es ahora la del servidor, por ejemplo abriendo https://ifconfig.me en el navegador o, en Linux:

curl -4 https://ifconfig.me
203.0.113.10

Añadir más clientes

Para cada dispositivo nuevo, repite el paso 7 con otro nombre de archivo y la siguiente IP libre (10.8.0.3/32, 10.8.0.4/32...), tanto en el [Peer] del servidor como en Address del cliente. Cada dispositivo debe tener su propio par de claves: no reutilices una configuración en varios equipos a la vez.

Para revocar un cliente, borra su bloque [Peer] de wg0.conf y vuelve a ejecutar sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'.

Solución de problemas

  • latest handshake no aparece. El cliente no llega al servidor. Confirma que 51820/udp está abierto en UFW y que Endpoint apunta a la IP y puerto correctos. Revisa también que la clave pública de cada lado corresponde a la privada del otro.
  • Hay handshake pero no hay Internet. Suele ser el reenvío o el NAT. Comprueba sysctl net.ipv4.ip_forward, que el nombre de interfaz en before.rules y en la regla ufw route es el correcto, y que ejecutaste sudo ufw reload.
  • Navegas pero no resuelve nombres. Revisa la línea DNS del cliente. En Linux, confirma que el comando resolvconf existe (ver paso 8).
  • El servicio no arranca. Consulta sudo journalctl -u wg-quick@wg0 para ver el error exacto, normalmente una clave mal copiada o una línea mal escrita en wg0.conf.

Conclusión

Tienes un servidor VPN WireGuard propio, configurado a mano, que arranca con el sistema y enruta el tráfico de tus dispositivos a través de la IP del servidor. Como siguientes pasos, puedes añadir IPv6 a la VPN, usar AllowedIPs para dar acceso solo a redes privadas concretas en lugar de todo el tráfico, o restringir los servicios internos del servidor para que solo escuchen en 10.8.0.1.