OpenVPN es una VPN de código abierto que cifra el tráfico con TLS y autentica a cada cliente con su propio certificado. Es una buena opción para dar acceso remoto seguro a una red privada o para que tus dispositivos salgan a Internet a través de un servidor de confianza. En este tutorial instalarás OpenVPN en Ubuntu 24.04, crearás una autoridad de certificación con Easy-RSA, configurarás el servidor para enrutar todo el tráfico de los clientes, generarás un perfil .ovpn listo para importar y aprenderás a revocar el acceso de un cliente.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS y una IP pública, por ejemplo un VPS de CubePath. 1 vCPU y 1 GB de RAM son suficientes para un uso personal o de un equipo pequeño.
  • Un usuario no root con privilegios sudo.
  • UFW como firewall, con SSH permitido. Si no lo tienes activado, lo harás en el paso 5.
  • El puerto 1194/udp accesible desde Internet.
  • Un dispositivo cliente con Linux, Windows, macOS, Android o iOS.

En el tutorial se usa your_server_ip para la IP pública del servidor y client1 como nombre del primer cliente.

Paso 1: Instalar OpenVPN y Easy-RSA

Ambos paquetes están en los repositorios de Ubuntu. OpenVPN es el servicio VPN; Easy-RSA es un conjunto de scripts para crear y firmar certificados:

sudo apt update
sudo apt install openvpn easy-rsa

Comprueba la versión instalada:

openvpn --version | head -n 1
OpenVPN 2.6.x x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]

Paso 2: Crear la autoridad de certificación

OpenVPN autentica servidor y clientes con certificados firmados por una autoridad de certificación (CA) propia. Crea un directorio de trabajo para Easy-RSA en tu usuario, sin sudo, para que las claves no sean de root:

make-cadir ~/easy-rsa
cd ~/easy-rsa

Inicializa la infraestructura de clave pública (PKI):

./easyrsa init-pki

Crea la CA. Te pedirá una frase de paso para proteger la clave privada de la CA (la necesitarás cada vez que firmes un certificado) y un nombre común; puedes aceptar el propuesto o escribir algo como CubePath-VPN-CA:

./easyrsa build-ca
...
Notice
------
CA creation complete. Your new CA certificate is at:
* /home/your_user/easy-rsa/pki/ca.crt

Paso 3: Generar el certificado del servidor y la clave tls-crypt

Genera la petición y la clave privada del servidor. nopass deja la clave sin frase de paso, necesario para que el servicio arranque solo. Acepta el nombre común server que te propone:

./easyrsa gen-req server nopass

Firma la petición como certificado de tipo servidor. Escribe yes para confirmar e introduce la frase de paso de la CA:

./easyrsa sign-req server server
...
Notice
------
Certificate created at:
* /home/your_user/easy-rsa/pki/issued/server.crt

Copia el certificado de la CA, el del servidor y su clave al directorio de configuración de OpenVPN:

sudo cp pki/ca.crt pki/issued/server.crt /etc/openvpn/server/
sudo install -m 600 pki/private/server.key /etc/openvpn/server/

Genera también una clave compartida para tls-crypt. Esta clave cifra y autentica los paquetes de control de TLS, de modo que el servidor descarta sin responder cualquier intento de conexión que no la tenga. Así se reduce la exposición a escaneos y ataques de denegación de servicio:

sudo openvpn --genkey secret /etc/openvpn/server/ta.key

Comprueba que tienes los cuatro archivos:

sudo ls -l /etc/openvpn/server/
-rw-r--r-- 1 root root 1204 Sep 25 10:00 ca.crt
-rw-r--r-- 1 root root 4608 Sep 25 10:01 server.crt
-rw------- 1 root root 1704 Sep 25 10:01 server.key
-rw------- 1 root root  636 Sep 25 10:02 ta.key

No hace falta generar parámetros Diffie-Hellman: la configuración usará dh none, con intercambio de claves por curva elíptica (ECDHE), que es más rápido y es el método recomendado en OpenVPN 2.6.

Paso 4: Configurar el servidor OpenVPN

Crea el archivo de configuración del servidor. El nombre del archivo (server.conf) determina el nombre de la instancia del servicio, openvpn-server@server:

sudo nano /etc/openvpn/server/server.conf
port 1194
proto udp
dev tun

ca ca.crt
cert server.crt
key server.key
dh none
tls-crypt ta.key

topology subnet
server 10.8.0.0 255.255.255.0

push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 9.9.9.9"

keepalive 10 120
user nobody
group nogroup
persist-key
persist-tun

verb 3
explicit-exit-notify 1

Qué hace cada bloque:

  • port, proto, dev: escucha en 1194/udp y crea una interfaz de red virtual tun (enrutada, capa 3).
  • ca, cert, key, tls-crypt: los archivos del paso 3, con rutas relativas a /etc/openvpn/server/, que es el directorio de trabajo del servicio.
  • server 10.8.0.0 255.255.255.0: la subred interna de la VPN. El servidor será 10.8.0.1 y los clientes recibirán direcciones a partir de 10.8.0.2. Si esa red ya se usa en tu infraestructura o en las redes de tus clientes, elige otra privada.
  • push "redirect-gateway ...": hace que los clientes envíen todo su tráfico por la VPN. Si solo quieres dar acceso a una red privada, quita esa línea y añade en su lugar una ruta concreta, por ejemplo push "route 10.10.0.0 255.255.0.0".
  • push "dhcp-option DNS ...": los servidores DNS que usarán los clientes mientras estén conectados.
  • user nobody y group nogroup: tras arrancar, el proceso deja de ejecutarse como root.

OpenVPN 2.6 negocia por defecto cifrados AEAD modernos (AES-256-GCM, AES-128-GCM o ChaCha20-Poly1305), así que no necesitas ninguna directiva de cifrado.

Paso 5: Activar el reenvío de IP y el NAT con UFW

Para que los clientes salgan a Internet a través del servidor, el kernel debe reenviar paquetes entre la interfaz tun0 y la interfaz pública, y el tráfico de la subred VPN debe salir con la IP del servidor (NAT).

Activa el reenvío de IPv4 de forma persistente:

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-openvpn.conf
sudo sysctl --system

Comprueba que está activo:

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

Identifica 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

Aquí es eth0; usa el nombre que veas en tu servidor en los siguientes comandos. Añade la regla de NAT al principio del archivo de reglas de UFW:

sudo nano /etc/ufw/before.rules

Pega este bloque justo después de los comentarios iniciales y antes de la línea *filter:

# NAT para los clientes de OpenVPN
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

Permite el puerto de OpenVPN, el reenvío desde la VPN hacia Internet y SSH, y activa o recarga UFW:

sudo ufw allow 1194/udp
sudo ufw route allow in on tun0 out on eth0
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw reload

La regla ufw route permite solo el tráfico reenviado de la VPN hacia la interfaz pública, en lugar de cambiar la política de reenvío global a ACCEPT. Comprueba las reglas:

sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
1194/udp                   ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
Anywhere on eth0           ALLOW FWD   Anywhere on tun0
...

Paso 6: Iniciar el servicio

Arranca OpenVPN y actívalo para que se inicie con el sistema:

sudo systemctl enable --now openvpn-server@server

Comprueba su estado:

sudo systemctl status openvpn-server@server
● [email protected] - OpenVPN service for server
     Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; preset: enabled)
     Active: active (running) since ...
     Status: "Initialization Sequence Completed"

La interfaz de la VPN debe existir con la dirección del servidor:

ip -brief address show tun0
tun0             UNKNOWN        10.8.0.1/24 ...

Si el servicio no arranca, el motivo aparece en el registro:

sudo journalctl -u openvpn-server@server -n 50 --no-pager

Paso 7: Crear el perfil de un cliente

Cada cliente necesita su propio certificado. Genera la petición y fírmala como certificado de tipo cliente (escribe yes y la frase de paso de la CA cuando te lo pida):

cd ~/easy-rsa
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1

Lo más cómodo para el cliente es un único archivo .ovpn con la configuración y los certificados incrustados. Prepara un directorio para los perfiles con una copia de la clave tls-crypt que pueda leer tu usuario:

mkdir -p ~/clients
sudo install -m 600 -o "$USER" -g "$USER" /etc/openvpn/server/ta.key ~/clients/ta.key
chmod 700 ~/clients

Crea la configuración base común a todos los clientes, sustituyendo your_server_ip por la IP pública del servidor:

nano ~/clients/base.conf
client
dev tun
proto udp
remote your_server_ip 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verb 3

remote-cert-tls server hace que el cliente solo acepte un certificado firmado como servidor, lo que impide que otro cliente de tu VPN se haga pasar por el servidor.

Como tendrás que repetir el montaje del archivo para cada cliente, crea un pequeño script que lo haga:

nano ~/clients/make-client.sh
#!/usr/bin/env bash
set -euo pipefail

name="${1:?Uso: make-client.sh NOMBRE_CLIENTE}"
pki="$HOME/easy-rsa/pki"
out="$HOME/clients/${name}.ovpn"

{
  cat "$HOME/clients/base.conf"
  echo "<ca>"
  cat "$pki/ca.crt"
  echo "</ca>"
  echo "<cert>"
  sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' "$pki/issued/${name}.crt"
  echo "</cert>"
  echo "<key>"
  cat "$pki/private/${name}.key"
  echo "</key>"
  echo "<tls-crypt>"
  cat "$HOME/clients/ta.key"
  echo "</tls-crypt>"
} > "$out"

chmod 600 "$out"
echo "Perfil creado: $out"

Hazlo ejecutable y genera el perfil de client1:

chmod +x ~/clients/make-client.sh
~/clients/make-client.sh client1
Perfil creado: /home/your_user/clients/client1.ovpn

Desde tu equipo, descarga el perfil con scp:

scp your_user@your_server_ip:clients/client1.ovpn .

Paso 8: Conectar un cliente y verificar la VPN

En Windows, macOS, Android e iOS instala el cliente oficial (OpenVPN Connect u OpenVPN GUI en Windows) e importa el archivo client1.ovpn.

En un cliente Linux, instala OpenVPN y conecta desde la terminal:

sudo apt install openvpn
sudo openvpn --config client1.ovpn

Cuando la conexión se complete verás esta línea:

... Initialization Sequence Completed

Desde otra terminal del cliente, comprueba que llegas al servidor por la VPN y que tu tráfico sale con la IP del servidor:

ping -c 3 10.8.0.1
curl -4 https://icanhazip.com
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
your_server_ip

Si curl muestra la IP del servidor en lugar de la de tu conexión, todo el tráfico está pasando por la VPN.

En el servidor, los clientes conectados aparecen en el archivo de estado del servicio:

sudo cat /run/openvpn-server/status-server.log
...
CLIENT_LIST,client1,198.51.100.20:51820,10.8.0.2,,...
...

Paso 9: Revocar el acceso de un cliente

Si un dispositivo se pierde o una persona deja de necesitar acceso, revoca su certificado. Desde el directorio de Easy-RSA:

cd ~/easy-rsa
./easyrsa revoke client1
./easyrsa gen-crl

gen-crl genera la lista de revocación pki/crl.pem. Cópiala al servidor OpenVPN con permisos de lectura, porque el proceso la lee ya sin privilegios de root:

sudo install -m 644 pki/crl.pem /etc/openvpn/server/crl.pem

La primera vez, añade la directiva que activa la comprobación en /etc/openvpn/server/server.conf:

crl-verify crl.pem

Reinicia el servicio:

sudo systemctl restart openvpn-server@server

A partir de ahora, un cliente revocado que intente conectarse será rechazado y en el registro del servidor aparecerá un error de verificación de certificado (certificate revoked). En las siguientes revocaciones basta con ejecutar revoke, gen-crl y volver a copiar crl.pem; OpenVPN relee el archivo en cada conexión.

Solución de problemas

El cliente no conecta y se queda en TLS key negotiation failed to occur within 60 seconds

Los paquetes no llegan al servidor. Comprueba que el puerto 1194/udp está permitido en UFW (sudo ufw status), que remote en el perfil tiene la IP correcta y que el servicio está en marcha. Un perfil con una clave tls-crypt distinta produce el mismo síntoma, porque el servidor descarta los paquetes en silencio.

El cliente conecta pero no navega

Casi siempre falla el reenvío o el NAT. Comprueba en el servidor sysctl net.ipv4.ip_forward (debe ser 1), que el bloque *nat de /etc/ufw/before.rules usa el nombre correcto de la interfaz pública y que existe la regla ALLOW FWD en sudo ufw status. Tras editar before.rules, ejecuta sudo ufw reload.

El cliente navega por IP pero no resuelve nombres

El cliente no está aplicando los DNS enviados por el servidor. En Windows, macOS y móviles, el cliente oficial los aplica; en Linux, consulta la nota del paso 8.

Options error: ... No such file or directory al arrancar el servicio

Falta alguno de los archivos del paso 3 en /etc/openvpn/server/ o el nombre no coincide con el de server.conf.

Conclusión

Has montado un servidor OpenVPN en Ubuntu 24.04 con su propia CA, cifrado moderno y protección tls-crypt, has configurado el NAT con UFW, has generado un perfil .ovpn para un cliente y sabes revocar certificados. Como siguientes pasos, puedes crear un perfil por cada usuario con make-client.sh, limitar la VPN a una red privada en lugar de enrutar todo el tráfico, o añadir soporte IPv6 dentro del túnel con la directiva server-ipv6.