DNSSEC falla aleatoriamente: depurar errores de validación sin pánico

¿Te fue útil?

Son las 02:13. La mitad de tu flota puede alcanzar una API de socio; la otra mitad obtiene SERVFAIL. Alguien dice “el DNS está caído”. Otro dice “es DNSSEC”. Te dan ganas de reiniciar un resolver y cruzar los dedos para que nadie lo note.

No lo hagas. Los fallos “aleatorios” de DNSSEC suelen ser deterministas. Solo parecen aleatorios porque distintos resolvers, rutas, caches, MTU, relojes y estados de claves producen resultados diferentes. Esta es una guía de campo para convertir el pánico en una lista corta de comprobaciones, con comandos que puedes ejecutar mientras el canal de incidentes aún discute de quién fue el cambio.

Qué significa realmente “falla aleatoria de DNSSEC”

La validación DNSSEC es una operación sí/no: o la cadena de confianza valida para el RRset en el momento en que la pides, o no. Entonces, ¿por qué parece intermitente?

  • Diferentes resolvers ven datos diferentes. El estado de la caché, el caché negativo, NSEC agresivo y el prefetch hacen que dos resolvers puedan estar “correctos” y aun así discrepen durante minutos.
  • Diferentes rutas tratan el UDP grande de forma distinta. Las respuestas DNSSEC son más grandes. EDNS0 aumenta el tamaño de la carga UDP; algunas redes descartan fragmentos o bloquean ICMP “Fragmentation needed”. Resultado: un cliente reintenta por TCP, otro no.
  • El tiempo importa. RRSIG tiene inicio/expiración. Un desfase de reloj en el validador puede convertir firmas válidas en “expiradas” o “aún no válidas”.
  • Diferentes estados del ancla de confianza. Los anclajes administrados y el comportamiento RFC 5011 pueden provocar “funciona aquí, falla allí” durante cambios de claves o tras una larga interrupción.
  • Diferencias aguas arriba. Si tus resolvers reenvían a distintos upstreams (o auto-descubren), puedes estar comparando manzanas con una naranja que además está en llamas.

El objetivo es dejar de tratarlo como un fantasma. Vas a acotar: qué resolver falla, para qué nombre/tipo, con qué estado DNSSEC y por qué.

Hechos e historia que importan en la práctica

Aquí hay puntos concretos que no son trivia—cambian cómo depuras:

  1. Las especificaciones centrales de DNSSEC llegaron en 2005 (RFC 4033/4034/4035). Mucha herramienta “DNS legado” es anterior y omite detalles importantes.
  2. La zona raíz se firmó en 2010. Antes de eso, la validación paraba en la raíz; después, las fallas pueden propagarse globalmente si la cadena se rompe.
  3. Los cambios de algoritmo son eventos reales, no teoría. Las digests DS basadas en SHA-1 (y algoritmos antiguos) se han ido retirando; las discrepancias suelen aparecer durante transiciones.
  4. DNSKEY y DS no son lo mismo. DS está en el padre; DNSKEY en el hijo. Si cambias claves sin actualizar DS, los validadores marcarán tu zona como “bogus”.
  5. Las respuestas DNS grandes fueron históricamente frágiles. DNS empezó con respuestas UDP de 512 bytes; DNSSEC hizo comunes las “respuestas grandes”, de ahí EDNS0 y más fallback a TCP.
  6. NSEC3 se introdujo para reducir el zone-walking. También aumenta la complejidad y el tamaño de las respuestas; lo verás en pruebas de existencia negativa.
  7. Algunos resolvers cachean decisiones “bogus” por un tiempo breve. Eso puede hacer que una mala configuración corta parezca más larga, y es por qué “lo arreglamos pero sigue fallando” sucede.
  8. Hubo un gran rollover del KSK raíz en 2018. Enseñó a todos que la “gestión de anclas de confianza” es trabajo operativo, no una casilla para marcar.

Una cita para mantenerte honesto, porque los incidentes castigan el pensamiento optimista:

“La esperanza no es una estrategia.” — General Gordon R. Sullivan

Guion rápido de diagnóstico

Cuando los usuarios dicen “DNSSEC es inestable”, necesitas un bucle cerrado. Aquí tienes el orden que encuentra el cuello de botella más rápido en sistemas reales.

1) Confirma que es validación DNSSEC (no DNS simple)

  • Elige un cliente que falle y uno que funcione conocido.
  • Consulta la misma IP de resolver directamente (no te fíes de los search de /etc/resolv.conf ni del DNS dividido).
  • Compara AD (Authenticated Data), RA, y el código de respuesta real (NOERROR, SERVFAIL, NXDOMAIN).

2) Identifica el validador que falla y aíslalo

  • Si ejecutas un pool de resolvers, comprueba uno por uno. Intermitente suele significar “subconjunto”.
  • Si reenvías a resolvers aguas arriba, evita el reenvío temporalmente (o prueba recursión directa) para localizar dónde rompe la validación.

3) Verifica la cadena: DS en el padre, DNSKEY en el hijo, firmas válidas “ahora”

  • Usa delv o drill -D para forzar un trazo de validación completo.
  • Busca mismatch de DS, RRSIG faltantes, firmas expiradas o algoritmo no soportado.

4) Comprueba MTU / fragmentación / fallback a TCP

  • Busca patrones de udp truncated, aumento de consultas TCP, o timeouts solo en algunas redes.
  • Prueba con tamaños EDNS reducidos para reproducir el fallo.

5) Comprueba tiempo y anclas de confianza

  • El desfase de reloj en validadores es un asesino silencioso.
  • Anclas de confianza raíz obsoletas aparecen tras largas caídas o imágenes congeladas.

Regla de decisión: si la misma consulta al mismo resolver cambia entre AD y SERVFAIL sin cambios en la zona, sospecha primero de la ruta de red/fragmentación o de un resolver sobrecargado, no de criptografía.

Modelo mental: dónde puede fallar la validación DNSSEC

Piénsalo en capas. DNSSEC no es una sola cosa; son varias dependencias alineadas, cualquiera de las cuales puede fallar de maneras que se parecen entre sí.

Layer A: Transporte (UDP/TCP, EDNS0, fragmentación)

DNSSEC suele aumentar el tamaño de la respuesta: conjuntos DNSKEY, registros DS, RRSIGs, pruebas NSEC/NSEC3. Si los paquetes UDP se fragmentan y se pierden fragmentos, el resolver puede no ensamblar la respuesta, reintentar o marcar al upstream como “lame”.

Layer B: Integridad de los datos (firmas y cadena de confianza)

La validación requiere un camino desde un ancla de confianza (normalmente la raíz) a través de DS y DNSKEY hasta el RRset que solicitaste. Rompe el enlace DS, publica firmas malas o deja que las firmas expiren, y un validador debe devolver SERVFAIL (o “bogus” internamente). Ese es el objetivo del mecanismo.

Layer C: Tiempo (ventanas de validez de RRSIG)

La vigencia/inicio de RRSIG no es indulgente. Un validador con reloj equivocado puede invalidar zonas perfectamente buenas. Este es uno de los pocos problemas de DNS que realmente se arreglan con NTP, no con argumentos.

Layer D: Comportamiento del validador (cacheo, RFC 5011, NSEC agresivo)

Los resolvers no son idénticos. Unbound, BIND, PowerDNS Recursor y otros difieren en valores por defecto: con qué agresividad cachean, cómo manejan prefetch, cómo registran fallas de validación y cómo gestionan anclas de confianza. Si operas una flota mixta, también operas un conjunto mixto de modos de falla.

Broma #1: DNSSEC es como el control de seguridad del aeropuerto: mejora la seguridad, pero te hará quitarte los zapatos en el peor momento posible.

Tareas prácticas: comandos, salidas, decisiones

La forma más rápida de depurar DNSSEC es recopilar “pruebas”, no sensaciones. Abajo hay tareas reales que puedes ejecutar en un cliente, en un resolver, o en ambos. Cada una tiene: un comando, qué significa la salida típica, y qué decisión tomas después.

Task 1: Comprueba si el resolver está validando (flag AD)

cr0x@server:~$ dig @192.0.2.53 www.cloudflare.com A +dnssec +multi

; <<>> DiG 9.18.24 <<>> @192.0.2.53 www.cloudflare.com A +dnssec +multi
; (1 server found)
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1122
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
www.cloudflare.com.  300 IN A 104.16.132.229
www.cloudflare.com.  300 IN RRSIG A 13 3 300 20260101000000 20251201000000 34505 cloudflare.com. ...

;; Query time: 21 msec
;; SERVER: 192.0.2.53#53(192.0.2.53) (UDP)

Significado: ad indica que el resolver validó la respuesta. La presencia de RRSIG muestra que se solicitó información DNSSEC.

Decisión: Si el caso que falla carece de ad o devuelve SERVFAIL, sigue investigando. Si devuelve NOERROR sin ad, el resolver puede no validar o estar configurado para eliminar AD.

Task 2: Confirma que el fallo es SERVFAIL por validación, no por timeout aguas arriba

cr0x@server:~$ dig @192.0.2.53 broken.dnssec-failed.org A +dnssec +comments

;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 44110
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

Significado: SERVFAIL es ambiguo por sí mismo. La clave es correlacionarlo con los logs del resolver (tareas abajo) y probar con una herramienta validante (delv).

Decisión: Si varios nombres no relacionados devuelven SERVFAIL, sospecha de la salud del resolver o de conectividad. Si solo una zona, sospecha de los datos DNSSEC de la zona o de problemas MTU en las respuestas de esa zona.

Task 3: Usa delv para obtener una explicación de validación (prueba local)

cr0x@server:~$ delv @192.0.2.53 example.com A

; fully validated
example.com.  300 IN A 93.184.216.34

Significado: “fully validated” significa que el resolver proporcionó suficientes datos y la validación tuvo éxito.

Decisión: Si delv dice “resolution failed” o “bogus”, trátalo como DNSSEC hasta que se pruebe lo contrario y pasa a inspeccionar la cadena.

Task 4: Haz que delv muestre por qué es bogus

cr0x@server:~$ delv @192.0.2.53 bad.example A +rtrace

...
; validation failure <bad.example/A>: no valid RRSIG
; resolution failed: SERVFAIL

Significado: Esto te dice la categoría: firma faltante/ inválida, mismatch de DS, algoritmo no soportado, etc.

Decisión: “no valid RRSIG” suele significar firma rota, firmas expiradas, o que la respuesta fue truncada/descartada y el resolver no recibió las firmas.

Task 5: Compara el comportamiento con DNSSEC deshabilitado en la consulta (test de control)

cr0x@server:~$ dig @192.0.2.53 example.com A +nodnssec +multi

; <<>> DiG 9.18.24 <<>> @192.0.2.53 example.com A +nodnssec +multi
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5881
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
example.com.  300 IN A 93.184.216.34

Significado: Si +nodnssec funciona pero +dnssec falla, está implicado el tamaño/validación DNSSEC. Si ambos fallan, es DNS simple o transporte.

Decisión: Usa esto para calmar a las partes interesadas: “DNS funciona, falla la validación DNSSEC” es un problema más acotado que “DNS está roto”.

Task 6: Inspecciona DS en el padre (la prueba “¿el padre apunta correctamente?”)

cr0x@server:~$ dig @192.0.2.53 example.com DS +dnssec +multi

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19981
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
example.com.  86400 IN DS 370 13 2 9F3E...C1A7
example.com.  86400 IN RRSIG DS 8 2 86400 20260101000000 20251201000000 12345 com. ...

Significado: El padre publica DS. La digest y el key tag deben coincidir con un DNSKEY en la zona hija. ad aquí es una buena señal: la cadena del padre está bien hasta este punto.

Decisión: Si DS falta, la zona es “insegura” (no firmada desde la perspectiva del padre). Si DS existe pero no coincide con DNSKEY del hijo, obtendrás bogus.

Task 7: Inspecciona DNSKEY en el hijo (la prueba “¿el hijo publica la clave correcta?”)

cr0x@server:~$ dig @192.0.2.53 example.com DNSKEY +dnssec +multi

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5022
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
example.com.  3600 IN DNSKEY 257 3 13 mGx...==
example.com.  3600 IN DNSKEY 256 3 13 tZk...==
example.com.  3600 IN RRSIG DNSKEY 13 2 3600 20260101000000 20251201000000 370 example.com. ...

Significado: Normalmente verás una KSK (flag 257) y una o más ZSK (flag 256). Deben estar firmadas, y las firmas deben validar.

Decisión: Si las consultas DNSKEY están expirando o truncadas, probablemente tienes problemas MTU/fragmentación. Si DNSKEY existe pero no se alinea con DS, es un problema de rollover DS.

Task 8: Fuerza TCP para descartar fragmentación UDP

cr0x@server:~$ dig @192.0.2.53 example.com DNSKEY +dnssec +tcp

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61001
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; Query time: 37 msec
;; SERVER: 192.0.2.53#53(192.0.2.53) (TCP)

Significado: Si TCP funciona de forma fiable mientras UDP falla intermitentemente, tu problema “aleatorio” probablemente sea fragmentación de paquetes, comportamiento del firewall, o PMTUD roto.

Decisión: Mitiga bajando el tamaño EDNS UDP en el resolver, permitiendo DNS sobre TCP/853 correctamente, o arreglando la ruta de red que descarta fragmentos/ICMP.

Task 9: Restringe el tamaño EDNS para reproducir fallos por “respuesta grande”

cr0x@server:~$ dig @192.0.2.53 example.com DNSKEY +dnssec +bufsize=1232

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4555
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232

Significado: 1232 es un tamaño EDNS seguro común para evitar fragmentación en rutas típicas. Si bajar el bufsize hace desaparecer los fallos, has aprendido algo útil sobre tu red.

Decisión: Configura el resolver con un tamaño EDNS conservador si operas en redes hostiles (VPNs, overlays, Wi‑Fi de hoteles, ciertos firewalls empresariales).

Task 10: Revisa los logs del resolver para errores explícitos de validación (Unbound)

cr0x@server:~$ sudo journalctl -u unbound --since "10 min ago" | tail -n 30
Dec 31 01:59:12 resolver-a unbound[912]: info: validation failure <example.com. DNSKEY IN>: signature expired
Dec 31 01:59:12 resolver-a unbound[912]: info: resolving example.com. DNSKEY IN
Dec 31 01:59:13 resolver-a unbound[912]: info: error: SERVFAIL example.com. A IN

Significado: Eso no es “aleatorio”. Es “firma expirada”, lo que suele significar que el operador de la zona no re-firmó a tiempo, o tu reloj está mal.

Decisión: Revisa la hora local primero (tarea 12). Si la hora está bien, escala al propietario de la zona con evidencia.

Task 11: Revisa los logs del resolver para errores de validación (BIND named)

cr0x@server:~$ sudo journalctl -u named --since "10 min ago" | tail -n 40
Dec 31 02:01:22 resolver-b named[1044]: resolver: info: validating example.com/A: no valid signature found
Dec 31 02:01:22 resolver-b named[1044]: resolver: info: DNSKEY example.com is not secure
Dec 31 02:01:22 resolver-b named[1044]: resolver: info: client @0x7f... 198.51.100.27#51622 (example.com): query failed (SERVFAIL) for example.com/IN/A at query.c:...

Significado: “No valid signature found” suele correlacionar con mismatch de DS, RRSIG faltante, o una respuesta truncada donde el resolver nunca recibió las firmas necesarias.

Decisión: Prueba inmediatamente con +tcp y +bufsize=1232 para ver si es por transporte. Si no, inspecciona la alineación DS/DNSKEY.

Task 12: Confirma que los relojes están bien (desfase del validador)

cr0x@server:~$ timedatectl
               Local time: Wed 2025-12-31 02:06:41 UTC
           Universal time: Wed 2025-12-31 02:06:41 UTC
                 RTC time: Wed 2025-12-31 02:06:41
                Time zone: UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Significado: La validación DNSSEC depende del tiempo correcto. Si System clock synchronized es “no”, estás en zona de peligro.

Decisión: Arregla NTP/sincronización de tiempo antes de tocar las configuraciones de DNS. Si la hora del host está mal, cualquier otra conclusión es sospechosa.

Task 13: Detecta un problema de ancla de confianza (problemas con la clave raíz) con la utilidad de Unbound

cr0x@server:~$ sudo unbound-anchor -a /var/lib/unbound/root.key
/var/lib/unbound/root.key has content
success: the anchor is ok

Significado: Esto comprueba si el archivo del ancla raíz configurado está presente y es razonable.

Decisión: Si esto falla solo en algunos resolvers, probablemente tengas deriva de imagen o un appliance obsoleto. Actualiza anclas de confianza de forma controlada.

Task 14: Comprueba si estás reenviando (y por tanto heredando el comportamiento DNSSEC de otro)

cr0x@server:~$ sudo unbound-control list_forwards
zone=.
forward-addr=203.0.113.9@53
forward-addr=203.0.113.10@53

Significado: No estás haciendo recursión completa; confías en forwarders upstream. Si ellos validan de forma distinta, filtran EDNS o rompen el fallback a TCP, tus resultados variarán.

Decisión: Para depuración, prueba recursión directa desde un resolver (temporalmente en un laboratorio o instancia aislada) para ver si el problema es tuyo o aguas arriba.

Task 15: Verifica que tu resolver realmente intente validación DNSSEC

cr0x@server:~$ sudo unbound-control get_option val-permissive-mode
val-permissive-mode: no

Significado: El modo permisivo puede convertir fallos duros en suaves. Excelente para mitigación de emergencia; terrible para expectativas de seguridad y claridad en la depuración.

Decisión: Mantén el modo permisivo apagado en operación normal. Si está activado durante un incidente, documenta, limita su tiempo y planifica la reversión.

Task 16: Mide la mezcla UDP vs TCP de consultas (señal de transporte)

cr0x@server:~$ sudo unbound-control stats_noreset | egrep 'num.query.tcp|num.query.udp|num.answer.rcode.SERVFAIL'
num.query.udp=1849921
num.query.tcp=219004
num.answer.rcode.SERVFAIL=3812

Significado: Un pico repentino en consultas TCP puede indicar problemas de fragmentación UDP o truncamiento deliberado. Un pico en SERVFAIL correlacionado con zonas específicas apunta a problemas de cadena DNSSEC.

Decisión: Si la proporción TCP sube durante la misma ventana que los fallos, mira red/MTU. Si SERVFAIL sube sin cambios en TCP, mira errores de validación y anclas de confianza.

Task 17: Prueba MTU y comportamiento de fragmentación (rápido y sucio)

cr0x@server:~$ ping -M do -s 1472 198.51.100.53 -c 3
PING 198.51.100.53 (198.51.100.53) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1480
ping: local error: message too long, mtu=1480
ping: local error: message too long, mtu=1480

--- 198.51.100.53 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2041ms

Significado: Existen restricciones de MTU en la ruta. DNS sobre UDP con grandes payloads EDNS ahora es sospechoso. Además: esto no prueba que los fragmentos DNS se descarten, pero es un fuerte indicio.

Decisión: Reduce el tamaño EDNS UDP en el resolver, asegura que el fallback a TCP funcione, y arregla el manejo de ICMP cuando sea posible.

Task 18: Confirma que los servidores autoritativos son alcanzables y consistentes

cr0x@server:~$ dig @ns1.example.net example.com DNSKEY +dnssec +norec
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3101
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

Significado: aa confirma una respuesta autoritativa. Si un servidor autoritativo da un DNSKEY/RRSIG diferente a otro, puedes tener problemas de propagación, signadores en split-brain o una clave parcialmente desplegada.

Decisión: Consulta cada nameserver autoritativo directamente. Datos DNSSEC inconsistentes entre servidores autoritativos son una causa de alta confianza para fallos “aleatorios”.

Broma #2: Depurar DNSSEC es cuando aprendes la diferencia entre “sistema distribuido” y “culpa distribuida”.

Errores comunes: síntoma → causa raíz → solución

Esta es la parte donde dejamos de fingir que siempre es “Internet” y nombramos a los sospechosos habituales.

1) Algunos clientes obtienen SERVFAIL, otros tienen éxito

  • Síntoma: Fallos intermitentes correlacionados con oficina/VPN/región; los reintentos a veces funcionan.
  • Causa raíz: Caídas de fragmentación UDP, PMTUD roto, o un firewall que estropea EDNS0. Las respuestas DNSSEC son grandes; la ruta no es amable.
  • Solución: Reduce el tamaño EDNS UDP en los resolvers (a menudo 1232), asegúrate de que TCP/53 esté permitido y arregla el manejo de ICMP en la ruta. Valida con dig +tcp y dig +bufsize=1232.

2) Todo funcionó hasta un rollover de claves, luego “rompió aleatoriamente”

  • Síntoma: Una zona estable ahora es intermitentemente bogus; algunos resolvers se recuperan más rápido que otros.
  • Causa raíz: El registro DS en el padre no coincide con la KSK activa en el hijo; o un autoritativo todavía sirve DNSKEY/RRSIG antiguos.
  • Solución: Verifica DS en el padre y DNSKEY en el hijo. Asegura que todos los autoritativos sirvan los mismos datos firmados. Repite correctamente los pasos de rollover; no “simplemente quites DNSSEC” a menos que disfrutes llamadas de clientes.

3) Los fallos comienzan tras “endurecer” la red

  • Síntoma: DNS va bien para registros pequeños; las consultas DNSKEY hacen timeout; TCP/53 bloqueado.
  • Causa raíz: Firewall bloquea fragmentos, bloquea TCP/53, o rate-limea patrones “UDP desconocido”, accidentalmente DoSeando DNSSEC.
  • Solución: Permite TCP/53 a los resolvers, permite el retorno de fragmentos o ajusta el tamaño EDNS hacia abajo. Confirma con estadísticas: aumento de fallback TCP, truncamiento o timeouts.

4) Fallas de validación aparecen solo en un subconjunto de resolvers

  • Síntoma: Resolver A valida; Resolver B devuelve SERVFAIL para la misma consulta.
  • Causa raíz: Diferentes anclas de confianza, root.key obsoleto, desfase de reloj, forwarders distintos, o versiones/defaults de resolver distintas.
  • Solución: Estandariza la configuración de resolvers y la gestión de anclas de confianza. Revisa la sincronización de tiempo. Compara unbound-anchor, versiones y settings de reenvío.

5) NXDOMAIN se convierte en SERVFAIL bajo DNSSEC

  • Síntoma: Un nombre inexistente debería ser NXDOMAIN pero llega SERVFAIL en resolvers validantes.
  • Causa raíz: Pruebas de inexistencia rotas (NSEC/NSEC3) o RRSIGs faltantes sobre NSEC/NSEC3.
  • Solución: Valida con delv +rtrace. Arregla el firmado autoritativo para NSEC/NSEC3, asegura parámetros correctos y confirma que todos los auth servers sirvan registros de denegación consistentes.

6) “Funciona con resolvers públicos pero no con los nuestros”

  • Síntoma: Resolvers públicos validan bien; tus resolvers internos fallan.
  • Causa raíz: Tus resolvers reenvían a un upstream que elimina DNSSEC, altera EDNS o bloquea fallback TCP; o tu red interna descarta fragmentos.
  • Solución: Prueba recursión directa (sin reenvío) en un resolver. Compara buffer EDNS, comportamiento TCP y logs.

Tres mini-historias corporativas desde las trincheras

Mini-historia 1: El incidente causado por una suposición equivocada

La Empresa A ejecutaba una capa de resolvers ordenada: dos VIP anycast por región, Unbound detrás de ellas, y una política de reenvío “sencilla” a un servicio DNS de terceros para “mejorar el hit rate de caché”. DNSSEC estaba habilitado porque su equipo de seguridad tenía una casilla trimestral que requería las palabras “validación DNSSEC”.

Un socio rotó sus claves DNSSEC. Nada inusual, solo higiene rutinaria. En una hora, un puñado de pods de aplicaciones en una región empezaron a fallar en handshakes TLS porque no podían resolver el hostname de un OCSP responder. El canal de incidentes se puso ruidoso.

El ingeniero on-call supuso: “Si Internet público lo resuelve, nuestros resolvers deben estar rotos.” Esa suposición estaba al revés. Los resolvers públicos no reenviaban al mismo upstream, no estaban detrás del mismo firewall y no sufrían el mismo manejo de EDNS.

Resultó que su forwarder upstream también hacía validación—pero con una política distinta. Devolvía SERVFAIL para zonas durante una ventana de transición de DS que su setup interno hubiera manejado si hiciera recursión completa. Los resolvers internos eran inocentes; estaban retransmitiendo obedientemente la falla upstream.

La solución fue poco glamorosa: deshabilitar temporalmente el reenvío para la zona afectada (reenvío basado en política), hacer recursión directa y los fallos cesaron. Luego rediseñaron: o reenvías y aceptas el comportamiento upstream, o haces recursión y te haces cargo de la validación. Mezclar ambos sin expectativas explícitas es cómo te hacen sonar las páginas.

Mini-historia 2: La optimización que salió mal

La Empresa B tenía una red global con “optimizadores WAN” que pretendían ayudar. Alguien notó que el tráfico DNS era “ruidoso” y decidió “optimizarlo”. El equipo de WAN desplegó una política que depriorizaba fragments UDP durante congestión porque “la fragmentación suele ser basura”.

No explotó de inmediato. La mayoría de respuestas DNS eran pequeñas. Pero una vez que DNSSEC se volvió común en su ecosistema de proveedores, DNSKEY y algunos registros TXT firmados empezaron a fragmentarse. Los optimizadores no descartaban todos los fragmentos—solo los suficientes para hacerlo intermitente bajo carga. Perfecto: un bug que se reproduce mejor cuando estás más ocupado.

Lo que lo empeoró fue el comportamiento de fallback. Algunos resolvers reintentaban por TCP rápidamente; algunos clientes tenían timeouts cortos; algunos middleboxes trataban TCP/53 como sospechoso. Los usuarios reportaron “fallos DNS aleatorios”, y la primera reacción fue añadir más resolvers.

Añadir resolvers cambió el comportamiento de caché y la distribución de consultas, lo que alteró ligeramente tamaños y tiempos de paquete. También complicó los gráficos del incidente. La optimización había fracasado dos veces: causó el problema y luego lo disfrazó.

La resolución final fue establecer un tamaño EDNS UDP conservador y ajustar la política WAN para dejar de tratar fragments como descartables. No fue heroico. Fue admitir que DNSSEC hizo del “UDP grande” un ciudadano de primera clase, te guste o no.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

La Empresa C no hacía nada sofisticado. Ejecutaban resolvers BIND con una línea base estricta de configuración, NTP en todas partes, gestión de configuración con detección de deriva y un resolver canario por región. También tenían un hábito: cada día, trabajos automatizados ejecutaban delv contra un pequeño conjunto de dominios externos críticos y algunas zonas internas firmadas.

Un martes, una actualización de DS por parte del registrador para una zona gestionada por un cliente salió mal. La zona seguía firmada, pero el DS en el padre ya no coincidía con la KSK en el hijo. Eso significa: los resolvers validantes deben fallar. Los resolvers no validantes seguirían resolviendo felizmente, lo que produce la experiencia de usuario de split-brain.

El trabajo canario diario lo detectó en minutos tras el cambio. No porque la compañía fuera psíquica—porque medían el estado de validación como una señal SLO de primera clase. Su on-call tenía un playbook, los logs estaban centralizados y la evidencia ya estaba en el ticket.

Notificaron al registrador, revirtieron el DS y el incidente nunca se convirtió en una caída a gran escala. La práctica aburrida no fue “experticia DNSSEC”. Fue repetir una pequeña prueba de validación cada día para que un mal día parezca un patrón conocido, no un horror novedoso.

Listas de verificación / plan paso a paso

Paso a paso: aislar si esto es datos de zona, configuración del resolver o la red

  1. Elige un solo nombre y tipo de registro que falle. Escríbelo. No depures “DNS” en general.
  2. Consulta el mismo resolver directamente desde un host que falla. Usa dig @IP e incluye +dnssec.
  3. Repite desde un host conocido bueno. Si los resultados difieren, tienes diferencias de ruta o selección de resolver.
  4. Prueba +tcp. Si TCP lo arregla, estás viendo problemas UDP/EDNS/fragmentación.
  5. Prueba +bufsize=1232. Si eso lo arregla, tu ruta de red es hostil a UDP grande.
  6. Ejecuta delv +rtrace para obtener la razón. Es más rápido que adivinar.
  7. Revisa los logs del resolver por razones de “bogus”. Firma expirada, mismatch DS, algoritmo no soportado, etc.
  8. Valida la sincronización de tiempo en el resolver. Si el tiempo está mal, detente y arréglalo.
  9. Consulta DS del padre y DNSKEY del hijo. Asegúrate de que coincidan y sean consistentes entre servidores autoritativos.
  10. Decide propiedad.
    • Si mismatch DS/DNSKEY: problema del propietario de la zona/registrador.
    • Si solo algunos resolvers fallan: deriva de flota/tiempo/anclas de confianza.
    • Si TCP funciona y UDP no: ruta de red/EDNS sizing.

Checklist: qué capturar para una escalación (para que se solucione)

  • FQDN que falla y tipo de registro (A/AAAA/TXT/DNSKEY/DS).
  • IP(s) del resolver probadas y si hay reenvío involucrado.
  • Salida de dig con +dnssec y con +tcp.
  • Salida de delv +rtrace que muestre la razón (firma expirada, mismatch DS, etc.).
  • Sello temporal y zona horaria/estado del reloj de tu resolver.
  • Qué servidores autoritativos fueron consultados directamente y si las respuestas diferían.

Preguntas frecuentes

1) ¿Por qué la falla DNSSEC aparece como SERVFAIL en lugar de un mensaje más claro?

Porque DNS es un protocolo diseñado para minimalismo y cacheo. Los validadores generalmente no filtran errores detallados de validación a los clientes. El resolver sabe “bogus”, el cliente ve “SERVFAIL”. Usa los logs del resolver y delv para la explicación.

2) ¿Cuál es la forma más rápida de demostrar que es mismatch DS/DNSKEY?

Consulta DS en el padre y DNSKEY en el hijo, luego ejecuta delv +rtrace. Si la digest DS no coincide con ningún DNSKEY, los validadores fallarán de forma consistente una vez que las cachés converjan.

3) ¿Puedo simplemente deshabilitar la validación DNSSEC durante un incidente?

Puedes, pero hazlo como una quema controlada: limita el tiempo, documenta y entiende lo que sacrificas. Una mejor mitigación de emergencia suele ser bajar el tamaño EDNS UDP o asegurar que TCP/53 esté permitido—arreglar el transporte sin quitar la validación.

4) ¿Por qué los resolvers públicos tienen éxito mientras los nuestros fallan?

Diferentes implementaciones de resolver, diferentes estados de ancla de confianza, diferentes rutas de red y diferentes políticas. Los resolvers públicos pueden tener mejor alcance anycast, fallback TCP más tolerante, o simplemente no estar detrás de tus reglas de firewall.

5) ¿Qué significa realmente la bandera AD?

AD (Authenticated Data) la establece un resolver validador cuando cree que los datos están validados. Puede ser eliminada o no establecida según la configuración. Trátala como una señal, no como un evangelio, y confirma con delv cuando importe.

6) ¿Es “malo para el rendimiento” bajar el tamaño EDNS UDP?

A veces incrementa el fallback a TCP, lo que puede añadir latencia. Pero una respuesta un poco más lenta gana a una falla aleatoria. Para muchas rutas empresariales, un tamaño EDNS conservador es la elección práctica.

7) ¿Cómo puede la deriva de tiempo causar fallos solo intermitentes?

Porque las ventanas de validez de RRSIG son basadas en tiempo, y distintos RRsets tienen firmas con tiempos distintos. Además, caches y reintentos pueden enmascararlo hasta que la firma de un registro específico cruce el umbral del desfase del validador.

8) ¿Cuál es la diferencia entre “insecure” y “bogus”?

Insecure significa que no hay cadena de confianza (no hay DS en el padre). El resolver puede responder sin validación. Bogus significa que se espera cadena pero falla (firmas malas, DS/DNSKEY desalineados, etc.). Bogus debe fallar de manera cerrada.

9) ¿Realmente importan tanto las flotas de resolvers mixtas?

Sí. Los valores por defecto difieren: comportamiento de cacheo, gestión de anclas de confianza, fallback TCP y registro. Si quieres comportamiento predecible, estandariza o al menos documenta las diferencias y prueba ambos caminos.

Conclusión: próximos pasos que puedes entregar esta semana

DNSSEC no falla aleatoriamente. Tu sistema hace una buena imitación de la aleatoriedad cuando distintos resolvers, caches, relojes y redes discrepan.

Haz lo siguiente:

  1. Implementa el guion rápido de diagnóstico. Ponlo en tu runbook on-call y haz “dig +dnssec, dig +tcp, delv +rtrace” memoria muscular.
  2. Estandariza las bases de los resolvers. Misma versión, mismo manejo de anclas, misma política de EDNS, mismo nivel de logs durante incidentes.
  3. Elige un tamaño EDNS UDP conservador si operas en redes desordenadas. Luego mide la proporción TCP para conocer el coste.
  4. Monitorea resultados de validación. Rastrea SERVFAIL por zona, no solo el total. Ejecuta canarios diarios de validación de dominios críticos.
  5. Ponerse serio con el tiempo. Si ejecutas validadores, ejecutas relojes. Haz que la deriva de NTP sea una alerta, no una nota al pie.
← Anterior
Clústeres y HA en Proxmox: cómo funciona, qué falla y cómo diseñarlo correctamente
Siguiente →
HBM en CPUs: Cuando la memoria entra en el paquete

Deja un comentario