Una nube híbrida une servidores con precio fijo, como un VPS, con los servicios bajo demanda de una nube pública, de forma que ambos entornos se comuniquen por direcciones privadas como si estuvieran en la misma red. En este tutorial conectarás un VPS con Ubuntu 24.04 a una VPC de AWS mediante un túnel WireGuard, usando una instancia EC2 como pasarela, y configurarás las rutas para que el VPS alcance cualquier recurso privado de la VPC. Al final verás cómo repartir las cargas entre los dos entornos.

Requisitos previos

Para seguir esta guía necesitas:

  • Un VPS con Ubuntu 24.04 LTS e IP pública fija, por ejemplo un VPS de CubePath, con un usuario no root con privilegios sudo y UFW activo.
  • Una cuenta de AWS con una VPC. Los ejemplos usan la VPC por defecto, cuyo rango es 172.31.0.0/16; si la tuya es otra, sustituye el rango.
  • Una instancia EC2 pequeña con Ubuntu 24.04 en esa VPC, que hará de pasarela. Un tipo t4g.nano o t3.micro basta para tráfico moderado.
  • La AWS CLI v2 configurada en tu equipo con permisos sobre EC2.

Paso 1: Planificar las direcciones

Los rangos de los dos entornos no pueden solaparse, o las rutas serán ambiguas. En esta guía se usan:

RedRangoUso
VPC de AWS172.31.0.0/16Instancias, bases de datos y demás recursos privados
Túnel WireGuard10.200.0.0/2410.200.0.1 el VPS, 10.200.0.2 la pasarela EC2

Comprueba en el VPS que ningún rango local coincide con los anteriores, por ejemplo si tienes una red privada entre VPS:

ip -brief address
ip route

Si alguna interfaz ya usa 10.200.0.0/24 o parte de 172.31.0.0/16, elige otro rango para el túnel.

El diseño es el siguiente: el VPS, que tiene IP fija, escucha en el puerto UDP 51820. La pasarela EC2 inicia la conexión hacia él, así que no necesita IP pública fija ni abrir puertos de entrada en AWS, y reenvía el tráfico entre el túnel y la VPC.

Paso 2: Instalar WireGuard y generar las claves

Ejecuta estos comandos en los dos servidores, el VPS y la instancia EC2. Instala las herramientas de WireGuard; el módulo del kernel ya viene incluido en Ubuntu 24.04:

sudo apt update
sudo apt install wireguard

Genera el par de claves. La clave privada se crea directamente con permisos 600:

sudo sh -c 'umask 077; wg genkey > /etc/wireguard/private.key'
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
kC3fR1q0dQ8x3bT4nJ0mH7pL2vW9sY6aE5uZ1iO8gXk=

El valor mostrado es la clave pública. Anota la del VPS (vps_public_key) y la de la instancia EC2 (ec2_public_key); cada servidor necesita la clave pública del otro. La clave privada nunca sale de su servidor.

Paso 3: Configurar WireGuard en el VPS

Crea la configuración del VPS:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.200.0.1/24
ListenPort = 51820
PostUp = wg set %i private-key /etc/wireguard/private.key

[Peer]
# Pasarela EC2 en AWS
PublicKey = ec2_public_key
AllowedIPs = 10.200.0.2/32, 172.31.0.0/16

PostUp carga la clave privada desde su archivo, así no queda copiada en la configuración. AllowedIPs tiene dos funciones: acepta del peer solo paquetes con esos orígenes y hace que wg-quick añada rutas hacia ellos por el túnel, de modo que todo el tráfico a 172.31.0.0/16 saldrá por wg0.

Abre el puerto UDP en el firewall y levanta la interfaz como servicio de systemd:

sudo ufw allow 51820/udp
sudo systemctl enable --now wg-quick@wg0
sudo wg show
interface: wg0
  public key: kC3fR1q0dQ8x3bT4nJ0mH7pL2vW9sY6aE5uZ1iO8gXk=
  private key: (hidden)
  listening port: 51820

peer: 9mZ2...=
  allowed ips: 10.200.0.2/32, 172.31.0.0/16

Todavía no hay latest handshake porque la pasarela no está configurada.

Paso 4: Configurar la pasarela EC2

Crea la configuración en la instancia EC2, sustituyendo your_vps_ip por la IP pública del VPS:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.200.0.2/24
PostUp = wg set %i private-key /etc/wireguard/private.key

[Peer]
# VPS
PublicKey = vps_public_key
Endpoint = your_vps_ip:51820
AllowedIPs = 10.200.0.1/32
PersistentKeepalive = 25

PersistentKeepalive envía un paquete cada 25 segundos para que el túnel se mantenga abierto a través del NAT de AWS aunque no haya tráfico.

La pasarela debe reenviar paquetes entre el túnel y la VPC. Activa el reenvío IP de forma persistente:

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

Levanta el túnel y comprueba el handshake:

sudo systemctl enable --now wg-quick@wg0
sudo wg show wg0 latest-handshakes
ping -c 3 10.200.0.1
64 bytes from 10.200.0.1: icmp_seq=1 ttl=64 time=24.1 ms
64 bytes from 10.200.0.1: icmp_seq=2 ttl=64 time=23.8 ms
64 bytes from 10.200.0.1: icmp_seq=3 ttl=64 time=23.9 ms

El túnel entre los dos extremos ya funciona. Solo necesitas permitir el tráfico saliente UDP hacia el VPS, que el grupo de seguridad por defecto ya permite.

Paso 5: Enrutar el tráfico dentro de la VPC

Por defecto, AWS descarta los paquetes que una instancia reenvía con un origen o destino que no son los suyos. Desactiva esa comprobación en la pasarela, sustituyendo el ID de la instancia:

aws ec2 modify-instance-attribute --instance-id your_instance_id --no-source-dest-check

Las demás instancias de la VPC tienen que saber que 10.200.0.0/24 se alcanza a través de la pasarela. Averigua la tabla de rutas de la subred de la pasarela y añade la ruta:

aws ec2 describe-route-tables --filters Name=vpc-id,Values=your_vpc_id \
  --query 'RouteTables[].[RouteTableId,Associations[0].Main]' --output table
aws ec2 create-route --route-table-id your_route_table_id \
  --destination-cidr-block 10.200.0.0/24 --instance-id your_instance_id
{
    "Return": true
}

Si tu VPC tiene varias tablas de rutas (por ejemplo subredes privadas), añade la misma ruta en cada una.

Por último, los grupos de seguridad de los recursos a los que quieras llegar deben aceptar tráfico del túnel. Por ejemplo, para permitir ICMP y PostgreSQL desde el VPS en el grupo de seguridad de una instancia o una base de datos:

aws ec2 authorize-security-group-ingress --group-id your_sg_id \
  --ip-permissions 'IpProtocol=icmp,FromPort=-1,ToPort=-1,IpRanges=[{CidrIp=10.200.0.0/24}]'
aws ec2 authorize-security-group-ingress --group-id your_sg_id \
  --protocol tcp --port 5432 --cidr 10.200.0.0/24

Aplica también la regla de ICMP al grupo de seguridad de la pasarela si quieres hacerle ping por su IP de la VPC.

Paso 6: Verificar la conectividad de extremo a extremo

Desde el VPS, haz ping a la IP privada de otra instancia de la VPC (your_private_instance_ip, por ejemplo 172.31.20.15):

ping -c 3 your_private_instance_ip
64 bytes from 172.31.20.15: icmp_seq=1 ttl=63 time=24.6 ms

El ttl=63 indica que el paquete ha atravesado un salto, la pasarela. Comprueba la ruta completa:

tracepath -n your_private_instance_ip
 1:  10.200.0.2                                           24.3ms
 2:  172.31.20.15                                         24.7ms reached

Desde la instancia de la VPC, el camino inverso también funciona: un ping 10.200.0.1 llega al VPS, porque la tabla de rutas de la VPC envía ese rango a la pasarela.

Paso 7: Repartir las cargas entre VPS y nube pública

Con la red unida, cada componente puede vivir donde sea más rentable. Una división habitual:

En el VPSEn la nube pública
Web y API con tráfico constanteTrabajos por lotes y procesamiento puntual
Base de datos principalRéplicas de lectura para analítica
Proxy inverso y terminación TLSInstancias con GPU bajo demanda
Monitorización y logsAlmacenamiento de objetos para backups y archivos

Algunos ejemplos concretos de uso del túnel:

  • La aplicación del VPS consulta una base de datos o una caché que vive en subredes privadas de la VPC, sin exponerlas a Internet.
  • Una instancia de la VPC lee de una réplica PostgreSQL en el VPS para generar informes, sin cargar la base de datos principal.
  • Sincronizar archivos al entorno de AWS por la red privada, cifrados por WireGuard, con rsync -a --delete /var/www/uploads/ your_user@your_private_instance_ip:/srv/uploads/.

Ten en cuenta que AWS cobra el tráfico que sale de la VPC hacia el VPS. Si mueves volúmenes grandes en ese sentido, calcula ese coste antes de decidir dónde colocar cada componente.

Solución de problemas

latest handshake no aparece: el paquete no llega al VPS. Comprueba que el puerto está abierto con sudo ufw status | grep 51820, que la IP en Endpoint es correcta y que las claves públicas no están intercambiadas. Revisa los errores con sudo journalctl -u wg-quick@wg0.

El ping a la pasarela por el túnel funciona pero no a otras instancias: revisa, por orden, que net.ipv4.ip_forward vale 1 en la pasarela, que la comprobación de origen y destino está desactivada (aws ec2 describe-instance-attribute --instance-id your_instance_id --attribute sourceDestCheck), que la tabla de rutas de la subred de destino tiene la ruta a 10.200.0.0/24 y que el grupo de seguridad del destino acepta ese rango.

El tráfico va por Internet en lugar del túnel: en el VPS, ip route get your_private_instance_ip debe mostrar dev wg0. Si no, falta el rango de la VPC en AllowedIPs; corrígelo y reinicia con sudo systemctl restart wg-quick@wg0.

Conexiones TCP que se cuelgan con transferencias grandes: WireGuard añade cabeceras y la interfaz usa un MTU de 1420 por defecto. Si alguna ruta intermedia tiene un MTU menor, prueba con MTU = 1380 en la sección [Interface] de ambos extremos.

Conclusión

Tu VPS y tu VPC de AWS forman ahora una sola red privada unida por un túnel WireGuard cifrado, con rutas en ambos lados y grupos de seguridad que controlan qué puede alcanzar cada recurso. Como siguientes pasos puedes añadir una segunda pasarela en otra zona de disponibilidad para eliminar el punto único de fallo, conectar de la misma forma una red de otro proveedor con un nuevo peer, o valorar AWS Site-to-Site VPN si prefieres un servicio gestionado con IPsec a cambio de un coste por hora.