Saltar a contenido

WireGuard — VPN del homelab

Reemplaza a Tailscale/Headscale (jul 2026). VPN plana punto a punto, sin control plane.

Servidor

Item Valor
Interfaz wg0100.99.21.122/24
Puerto 51820/udp (router monopuesto, llega directo)
Config /etc/wireguard/wg0.conf (600 root)
Servicio wg-quick@wg0 (enabled)
NAT MASQUERADE hacia enp42s0 vía PostUp (acceso a LAN 192.168.0.0/24)
Endpoint público matias7235.com.ar:51820 (registro raíz, mantenido por DDNS deSEC)

Clientes

Configs en /etc/wireguard/clients/:

Cliente IP Config
notebook 100.99.21.2 notebook.conf
celular 100.99.21.3 celular.conf
pc escritorio (Arch Linux) 100.99.21.4 /etc/wireguard/clients/pc-escritorio-arch.conf

Notebook y celular usan full tunnel (AllowedIPs = 0.0.0.0/0, ::/0). La PC de escritorio usa split tunnel para el homelab (AllowedIPs = 100.99.21.0/24, 192.168.0.0/24). Todos mantienen MTU = 1380 para evitar fragmentación.

  • DNS: 192.168.0.12 (AdGuard) → resuelve *.matias7235.com.ar a la IP LAN (split-horizon).
  • PresharedKey por peer (defensa extra post-cuántica).
  • El server ya soporta exit node sin cambios adicionales: el MASQUERADE de wg0.conf no distingue destino, y las reglas FORWARD aceptan todo el tráfico entrante/saliente de wg0.

Operaciones

sudo wg show                          # estado y handshakes
sudo systemctl restart wg-quick@wg0   # aplicar cambios de wg0.conf
sudo qrencode -t ansiutf8 < /etc/wireguard/clients/celular.conf   # QR para el móvil

Agregar un cliente nuevo

umask 077
K=$(wg genkey); P=$(echo $K | wg pubkey); PSK=$(wg genpsk)
# 1. Agregar [Peer] en /etc/wireguard/wg0.conf con PublicKey=$P, PresharedKey=$PSK, AllowedIPs=100.99.21.X/32
# 2. Crear /etc/wireguard/clients/<nombre>.conf con PrivateKey=$K (mismo formato que los existentes, Address=100.99.21.X/32)
# 3. sudo systemctl restart wg-quick@wg0

Cambio de rango: 10.66.66.0/24 → 100.99.21.0/24 (2026-08-12)

El servidor pasó de 10.66.66.1 a 100.99.21.122 (la vieja IP de Tailscale, ya memorizada). Los últimos octetos de los clientes se conservaron (.2, .3, .4). Las claves no cambiaron: la migración fue solo el campo Address en cada dispositivo.

⚠️ 100.64.0.0/10 es espacio CGNAT (RFC 6598) y es el rango que Tailscale reclama entero. Si alguna vez se reinstala Tailscale, agrega una ruta para todo el /10 y rompe esta VPN. Migrar el rango antes de instalarlo (10.99.21.0/24 era la alternativa evaluada).

Además de wg0.conf y los .conf de cliente, el cambio tocó: los port bindings de firecrawl (:3002) y searxng (:8518), el ACL de /admin* en el Caddyfile, ignoreip de fail2ban y las reglas de /etc/ufw/user.rules (ufw inactivo). Backup previo en /root/wg-migracion-2026-08-12-1438/.

🔶 Estado transitorio: dual-rango (pendiente de limpiar)

Para no dejar los dispositivos sin VPN mientras se migran de a uno, el servidor acepta los dos rangos a la vez: Address = 100.99.21.122/24, 10.66.66.1/24, MASQUERADE para ambos, y cada peer con AllowedIPs = 100.99.21.X/32, 10.66.66.X/32. Un dispositivo funciona igual con la IP vieja o la nueva.

Al terminar de migrar los 3 dispositivos, revertir a rango único: quitar de wg0.conf la segunda Address, el segundo MASQUERADE de PostUp/PostDown y el segundo AllowedIPs de cada peer; después systemctl restart wg-quick@wg0. Mientras el dual siga activo, un cliente mal configurado sigue andando y no te enterás.

Se aprovechó para hacer el PostDown tolerante a fallos (|| true por regla). Antes, un restart con el rango ya editado hacía fallar el stop con iptables: Bad rulestatus=1/FAILURE, y dejaba la regla NAT vieja huérfana en la tabla.

Nota operativa — el Caddyfile es un bind mount de archivo. sed -i reemplaza el inode, así que el contenedor sigue viendo la versión anterior: caddy reload reporta éxito sin aplicar nada. Después de editarlo hace falta docker restart caddy.

Migración desde Headscale — COMPLETADA (2026-07-04)

  • Headplane y Headscale eliminados: stacks archivados en /opt/docker/headplane.removed.20260704 y /opt/docker/headscale.removed.20260704, entradas quitadas del Caddyfile.
  • tailscaled detenido, deshabilitado y desinstalado del server (las reglas ts-* de iptables se fueron con él). Desinstalar también el cliente Tailscale de los dispositivos si quedó alguno.
  • WireGuard verificado como exit node en notebook y celular (handshakes y tráfico confirmados).