Llevo años usando Tailscale como mi VPN personal: increíblemente cómodo, configuración cero, funciona en todas partes. Pero nunca lo mantenía siempre activo — lo encendía cuando lo necesitaba y lo apagaba después. Un poco rudimentario como precaución, lo sé, pero había una razón: un servidor VPS expuesto a internet sentado en la misma red que mis dispositivos domésticos nunca me convenció. En algún momento decidí hacer las cosas correctamente, en lugar de depender de la disciplina manual.
1. El problema: la red de Tailscale es plana por defecto
Tailscale crea una red mesh privada entre todos tus dispositivos. Por defecto, cada nodo puede alcanzar a cualquier otro nodo en cualquier puerto. Es cómodo, pero es una red plana — exactamente como una LAN doméstica donde todos pueden verse entre sí.
Mi configuración: un servidor VPS expuesto a internet (Nginx, algunos puertos abiertos, servicios públicos) en la misma red Tailscale que mi PC doméstico, smartphone y Raspberry Pis. El riesgo es obvio — por eso no mantenía Tailscale siempre activo. Pero “lo apago cuando no lo necesito” no es una política: es una excusa. Basta con olvidarlo una vez, o querer revisar el monitoreo a las 2am, para tener la red plana activa sin haberlo pensado.
La solución correcta no es activar y desactivar — es segmentar: asegurarse de que el VPS, aunque se vea comprometido, no pueda alcanzar nada al otro lado de la red.
2. La solución: ACL y etiquetas de Tailscale
Tailscale permite definir políticas de acceso mediante un archivo de configuración en formato HuJSON (JSON con comentarios), gestionado desde la consola de administración. El mecanismo se basa en dos conceptos:
- Etiquetas: etiquetas asignadas a dispositivos (p. ej.
tag:server,tag:monitoring). Las etiquetas permiten agrupar dispositivos por rol, independientemente de quién los posea. - ACL (Lista de Control de Acceso): reglas que definen quién puede comunicarse con quién, en qué puertos y protocolos.
El sistema funciona como una lista blanca: todo lo que no está explícitamente permitido queda bloqueado. Esta es la diferencia clave respecto a la configuración predeterminada.
Las etiquetas se definen en la sección tagOwners del archivo de política, que especifica quién tiene derecho a asignar esa etiqueta a un dispositivo. Las etiquetas se asignan luego a los dispositivos desde la consola de administración o mediante tailscale set --advertise-tags en el propio dispositivo.
3. Diseño de la red
Estructuré la red con cinco dispositivos, cada uno con un rol bien definido:
| Dispositivo | Etiqueta | Rol |
|---|---|---|
| PC de escritorio | tag:personal | Máquina de trabajo / uso diario |
| Smartphone | tag:personal | Dispositivo móvil personal |
| Raspberry Pi (genérico) | tag:homelab | Servicios internos, experimentos |
| Raspberry Pi (monitoreo) | tag:monitoring | Prometheus, Grafana, alertas |
| Servidor VPS | tag:server | Servicios públicos expuestos a internet |
La lógica de acceso que quería implementar:
- Los dispositivos
personalpueden alcanzar todo (soy yo quien administra) - El nodo
monitoringpuede hacer scraping de todos los nodos (puerto 9100 para node_exporter) - El
serverVPS puede ser alcanzado desdepersonalymonitoring, pero no puede iniciar conexiones hacia otros homelabestá aislado: no puede ser alcanzado desde el servidor
4. Las políticas implementadas
Aquí está la matriz de visibilidad resultante:
| De A | personal | homelab | monitoring | server |
|---|---|---|---|---|
| personal | ✓ | ✓ | ✓ | ✓ |
| homelab | ✗ | ✓ | ✗ | ✗ |
| monitoring | ✗ | ✓ (9100) | ✓ | ✓ (9100) |
| server | ✗ | ✗ | ✗ | ✗ |
Y el archivo ACL HuJSON correspondiente:
{
// Who can assign tags
"tagOwners": {
"tag:personal": ["autogroup:admin"],
"tag:homelab": ["autogroup:admin"],
"tag:monitoring": ["autogroup:admin"],
"tag:server": ["autogroup:admin"]
},
"acls": [
// Personal devices can reach everything
{
"action": "accept",
"src": ["tag:personal"],
"dst": ["*:*"]
},
// Monitoring can scrape homelab and server (node_exporter)
{
"action": "accept",
"src": ["tag:monitoring"],
"dst": ["tag:homelab:9100", "tag:server:9100"]
},
// Monitoring can reach itself (e.g. Prometheus → Grafana)
{
"action": "accept",
"src": ["tag:monitoring"],
"dst": ["tag:monitoring:*"]
},
// Homelab can only reach itself
{
"action": "accept",
"src": ["tag:homelab"],
"dst": ["tag:homelab:*"]
}
// Everything else is implicitly blocked (whitelist)
]
}
Con esta configuración, el VPS no puede abrir conexiones hacia ningún otro nodo. Aunque se vea comprometido, queda aislado del resto de la red.
5. Un error común: etiquetas no asignadas a los dispositivos
Este es el error que cometí la primera vez, y probablemente algo con lo que se encontrará cualquiera que se acerque a esta configuración.
Escribí la política, la guardé en la consola de Tailscale y me conecté por SSH al servidor. Todo funcionó. Esperé unos minutos, lo intenté de nuevo — y SSH se quedó bloqueado. Sin timeout explícito, solo silencio.
El problema: había definido las etiquetas en la política pero no las había asignado a los dispositivos. Un dispositivo sin etiqueta no coincide con ninguna regla ACL, por lo que en modo lista blanca no puede enviar ni recibir nada — excepto las conexiones ya activas cuando se aplicó la política (que eventualmente expiran).
Diagnostica esto con:
tailscale status
En la columna de etiquetas, los dispositivos sin etiquetas aparecen vacíos o muestran solo el nombre de usuario. La solución es asignar etiquetas desde el propio dispositivo:
# On the VPS server
sudo tailscale set --advertise-tags=tag:server
# On the monitoring Raspberry Pi
sudo tailscale set --advertise-tags=tag:monitoring
# On the generic Raspberry Pi
sudo tailscale set --advertise-tags=tag:homelab
O desde la consola de administración de Tailscale, en la sección Machines, haciendo clic en el dispositivo y editando sus etiquetas. Tras la asignación, las reglas ACL entran en vigor en pocos segundos.
Nota: para asignar una etiqueta a un dispositivo, ese usuario (o el propio dispositivo, si usa una auth key con preautorización) debe figurar en la sección tagOwners de la política.
6. Conclusión
El principio de mínimo privilegio no es solo para aplicaciones empresariales. Aplicarlo a tu red doméstica — incluso con herramientas de consumo como Tailscale — marca una diferencia real.
El resultado práctico para mí fue poder mantener Tailscale siempre activo sin tener que pensar cada vez en qué está conectado a qué. La segmentación transformó una precaución conductual frágil (“recuerda apagarlo”) en una garantía estructural: el VPS está aislado por diseño, no por disciplina.
Unas pocas docenas de líneas de HuJSON, etiquetas asignadas a los dispositivos, y la topología de red finalmente refleja lo que realmente quería — no lo que era conveniente dejar por defecto.
Si gestionas una red Tailscale con dispositivos de distintos niveles de confianza (y un servidor expuesto a internet definitivamente cuenta como de menor confianza que tu portátil), vale la pena dedicar una tarde a hacer este trabajo correctamente.
¿Quieres hacerlo en cinco minutos? Delégaselo a Claude
Si tu red tiene más que un puñado de dispositivos, diseñar etiquetas y reglas ACL a mano se vuelve tedioso — especialmente si aún no conoces bien la sintaxis HuJSON. Hay una forma mucho más rápida: exporta la lista de hosts desde Tailscale y deja que Claude la procese directamente.
Ve a la consola de administración de Tailscale → Machines, copia la lista de máquinas con el hostname y el rol de cada una, luego pégalo todo en Claude con un prompt como:
Here is the list of machines on my Tailscale network:
- pc-home → personal PC, daily use
- personal-phone → personal smartphone
- rpi-monitor → Raspberry Pi with Prometheus and Grafana
- rpi-homelab → Raspberry Pi for experiments
- vps-prod → VPS server exposed to the internet
Create a complete HuJSON file for Tailscale ACLs:
- assign appropriate tags to each device based on its role
- define a sensible isolation policy (the server should not be able
to reach personal devices or the homelab)
- the monitoring node must be able to scrape all nodes (port 9100)
- add explanatory comments for each rule
- include the tailscale set --advertise-tags commands for each device
Como respuesta obtendrás un archivo HuJSON completo y comentado, la lista de comandos a ejecutar en cada nodo, y una matriz de visibilidad lista para usar — todo listo para pegar en la sección Access Controls de la consola de Tailscale. Si algo no parece correcto, basta con pedir ajustes: en pocos intercambios llegarás a una política personalizada sin tener que estudiar la sintaxis desde cero ni releer la documentación cada cinco minutos.








