RocksDNS por dentro: cómo montamos un DNS público cifrado sin puerto 53
RocksDNS lleva un año en marcha. En este tiempo hemos cambiado de arquitectura, hemos aprendido cosas por las malas y hemos llegado a una configuración que funciona bien en producción. Este artículo explica cómo está montado ahora mismo: las piezas, por qué las elegimos y qué hemos aprendido en el proceso.
No es un manual de copiar y pegar. Es la explicación de las decisiones detrás de la arquitectura actual, con los comandos clave donde ayudan a entenderla.
Por qué montamos RocksDNS
El punto de partida fue simple: no queríamos depender de resolvers corporativos para algo tan básico como resolver un nombre de dominio. Cada consulta DNS revela qué servicios usas, y quien controla esa resolución tiene una vista bastante completa de tus hábitos.
RocksDNS nació para ofrecer resolución cifrada, sin guardar historial de consultas, y con bloqueo de parte del ruido publicitario y de tracking. No pretende sustituir a un DNS corporativo en escala, pero sí demostrar que se puede montar algo útil sin depender de los proveedores habituales.
Qué ofrece
DoH, DoT y DoQ: tres formas actuales de resolución DNS cifrada. Sin DNS plano público expuesto.
Sin puerto 53 público: el DNS tradicional en texto plano no está expuesto a internet. Internamente, la resolución queda limitada a localhost o a redes privadas entre nodos.
Bloqueo de publicidad y rastreo: mediante listas locales cargadas en Unbound antes de continuar con la resolución recursiva.
Consultas sin registrar: no se guarda un historial de qué dominios resuelve cada usuario.
Arquitectura general
La cadena de resolución sigue este orden:
Cliente → dnsdist (DoH/DoT/DoQ) → Unbound (bloqueo + caché + DNSSEC + recursión) → Internet
dnsdist hace de frontal: recibe las consultas cifradas, reparte carga y aplica límites. Unbound aplica el bloqueo mediante listas locales, valida DNSSEC, mantiene caché y resuelve de forma recursiva, sin depender de resolvers de terceros. Los backends internos entre nodos se comunican mediante WireGuard, no expuestos a internet abierto.
Por qué dnsdist
Antes de dnsdist, cada protocolo cifrado necesitaba su propia gestión de certificados y su propia configuración de exposición. dnsdist centraliza esto:
Separación de protocolos: DoH, DoT y DoQ gestionados desde un único punto de entrada, con certificados compartidos.
Rate limiting: límites por IP y por patrón de consulta, para contener abuso sin tocar Unbound.
Reparto de carga: entre backends de Unbound, con reintentos automáticos si uno falla.
Visibilidad operativa: métricas de consultas, latencias y errores sin necesidad de registrar el contenido de las consultas.
Por qué Unbound
Unbound resuelve de forma recursiva: en lugar de reenviar tu consulta a un resolver de terceros, va directamente a los servidores raíz y baja por la cadena de delegación hasta obtener la respuesta. Esto evita depender de qué hace un proveedor externo con esas consultas.
DNSSEC: validación de firmas para evitar respuestas manipuladas.
Caché propia: reduce latencia y carga en resoluciones repetidas.
Serve-expired: responde con datos de caché ligeramente caducados mientras resuelve en segundo plano, en lugar de hacer esperar al cliente.
Root hints locales: Unbound parte de la zona raíz y resuelve de forma recursiva, sin forwarders externos por defecto. Resolución real, no reenvío disfrazado.
Bloqueo DNS
El filtrado combina dos capas. La base es OISD Big, una lista de bloqueo amplia y bien mantenida que cubre publicidad, tracking y dominios maliciosos conocidos. Sobre esa base aplicamos una lista propia de ajuste fino: no es una lista enorme ni especialmente elaborada, y preferimos no publicarla completa porque cambia con frecuencia y está pensada para complementar OISD, no para sustituirla. La usamos sobre todo para cubrir dominios concretos que vemos en abuso, tracking, publicidad especialmente agresiva o casos que OISD todavía no cubre.
En un momento anterior de RocksDNS, AdGuard Home hacía tanto de filtro como de intermediario hacia el resolver. Lo retiramos de esa posición: ahora el filtrado lo aplica Unbound directamente mediante listas locales, de forma más ligera, y AdGuard ya no está en la ruta crítica de resolución.
Seguridad
El stack de seguridad sigue la misma línea que el resto de la infraestructura TuiterRocks: firewall restrictivo, SSH endurecido, Fail2Ban y CrowdSec con bouncer de firewall, combinando listas comunitarias con escenarios propios ajustados a lo que vemos en producción.
La defensa principal no es poner más capas por ponerlas, sino exponer menos cosas. En RocksDNS en concreto, lo más importante es la reducción de superficie expuesta:
Sin puerto 53 público: solo protocolos cifrados expuestos a internet.
Paneles no expuestos: la administración no es accesible desde internet.
WireGuard entre nodos: los backends internos se comunican por una red privada, no por internet abierto.
Fail2Ban + CrowdSec: contención de intentos de abuso en los puntos que sí están expuestos.
Lecciones aprendidas
No todo salió bien a la primera. La más instructiva: en uno de los nodos, todo parecía funcionar. DNSSEC pasaba las pruebas, las respuestas llegaban rápido y Unbound reportaba métricas normales. Pero al comprobar la resolución con dnscheck.tools, los resultados no correspondían a nuestra arquitectura recursiva.
El motivo era resolvconf: estaba inyectando automáticamente los DNS del proveedor de hosting como forwarders de Unbound, sin que apareciera como una forward-zone escrita en nuestra configuración principal de Unbound. Unbound seguía validando DNSSEC y devolviendo respuestas correctas, pero estaba reenviando parte de las consultas en lugar de resolverlas de forma recursiva.
La solución fue desactivar esa integración:
printf 'USE_RESOLVCONF_FORWARDS=false\n' > /etc/default/unbound
Y comprobar, nodo por nodo, que Unbound quedaba sin forwarders dinámicos:
unbound-control list_forwards
Si la salida no está vacía y aparece una forward zone para ., ese nodo no está resolviendo de forma recursiva pura.
Otras lecciones más pequeñas pero igual de reales: las cachés frías después de un reinicio afectan a la latencia percibida durante minutos, no segundos. DNSSEC hay que comprobarlo por separado en cada backend, no asumir que si funciona en uno funciona en todos. Y añadir más nodos no siempre reduce la latencia si la caché no ha tenido tiempo de calentarse.
Estado actual
DNS1 funciona como nodo principal, apoyado por backends internos conectados por WireGuard. Todos los nodos resuelven de forma recursiva, validan DNSSEC y no dependen de forwarders externos accidentales. La arquitectura dnsdist → Unbound se mantiene estable desde la migración.
Sigue habiendo trabajo pendiente: afinar el filtrado, revisar métricas sin comprometer la privacidad, y mantener la documentación al día según vaya cambiando la infraestructura.
RocksDNS no está terminado, porque una infraestructura viva nunca lo está. Pero hoy es más simple, más clara y más nuestra que cuando empezó.
Si quieres probar RocksDNS, puedes consultar la web de RocksDNS y la guía introductoria de RocksDNS para configurarlo en tu sistema.
Si valoras proyectos así
Donación
Para mantener los servidores en marcha y seguir ofreciendo servicios libres y sin anuncios.
Hacer una donaciónCamisetas
Camisetas y productos TuiterRocks en La Tostadora. Llevas el mapache contigo y apoyas el proyecto.
Ver camisetasApoyo gratuito
Comparte, recomienda y ayuda a otras personas a descubrir alternativas al DNS de siempre.
TuiterRocks
Una instancia de Mastodon en español, pequeña a propósito, con registro abierto.
Crear cuenta