- Wag es un proyecto que agrega autenticación multifactor, restricción de rutas y registro de dispositivos a WireGuard, y permite distinguir entre rutas que requieren MFA y rutas públicas siempre accesibles
- Ofrece una API para registrar clientes nuevos, alta disponibilidad, actualizaciones y notificaciones de usuarios en tiempo real, e integraciones de MFA como Security Key, SSO, PAM y TOTP
- Para operar el servidor se requiere habilitar el reenvío de IP y, en ejecución manual, instalar
iptablesylibpam, además de ejecutarlo como root para gestionariptablesy dispositivos WireGuard - La administración puede hacerse desde la UI web y la CLI; la CLI incluye subcomandos
start,registration,devices,usersywebadminpara manejar tokens de registro, bloqueo de dispositivos, reinicio de MFA y cuentas de administrador web - Entre sus limitaciones, solo admite un
AllowedIPpor cliente y está orientado principalmente a Linux; Windows puede funcionar con algunos pasos adicionales
Funcionalidades que Wag agrega a WireGuard
- Wag agrega MFA, restricción de rutas y registro de dispositivos a WireGuard
- Las rutas pueden definirse separando las que requieren autenticación MFA de las rutas públicas que siempre están accesibles
- Proporciona una API sencilla para registrar clientes nuevos
- Soporta alta disponibilidad, actualizaciones y notificaciones de usuarios en tiempo real
- Las integraciones de MFA incluyen los siguientes métodos
- Security Key
- SSO
- PAM
- TOTP
- La documentación está disponible en Documentation
Requisitos de instalación y ejecución
- Debe estar habilitado el reenvío en el servidor
- Para IPv4 se usa la configuración
net.ipv4.ip_forward=1 - Para IPv6 se usan configuraciones
sysctlrelacionadas comonet.ipv6.conf.all.forwarding=1
- Para IPv4 se usa la configuración
- El ejemplo de ejecución con Docker Compose usa la imagen
wagvpn/wag:latest- Un ejemplo de puerto para la página de administración es
4433/tcp - Un ejemplo de puerto para la página pública de registro es
8081/tcp - Un ejemplo de puerto de WireGuard es
53230/udp - El dispositivo
/dev/net/tunse conecta al contenedor
- Un ejemplo de puerto para la página de administración es
- La instalación manual requiere
iptablesylibpam - Wag debe ejecutarse como root para administrar
iptablesy los dispositivos WireGuard - Las versiones binarias requieren
glibc 2.31+ - Compilar desde el código fuente requiere
go1.23.1ynpm
Formas de administración
- Después de habilitar la UI de administración y configurar Wag, se crea el primer administrador y la contraseña se imprime en STDOUT
- Luego se puede iniciar sesión en la UI web para administrar usuarios
- El usuario root puede administrar el servidor Wag desde la CLI
- El formato de la CLI es
wag subcommand [-options] - Los subcomandos soportados son los siguientes
start: inicia el servidor Wag sin ejecutarlo como daemonregistration: maneja la creación, eliminación y listado de tokens de registrodevices: maneja el listado, eliminación, bloqueo, desbloqueo y consulta de sesiones MFA activas de dispositivos WireGuardusers: maneja la administración de MFA de usuarios, eliminación de usuarios, bloqueo de cuentas y reinicio de MFAwebadmin: maneja agregar, eliminar, listar, bloquear y desbloquear usuarios administradores de la UI webversionyfirewalltambién están incluidos entre los comandos soportados
Flujo de tokens de registro y MFA
- Para registrar un dispositivo nuevo, primero se genera un token de registro con un comando como
wag registration -add -username tester - Si se entrega el token generado al endpoint público de registro, se puede obtener una respuesta con la configuración de WireGuard
- La configuración devuelta incluye elementos como
Interface,PrivateKey,Address,Peer,Endpoint,PublicKey,AllowedIPsyPersistentKeepAlive - El usuario se conecta a la dirección VPN del servidor e ingresa el código 2FA
- El tiempo durante el cual la sesión permanece activa antes de expirar se define en el archivo de configuración
Consola de administración web
- Para iniciar sesión en la consola de administración,
Webserver.Management.Enableddebe estar configurado entrue - En la consola se agrega una cuenta de administrador web con
sudo ./wag webadmin -add -username <your_username> -password <your-password-here> - Después se accede a la dirección de escucha de administración e ingresan las credenciales
- La propia interfaz web no puede agregar usuarios administradores
- Se recomienda no exponer el portal de administración hacia el exterior; se recomienda configurar
ListenAddressen127.0.0.1olocalhosty exponerlo mediante reenvío SSH
Principales opciones de configuración
NumberProxiesespecifica cuántos proxies reversos confiables hay delante del cliente y permite que Wag interpreteX-Forward-Forpara obtener la IP del clienteSocketes el socket de control de Wag; al cambiarlo, se pueden ejecutar varias instancias de Wag en la misma máquinaNATactiva o desactiva el enmascaramiento; si está habilitado, todo el tráfico parecerá originarse en el servidor VPNNATExcludeRangesespecifica los rangos CIDR excluidos de NAT cuandoNAT=trueExposePortsexpone puertos del servidor VPN a los clientes y agrega reglas deiptablesCheckUpdatesestá desactivado por defecto; si se activa, la UI de administración mostrará avisos de nuevas versiones de Wag y accederá aapi.github.comAclsdefine grupos y políticas, pero solo se aplica en la primera ejecución; durante la ejecución se edita desde la UI webWebserverincluye la configuración del endpoint público de registro, el portal MFA del túnel y el portal de administraciónWireguardconfigura el nombre del dispositivo, el puerto de escucha, la clave privada, la subred a cargo de la VPN, el MTU y los servidores DNSClusteringincluye la configuración del nombre del clúster, el estado del clúster etcd, el nivel de logs, nodos witness, ubicación de la base de datos y certificados del clúster
Comportamiento de las políticas ACL
Policiesdefine las rutas que la VPN capturará y los puertos y protocolos que pasarán por Wag- La aplicación de reglas usa la longitud del prefijo de subred, y la coincidencia más específica determina el nivel de acceso a la ruta
- Por ejemplo, si
/16se define como MFA y un/32específico dentro de ese rango se define como Allow, ese/32más específico tiene prioridad y permite acceso sin MFA - Este comportamiento cambió en
v6.0.0; antes, las rutas MFA siempre tenían prioridad - Si se definen varias políticas para una misma ruta, las políticas se componen y las reglas MFA tienen prioridad
- A partir de una versión que aún no ha sido liberada, las reglas
Denypueden bloquear el acceso a rutas - Como la regla más específica crea un nuevo “bucket” de reglas, si en el bucket
/32solo hay un deny, puede que tampoco se permita el acceso a otros puertos del mismo/32
Reglas de puertos y protocolos
- El acceso a servicios puede definirse con reglas de puertos y protocolos
- Hay 3 tipos de reglas soportadas
- Any: si no hay una regla separada o se usa la palabra clave
any, se permite cualquier combinación de servicio y puerto - Single Service: permite puertos TCP o UDP específicos de un host, como
192.168.1.1 22/tcp 53/udp - Ranges: permite definir rangos de puertos, como
192.168.1.1 22-1024/tcp 23-53/any
- Any: si no hay una regla separada o se usa la palabra clave
- En los rangos de puertos, primero debe escribirse el puerto menor
- ICMP no tiene puertos, así que puede especificarse sin puerto, como
1.1.1.1 icmp
Limitaciones y desarrollo
- Wag solo soporta un
AllowedIPpor cliente - Esta limitación se adapta a una estructura de cliente a servidor
- Está orientado principalmente a Linux y Windows puede funcionar con algunos pasos adicionales
- En modo de desarrollo se puede usar una variable de entorno para establecer como IP del cliente la IP de las solicitudes que entran por el túnel
- El ejemplo de prueba ejecuta
sudo go test -v .eninternal/router - Para contribuciones externas, se indica que al agregar funciones o corregir errores se escriban pruebas cuando sea posible y se abra un Pull Request
1 comentarios
Opiniones en Hacker News
Se ve bien, pero hay algunas cosas que me preocupan.
Con el ejemplo
curl [http://public.server.address:8080/register_device?key=e83253...](<http://public.server.address/register_device/…;)y la descripción de que “el servicio devuelve una respuesta completamente basada en plantillas”, parece que durante el proceso de registro el servidor genera la clave privada y se la envía al cliente, en vez de que el cliente cree la clave privada y envíe la clave pública al servidor.Además, como el ejemplo usa HTTP, sería bueno cambiar al menos esa parte para que la gente no piense que HTTP también es una opción aceptable.
También me pregunto si el cliente tiene alguna forma de darse cuenta cuando la sesión expira. ¿O algo como una sesión SSH simplemente se queda colgado?
A veces he buscado un cliente de WireGuard que funcione como la detección de portales cautivos en Wi-Fi. Idealmente sería algo como agregar una línea tipo
persistentkeepaliveal archivo de configuración para obtener una URL y revisarla periódicamente. Si llegaOK, todo normal; si no hay respuesta, es un problema de red; si llega un encabezadoLocation, abrir el navegador en esa ubicación para reautenticar la sesión, etc.Todavía no he encontrado un cliente así.
pubkey, así que no es necesario depender de que el servidor genere la clave privada. La documentación es insuficiente, así que es comprensible que confunda.Para responder a la última pregunta: eBPF XDP, que es lo que uso, solo puede hacer
PASS,DROPyREDIRECT. Así que lo manejo con el resultado más simple,PASS/DROP, y la conexión simplemente se queda colgada.Sin embargo, si agregas la página de detección de portal cautivo a la lista de MFA de wag, puedes configurar la detección por tu cuenta, y después el navegador se encargará del resto.
No tengo intención de implementar en wag una funcionalidad que actúe como interceptación o proxy. Hacer eso facilitaría un poco manejar expiraciones de autenticación o cierres de sesión, pero no es la dirección que quiero tomar.
Escribí un cliente en Go para Mac y también manejaba la generación de claves usando el
wgde línea de comandos de Brew, pero era tosco y requeríasudo.Sería bueno tener una app nativa bien hecha que use permisos de red, pero eso está fuera de mis capacidades.
Me pregunto si ya han abordado, o planean abordar, el problema de la gestión de sesiones.
En esencia, una clave de WireGuard es como una clave de sesión eterna.
Si el software que implementa la capa de transporte de WireGuard pretende ser una solución de servidor VPN completa, creo que también debería implementar gestión de sesiones. Es decir: rotar periódicamente las claves de sesión mediante un segundo canal con el servidor, finalizar sesiones, cambiar direcciones IP, configurar nuevas rutas y repetir la autenticación cuando sea necesario.
La clave de WireGuard permite comunicarse con el servidor wag, pero la sesión real se mantiene en un mapa eBPF que contiene si el usuario está autenticado o no.
Por eso, aunque alguien robe el material de la clave privada, no puede acceder a las rutas protegidas por MFA.
Me pregunto si están impidiendo los ataques de fuerza bruta contra códigos TOTP. Por ejemplo, con límites de velocidad o límites de reintentos.
Le di un vistazo rápido al código y no encontré nada de eso.
El escenario que imagino es alguien que abre la UI de ingreso de TOTP en el navegador, abre las herramientas de desarrollo y prueba iterativamente todos los códigos TOTP posibles.
En particular, la intención también es hacer que el usuario se pregunte por qué el dispositivo está intentando autenticarse a la fuerza. Una situación así podría indicar que el endpoint está comprometido.
Suena muy parecido a Headscale o Tailscale. Es bueno ver alternativas para administrar redes WireGuard.
Me pregunto si hay algún material comparativo para entender hasta dónde se superponen las funciones, qué se agregó, qué es distinto y qué cosas no se implementarán en el futuro.
No incluí una comparación directa en la documentación, pero actualmente no es la dirección en la que quiero ir. Este proyecto se ajusta a mis necesidades y es bastante divertido.
Wag encaja mejor con una estructura hub-and-spoke que busca límites firmes, más que con una malla al estilo Tailscale donde todo puede llegar a todo y las reglas definen el overlay.
Tanto wag como Tailscale agregan integración SSO y, en la práctica, 2FA para proteger a los usuarios.
Ambos tienen una UI web para métodos de registro y administración, pero como soy un desarrollador en solitario al que no le gusta el desarrollo web, Tailscale seguramente está mucho más pulido.
Lo que definitivamente no voy a implementar es interceptación o proxy TLS para redirigir usuarios después de cerrar sesión. La razón principal es que hacerlo con eBPF ahora mismo se me hace un poco demasiado, y no quiero usar los componentes DNAT/SNAT que probablemente tendría que escribir para que funcione.
Que sea solo IPv4… pensaría que un sitio que elige WireGuard quizá tenga una configuración más moderna y use bastante ULA propia como servicio.
Me pregunto si tenías algo específico en mente al mencionar ULA.