Saltar al contenido
●homelab@casa:~/servidor
~$homelabista

// VPN CASERA

Cómo montar una VPN en casa con WireGuard (2026)

VPN casera con WireGuard y wg-easy v15: instalación, CG-NAT y cómo distinguir fallos de handshake, rutas y DNS sin abrir el panel a Internet.

10 min de lecturaGonzalo
  • #vpn-casera
  • #wireguard
  • #acceso-remoto
  • #raspberry-pi
Montar una VPN en casa con WireGuard: un túnel cifrado desde el móvil fuera de casa hasta tu red local, servido desde un mini PC o una Raspberry Pi de bajo consumo

Activar la VPN en el móvil no demuestra que puedas entrar en casa. WireGuard puede mostrar el túnel encendido sin haber intercambiado un solo paquete con el servidor. Y puede haber handshake, el intercambio inicial de claves, sin que cargue el NAS.

Para montar una VPN casera con WireGuard conviene separar esas dos cosas desde el principio: llegar al servidor VPN y llegar al servicio que está detrás. Si ya tienes la instalación hecha, salta al diagnóstico por síntomas. Si vienes de una receta antigua de wg-easy, revisa antes la diferencia entre v14 y v15.

[aff]Hay enlaces de afiliado más abajo: si compras algo desde ellos me llevo una pequeña comisión y a ti no te cuesta ni un céntimo más. En calidad de Afiliado de Amazon, obtengo ingresos por las compras adscritas que cumplen los requisitos aplicables.

Para qué sirve de verdad una VPN en casa

Una VPN casera permite acceder al NAS o a Home Assistant sin publicar sus paneles en Internet. El servidor VPN sí necesita una vía de entrada; lo que evitas es abrir un puerto por aplicación. Las cuentas, actualizaciones y permisos siguen haciendo falta.

También puedes usar la conexión de casa como salida cuando estás en una wifi ajena. Para eso necesitas un túnel completo, con rutas para el tráfico que quieras transportar, DNS y salida a Internet operativos. Encender WireGuard no garantiza por sí solo que todo el tráfico, incluido IPv6, pase por casa.

WireGuard, OpenVPN o Tailscale: cuál elegiría

WireGuard encaja si quieres gestionar las claves y dispones de un extremo alcanzable desde fuera. En Linux puede funcionar en el kernel; no necesitas una interfaz web para usarlo. wg-easy añade esa interfaz para administrar clientes.

OpenVPN tiene sentido cuando ya lo exige tu router o una infraestructura existente. No cambiaría una VPN que funciona sólo por cambiar de protocolo. Para una instalación doméstica nueva, empezaría valorando WireGuard por su configuración más pequeña.

Tailscale utiliza WireGuard y añade coordinación y mecanismos para atravesar NAT; cuando no consigue conexión directa puede recurrir a relés. Reduce el trabajo en conexiones con CG-NAT, a cambio de depender de esa coordinación y de sus políticas. No es lo mismo que instalar únicamente WireGuard.

Arquitectura de una VPN casera con WireGuard: el móvil fuera de casa cruza internet cifrado por el puerto UDP redirigido en el router hasta el servidor VPN en un mini PC o Raspberry Pi, que da acceso a la red local con NAS, Home Assistant y multimedia
El camino de un paquete cuando entras a tu red desde la calle. Solo un puerto abierto, y encima cifrado.

Dónde la alojas: router, Raspberry Pi o mini PC

Empieza por lo que ya esté encendido. Si tu router admite WireGuard y permite las rutas que necesitas, no hace falta comprar otra máquina. Si lo alojas en un servidor, recuerda que al apagarlo también pierdes ese acceso remoto.

Una Raspberry Pi 5 puede dedicar su sistema a la VPN; para wg-easy v15 utiliza un sistema arm64, no uno de 32 bits. La guía de Raspberry Pi como servidor ayuda a decidir si te compensa el conjunto de placa, almacenamiento y alimentación.

Si ya tienes un mini PC disponible, reutilizarlo evita otro gasto. El Beelink S12 Pro con Intel N100 es una opción compacta; el ME Mini con N95 y 12 GB tiene sentido si además necesitas sus seis ranuras M.2 para un NAS, con los SSD de datos aparte. No damos una velocidad de VPN garantizada: influyen la conexión, el sistema y la carga. El comparador de mini PC permite comparar configuraciones y TDP del procesador; para estimar la factura, usa consumo medido del equipo, no TDP, en la calculadora.

WireGuard en Docker: no mezcles wg-easy v14 y v15

La documentación de wg-easy recomienda la etiqueta :15 y advierte de que latest apunta a v14. Escribir sólo ghcr.io/wg-easy/wg-easy tampoco fija v15. El número importa: v15 es una reescritura y buena parte de las antiguas variables WG_HOST, WG_DEFAULT_DNS o PASSWORD_HASH se configura ahora desde el panel.

Si ya tienes v14, no cambies la imagen y reutilices la configuración a ciegas. La migración oficial pide conservar wg0.json y las variables anteriores, que no se migran automáticamente, e importar el archivo en el asistente nuevo. Esa copia contiene material sensible: guárdala fuera de la web y del repositorio público. Prepara otro acceso al servidor antes de intervenir en la VPN que usas para administrarlo.

Instalación nueva con el panel fuera de la LAN

Para Linux x86_64 o arm64, Docker Engine actualizado (28 o posterior) y Compose. El ejemplo adapta el Compose oficial: mantiene su red y publica la web sólo en loopback, para administrarla a través de SSH. Comprueba antes que 10.42.42.0/24 y la red IPv6 del ejemplo no se solapen con tus redes. No lo arranques encima de otra VPN que use los mismos puertos.

Guarda este compose.yaml en una carpeta nueva:

services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:15
    environment:
      INSECURE: "true"
    networks:
      wg:
        ipv4_address: 10.42.42.42
        ipv6_address: fdcc:ad94:bacf:61a3::2a
    volumes:
      - etc_wireguard:/etc/wireguard
      - /lib/modules:/lib/modules:ro
    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.all.disable_ipv6=0
      - net.ipv6.conf.all.forwarding=1
      - net.ipv6.conf.default.forwarding=1
    restart: unless-stopped

volumes:
  etc_wireguard:

networks:
  wg:
    driver: bridge
    enable_ipv6: true
    ipam:
      config:
        - subnet: 10.42.42.0/24
        - subnet: fdcc:ad94:bacf:61a3::/64

Desde esa carpeta, valida y arranca:

docker compose config --quiet
docker compose up -d

La validación comprueba el archivo, no una conexión desde Internet. :15 conserva la versión mayor, pero puede incorporar nuevas versiones menores al descargar; guarda configuración y copia antes de actualizar.

Desde tu ordenador, abre el túnel SSH hacia el servidor. Sustituye usuario@servidor-lan por tu acceso habitual:

ssh -N -L 127.0.0.1:51821:127.0.0.1:51821 usuario@servidor-lan

Mantén esa terminal abierta y visita http://127.0.0.1:51821 en tu ordenador. INSECURE=true permite HTTP en wg-easy; no aporta cifrado. En esta configuración el tramo entre ambos equipos lo protege SSH. No cambies el bind por 51821:51821 para arreglar un acceso fallido: publicarías el panel en todas las interfaces. Para otras formas de acceso usa la configuración HTTPS oficial y contrasta la exposición de puertos de Docker.

En el asistente de v15 crea la cuenta administradora, configura el dominio o IP pública y el puerto UDP del túnel, y crea un cliente. El QR y el archivo del cliente contienen su clave privada: no los incluyas en capturas ni consultas públicas.

Panel web de wg-easy con un cliente ficticio llamado Portátil de pruebas y una dirección privada de demostración
Panel de una versión anterior de wg-easy con un cliente ficticio; el asistente de v15 tiene otra interfaz. La captura sale de una instancia temporal y aislada: no contiene claves, códigos QR ni datos de la VPN doméstica.

Qué tráfico debe ir por el túnel

En el perfil del cliente, AllowedIPs decide qué destinos se envían a ese par. Para acceso sólo a casa, incluye las subredes que necesites y la dirección del DNS interno si cae fuera de ellas. 192.168.50.0/24 es un ejemplo, no una dirección que debas copiar sin mirar tu LAN. No traslades esa lista sin más al par del servidor: allí identifica las direcciones que corresponden a ese cliente.

Para túnel completo se suelen usar 0.0.0.0/0 y ::/0, pero el servidor debe tener reenvío y salida funcionales para ambas familias. Si no has preparado IPv6, no prometas que lo transportas. Tampoco un túnel dividido garantiza menos batería: depende del tráfico y del dispositivo.

El detalle que te va a tocar pelear: la puerta de casa

IP dinámica y CG-NAT no son el mismo problema. DDNS actualiza un nombre cuando cambia la dirección pública; no crea una ruta de entrada a través del NAT del operador.

Mira la IPv4 WAN/Internet del router, no su dirección LAN, y compárala con la IPv4 que ve una web desde esa conexión, sin otra VPN o proxy de por medio. Si no coinciden, hay que investigar el equipo o la red que hay delante; no basta para diagnosticar CG-NAT.

  • Una WAN entre 100.64.0.0 y 100.127.255.255 pertenece al espacio compartido 100.64.0.0/10 del RFC 6598. En una conexión doméstica es una señal para consultar al operador.
  • Una WAN en 10.0.0.0/8, 172.16.0.0/12 o 192.168.0.0/16 indica direccionamiento privado aguas arriba. Puede ser un segundo router tuyo, NAT del operador u otra topología. Comprueba qué equipo controla esa primera entrada.
  • Una WAN pública que coincide permite seguir con las reglas de entrada, pero no demuestra que el operador o el cortafuegos dejen pasar UDP.

Con IPv4 pública y un solo router, redirige 51820/UDP a una dirección LAN estable del servidor. Con doble NAT propio, configura las dos etapas o una topología adecuada a tu conexión. No actives una DMZ general ni abras el panel TCP 51821 para diagnosticar la VPN.

Si el CG-NAT del operador impide la entrada IPv4, las opciones incluyen solicitar IPv4 pública, utilizar IPv6 si ambos extremos tienen conectividad y reglas adecuadas, o iniciar desde casa una conexión hacia un extremo público que controles. Tailscale es otra alternativa. Un túnel web para publicar una aplicación no sustituye automáticamente una VPN para toda la LAN.

WireGuard no conecta: comprueba esto en orden

Haz la primera prueba con datos móviles y la wifi apagada, intentando abrir un servicio que sepas que funciona dentro de casa. Probar desde la propia LAN puede dar otro resultado por el NAT loopback del router.

En el servidor, desde la carpeta del Compose:

docker compose exec wg-easy wg show wg0 latest-handshakes
docker compose exec wg-easy wg show wg0 transfer

La primera salida muestra la clave pública del par y una marca de tiempo Unix; 0 significa que esa interfaz no registra todavía un handshake para ese par. La segunda muestra bytes recibidos y enviados. Comprueba el cliente que estás usando, no el de otro dispositivo. No publiques salidas completas: aunque estos dos comandos no muestran claves privadas, identifican pares y actividad. Evita compartir wg showconf o wg show ... dump, que sí pueden revelar secretos.

No aparece un handshake después de intentar acceder

Revisa el Endpoint del cliente (dominio/IP y puerto), su resolución DNS, la redirección UDP, los filtros y las claves de ambos pares. Si el dominio tiene registros IPv4 e IPv6, verifica por qué dirección intenta conectar. Un comprobador web de puertos TCP no demuestra que 51820/UDP funcione; WireGuard tampoco responde a cualquier paquete UDP sin autenticar.

No empieces cambiando el DNS de las aplicaciones: primero debe llegar el túnel. Si estás bajo CG-NAT, vuelve a la comprobación de la WAN. PersistentKeepalive = 25 puede conservar un mapeo NAT ya creado por un par que inicia tráfico, según el Quick Start de WireGuard; no abre por sí solo una entrada que el operador no ofrece.

Hay handshake, pero el NAS no abre ni por IP

Comprueba AllowedIPs, que la red remota no coincida con la wifi desde la que te conectas, el reenvío del servidor, sus filtros y el camino de vuelta desde la LAN. Prueba el servicio por su IP y puerto reales: que no responda a ping no basta para declararlo caído.

Ensayo aislado del 2 de octubre de 2026: dos pares WireGuard en redes Linux separadas intercambiaron tráfico. Al cambiar AllowedIPs del emisor para que excluyera la IP de destino, el ping dejó de llegar aunque seguía registrada la marca del handshake. Al restituir la ruta permitida volvió a funcionar. Se probó con wireguard-tools 1.0.20210914 y kernel 6.8.0-142-generic, sin tocar una VPN doméstica. Es una prueba de ese fallo concreto, no una medición de velocidad ni una validación de wg-easy v15 desde Internet.

Funciona por IP, pero no por nombre

Separa DNS convencional y descubrimiento local. El cliente necesita alcanzar un servidor DNS que conozca el nombre interno; la ruta hasta ese DNS también debe entrar por la VPN. Comprueba primero un registro interno que hayas configurado de verdad.

homeassistant.local es otro caso. .local utiliza normalmente mDNS, limitado al enlace local por el RFC 6762. WireGuard no extiende automáticamente ese multicast entre redes. Cambiar el DNS del perfil no garantiza que funcione. Usa la IP o un nombre en tu DNS interno, por ejemplo ha.home.arpa si lo has creado, antes de plantear repetidores de descubrimiento.

Entonces, ¿por dónde empiezo?

Primero averigua si tu conexión acepta la entrada que necesitas. Después elige el equipo ya disponible, instala una versión coherente de wg-easy y prueba desde fuera. Deja para el final el acceso por nombres: así no persigues un problema de DNS cuando el túnel ni siquiera alcanza tu casa.

Si vas a pedir ayuda, aporta versión, tipo de conexión y cuál de los tres síntomas anteriores observas, con direcciones e identificadores ocultos. El hilo de soporte «conecta, pero no accede a recursos» ilustra esa diferencia; es una consulta de 2024, no una incidencia actual ni una prueba de v15.