Saltar al contenido
ecdsa.com
← Todos los artículos

Cadena de confianza DNSSEC: DS, DNSKEY, RRSIG y qué falla

Un resolvedor validador confía en una sola clave, la de la raíz, y sigue punteros firmados hasta la respuesta. Cada caída de DNSSEC es un eslabón roto de esa cadena. Esta página recorre una cadena real con dig y delv y después rompe una a propósito en un laboratorio para mostrar qué aspecto tiene cada error.

Respuesta breve. DNSSEC enlaza las zonas con dos tipos de registro. Un registro DS en la zona padre contiene un hash de la clave de firma de claves de la zona hija (DNSKEY, indicadores 257). Esa clave firma el conjunto DNSKEY de la zona hija, y la clave de firma de zona (indicadores 256) firma los registros propiamente dichos con firmas RRSIG. Un resolvedor validador parte de la clave raíz en la que confía y comprueba cada eslabón hasta la respuesta. Si falla cualquiera de ellos, devuelve SERVFAIL en lugar de los datos. Comprueba una cadena con delv («fully validated») o con dig +dnssec (el indicador ad), compara el DS de la zona padre con la DNSKEY de la zona hija mediante dnssec-dsfromkey y usa +cd para ver si los datos están ahí pero no superan la validación. La mayoría de las caídas se deben a rotaciones de claves (key rollovers): un DS que no se actualizó tras cambiar la KSK, firmas que se dejaron caducar o claves cambiadas más deprisa de lo que caducan las cachés.

Los cuatro registros

RegistroDónde estáQué contiene
DNSKEYEn la propia zonaClaves públicas. Los indicadores 257 marcan una clave de firma de claves (KSK, con el bit «SEP» activado) y 256, una clave de firma de zona (ZSK)
RRSIGJunto a cada conjunto de registros firmadoUna firma de una clave sobre un conjunto de registros (RRset), con la fecha de inicio, la fecha de caducidad y la etiqueta de la clave de firma
DSEn la zona padre, en la delegaciónUn resumen de una de las DNSKEY de la zona hija: etiqueta de clave, algoritmo, tipo de resumen y resumen
NSEC / NSEC3En la zonaPrueba firmada de que un nombre o un tipo no existe

El diseño reparte las claves por función. La KSK firma solo el RRset DNSKEY, y su hash está en la zona padre. Cambiarla implica tratar con la zona padre (el registrador o el registro). La ZSK firma todo lo demás y se puede cambiar sin que intervenga la zona padre. Una zona también puede usar una única clave combinada (CSK) para ambas funciones, que es lo que hace default, la política dnssec-policy integrada en BIND (csk ... algorithm 13). Las reglas son las mismas; la clave simplemente tiene los indicadores 257 y lo firma todo.

Recorrido de una cadena real con dig

www.isc.org, paso a paso, el 20 de octubre de 2026 (dig de BIND 9.20.10, consultas enviadas a 1.1.1.1). Primero, la raíz. Su conjunto DNSKEY tiene una ZSK y dos KSK:

dig . DNSKEY +multiline (abreviado)
.			2158 IN	DNSKEY 256 3 8 (
) ; ZSK; alg = RSASHA256 ; key id = 8763
.			2158 IN	DNSKEY 257 3 8 (
) ; KSK; alg = RSASHA256 ; key id = 20326
.			2158 IN	DNSKEY 257 3 8 (
) ; KSK; alg = RSASHA256 ; key id = 38696

La clave 20326 es KSK-2017 y la 38696 es KSK-2024. La rotación de la KSK raíz tuvo lugar nueve días antes de esta captura. En palabras de la ICANN: «El 11 de octubre de 2026 a las 14:00 UTC, KSK-2024 empezó a firmar la zona raíz del DNS según lo previsto». Lo confirma la firma sobre el conjunto DNSKEY de la raíz:

dig . DNSKEY +dnssec: la firma sobre el conjunto de claves de la raíz
.			1587 IN	RRSIG DNSKEY 8 0 172800 (
20261101000000 20261011000000 38696 .

Es la única RRSIG sobre ese conjunto. La clave antigua sigue publicada hasta su revocación prevista, pero ya no firma. Un resolvedor que solo confía en KSK-2017, porque nunca conoció KSK-2024 mediante las actualizaciones automáticas de RFC 5011 ni con una actualización del software, ya no puede validar nada.

Después, cada delegación. El DS de la zona padre identifica la KSK de la zona hija por su etiqueta de clave:

dig org. DS, dig org. DNSKEY, dig isc.org. DS, dig isc.org. DNSKEY (abreviado)
org.			81000	IN	DS	26974 8 2 4FEDE294C53F438A158C41D39489CD78A86BEB0D8A0AEAFF14745C0D 16E1DE32
) ; ZSK; alg = RSASHA256 ; key id = 25488
) ; ZSK; alg = RSASHA256 ; key id = 11859
) ; ZSK; alg = RSASHA256 ; key id = 24060
) ; KSK; alg = RSASHA256 ; key id = 725
) ; KSK; alg = RSASHA256 ; key id = 26974
isc.org.		3600	IN	DS	7250 13 2 A30B3F78B6DDE9A4A9A2AD0C805518B4F49EC62E7D3F4531D33DE697 CDA01CB2
) ; ZSK; alg = ECDSAP256SHA256 ; key id = 27566
) ; KSK; alg = ECDSAP256SHA256 ; key id = 7250

El DS de la raíz para org. apunta a la clave 26974, que org. publica como KSK. El DS de isc.org. en org. apunta a la clave 7250, la KSK de isc.org. Fíjate en el cambio de algoritmo al bajar: org. firma con RSA (algoritmo 8) e isc.org, con ECDSA P-256 (algoritmo 13). Cada zona elige el suyo. Por último, la respuesta y su firma con la ZSK de isc.org, la 27566:

dig www.isc.org. A +dnssec +multiline
www.isc.org.		300 IN A 151.101.3.42
www.isc.org.		300 IN A 151.101.67.42
www.isc.org.		300 IN A 151.101.131.42
www.isc.org.		300 IN A 151.101.195.42
www.isc.org.		300 IN RRSIG A 13 3 300 (
				20261103074926 20261020065242 27566 isc.org.
				qz5Qb4BFyOw4PRXBJjeK61LrPSKo6G2Ma1aFwNwZ57x5
				bFIg/d3EoMHtXopLYU949QQtMjcQ8BWULk7a629tLA== )

Los campos de la RRSIG son: tipo cubierto A, algoritmo 13, 3 etiquetas, TTL original 300, caducidad 2026-11-03 07:49:26 UTC, inicio 2026-10-20 06:52:42 UTC, etiqueta de clave 27566 y firmante isc.org.. Un resolvedor validador que comprueba todo esto activa el indicador AD (authenticated data, datos autenticados):

dig www.isc.org A +dnssec @1.1.1.1
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

ad es una afirmación del resolvedor, y solo es tan fiable como el camino hasta él. Para validar por tu cuenta, usa delv, que hace todo el recorrido en local con sus anclas de confianza raíz integradas. +rtrace muestra cada petición:

delv @1.1.1.1 www.isc.org A +rtrace (BIND 9.20.10, abreviado)
;; fetch: www.isc.org/A
;; fetch: isc.org/DNSKEY
;; fetch: isc.org/DS
;; fetch: org/DNSKEY
;; fetch: org/DS
;; fetch: ./DNSKEY
; fully validated

dig +sigchase, que recomiendan las guías antiguas, ya no existe: dig 9.20 responde dig: +sigchase option no longer supported. Usa delv. Para hacer el mismo recorrido en el navegador mediante DNS-over-HTTPS, el inspector de DNSSEC obtiene cada eslabón, verifica cada RRSIG con su propio código y señala el eslabón que se rompe.

Algoritmos 8, 13 y 15

El número de algoritmo aparece en los registros DNSKEY, DS y RRSIG. RFC 9904 (noviembre de 2025) sustituyó a RFC 8624 y trasladó las recomendaciones al propio registro de la IANA; RFC 9905, publicado junto con él, prohíbe firmar con los dos algoritmos basados en SHA-1:

NúmeroAlgoritmoFirmaValidación
5, 7RSA/SHA-1Prohibido (MUST NOT)Implementación obligatoria; los operadores de resolvedores lo tratan como no admitido
8RSA/SHA-256Recomendado, implementación obligatoriaImplementación obligatoria
10RSA/SHA-512No recomendadoImplementación obligatoria
13ECDSA P-256/SHA-256Recomendado, implementación obligatoriaImplementación obligatoria
14ECDSA P-384/SHA-384OpcionalRecomendado
15Ed25519RecomendadoRecomendado
16Ed448OpcionalRecomendado

Para los resúmenes DS, el que hay que usar es SHA-256 (tipo 2). SHA-1 (tipo 1) es «MUST NOT» (no debe usarse) para las delegaciones, aunque los validadores todavía tienen que admitirlo. De las diez zonas que comprobamos el 20 de octubre de 2026, com., net., nl., cloudflare.com, isc.org, ietf.org, nic.cz y sidn.nl firman con 13, mientras que org. y de. usan 8, igual que la raíz. Firmar la misma zona con cada algoritmo muestra por qué el 13 es tan popular:

dnssec-keygen / dnssec-signzone 9.20.29: una zona, tres algoritmos
algorithm 8  RSASHA256         ZSK public key 260 bytes, RRSIG signature 256 bytes
algorithm 13 ECDSAP256SHA256   ZSK public key  64 bytes, RRSIG signature  64 bytes
algorithm 15 ED25519           ZSK public key  32 bytes, RRSIG signature  64 bytes

Las firmas pequeñas mantienen las respuestas por debajo del límite de tamaño de UDP (1232 bytes es el búfer EDNS habitual hoy en día), lo que evita la fragmentación y el paso a TCP. El algoritmo 15 tiene las claves más pequeñas, pero su compatibilidad en los validadores es RECOMMENDED (recomendada), no MUST (obligatoria), así que comprueba los resolvedores de tu audiencia antes de elegirlo.

Romper una cadena a propósito

Para ver los fallos sin romper un dominio real, el laboratorio siguiente ejecuta dos instancias de BIND 9.20.29 en Debian 13. Una es un servidor autoritativo para una raíz privada ., para lab. y para shop.lab., todas firmadas con el algoritmo 13. La otra es un resolvedor validador cuya única ancla de confianza es el DS de esa raíz privada. Los pasos de claves y de firma usan las herramientas habituales de BIND:

Extracto del laboratorio: claves, firma y el ancla de confianza del resolvedor
keygen() { dnssec-keygen -q -K keys -a ECDSAP256SHA256 -L 3600 "$@"; }
for z in . lab shop.lab; do keygen -fKSK "$z" >/dev/null; keygen "$z" >/dev/null; done

# the parent includes the child's dsset file before signing
cat auth/db.lab.unsigned auth/dsset-shop.lab. > auth/db.lab
dnssec-signzone -q -S -K keys -d auth -o lab -f auth/db.lab.signed auth/db.lab

read -r _ _ _ tag alg dt d1 d2 < auth/dsset-.
echo "trust-anchors { . static-ds $tag $alg $dt \"$d1$d2\"; };" > anchors.conf

1. Todo correcto. El DS en lab. identifica la KSK de shop.lab., el resolvedor activa ad y delv valida:

Laboratorio, caso 1
DS in lab.: shop.lab. 48794 13 2
DNSKEY in shop.lab.: ZSK; alg = ECDSAP256SHA256 ; key id = 6251
DNSKEY in shop.lab.: KSK; alg = ECDSAP256SHA256 ; key id = 48794
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
www.shop.lab.		5	IN	A	192.0.2.10
$ delv @127.0.0.2 -a anchors.conf www.shop.lab A
; fully validated
www.shop.lab.		5	IN	A	192.0.2.10

2. KSK sustituida en la zona hija, DS sin actualizar en la zona padre. Es la caída clásica tras un cambio de proveedor de alojamiento DNS o una rotación automática de la KSK que nadie completó en el registrador:

Laboratorio, caso 2
DS in lab.: shop.lab. 48794 13 2
DNSKEY in shop.lab.: KSK; alg = ECDSAP256SHA256 ; key id = 11943
DNSKEY in shop.lab.: ZSK; alg = ECDSAP256SHA256 ; key id = 6251
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
$ dig @127.0.0.1 www.shop.lab A +dnssec +cd
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
www.shop.lab.		5	IN	A	192.0.2.10
$ delv @127.0.0.2 -a anchors.conf www.shop.lab A
;; validating shop.lab/DNSKEY: no valid signature found (DS)
;; broken trust chain resolving 'www.shop.lab/A/IN': 127.0.0.2#53
;; resolution failed: broken trust chain

El DS sigue diciendo 48794, y la zona tiene ahora la KSK 11943. +cd (checking disabled, comprobación desactivada) devuelve los datos, lo que demuestra que la zona funciona y que solo falla la validación. Es la forma más rápida de distinguir un fallo de DNSSEC de una caída del servicio.

3. Firmas caducadas. El DS está corregido, pero la zona se firmó una vez y nunca se volvió a firmar. Aquí el laboratorio la firma con un inicio de hace diez días y una caducidad de hace una hora:

Laboratorio, caso 3
RRSIG inception 20261010131152 expiration 20261020121152
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
; EDE: 7 (Signature Expired): (shop.lab/DNSKEY)
$ delv @127.0.0.2 -a anchors.conf www.shop.lab A
;; validating shop.lab/DNSKEY: no valid signature found (DS)
;; broken trust chain resolving 'www.shop.lab/A/IN': 127.0.0.2#53
;; resolution failed: broken trust chain

BIND adjunta un error DNS extendido (Extended DNS Error, RFC 8914) que indica la causa: EDE: 7 (Signature Expired). La firma estática con dnssec-signzone genera por defecto firmas de 30 días (en la primera firma del laboratorio, el inicio fue 20261020120639 y la caducidad, 20261119120639), así que una tarea de cron que dejó de volver a firmar provoca exactamente esto un mes después. En su lugar, deja que el servidor DNS firme y vuelva a firmar automáticamente: dnssec-policy en BIND, cuya configuración por defecto renueva firmas de 14 días cada 5 días, o su equivalente en Knot o PowerDNS.

4. ZSK cambiada en un solo paso. La zona sustituye su ZSK y vuelve a firmarlo todo con la clave nueva de inmediato. Un resolvedor que tenía en caché el conjunto DNSKEY antiguo (TTL 3600) recibe un registro A firmado por una clave que no tiene:

Laboratorio, caso 4
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
www.shop.lab.		5	IN	A	192.0.2.10
resolver cache: DNSKEY flags 256 TTL 3600
resolver cache: DNSKEY flags 257 TTL 3600
(6 s later: the A record's 5 s TTL has expired, the cached DNSKEY set's 3600 s TTL has not)
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
(resolver restarted, cache empty)
$ dig @127.0.0.1 www.shop.lab A +dnssec
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
www.shop.lab.		5	IN	A	192.0.2.10

La zona en sí es válida: un resolvedor recién iniciado la valida. Pero cada resolvedor que guardó en caché el conjunto de claves antiguo falla hasta que esa entrada de la caché caduca. La caída es intermitente y depende del resolvedor: el tipo más difícil de depurar.

Rotaciones de claves que no rompen nada

RFC 6781 describe las secuencias seguras. La regla que hay detrás de todas ellas es que cada resolvedor debe poder validar con cualquier combinación de registros antiguos y nuevos que tenga en caché.

  • ZSK, prepublicación (pre-publish). Añade la nueva ZSK al conjunto DNSKEY mientras la antigua sigue firmando. Espera al menos el TTL de DNSKEY, para que todas las cachés tengan ambas claves. Pasa a firmar con la clave nueva. Espera el TTL más largo de los datos firmados para que las firmas antiguas desaparezcan de las cachés. Después, elimina la clave antigua.
  • KSK, doble firma (double-signature). Añade la nueva KSK y firma el conjunto DNSKEY con ambas. Envía el nuevo DS a la zona padre. Espera a que la zona padre lo publique y a que el DS antiguo haya caducado en las cachés (el TTL del DS, a menudo una hora o un día). Solo entonces elimina la KSK antigua.
  • Rotación de algoritmo (por ejemplo, de 8 a 13). Las claves nuevas del nuevo algoritmo deben firmarlo todo antes de que aparezca el nuevo DS, y el algoritmo antiguo debe seguir firmando hasta que desaparezca el DS antiguo. RFC 6781 §4.1.4 recoge la secuencia completa.
  • Automatiza el lado de la zona padre. Los registros CDS y CDNSKEY (RFC 8078) permiten que una zona padre compatible recoja el nuevo DS de la zona hija. Sin esa automatización, el paso del DS es manual en el registrador, y ahí es donde se atascan las rotaciones.
  • Cambio de proveedor de DNS. O haces una migración coordinada con varios firmantes (multi-signer), o primero eliminas el DS en el registrador, esperas su TTL y vuelves a activar DNSSEC con la clave del nuevo proveedor. Cambiar los registros NS mientras sigue el DS antiguo es el caso 2 en producción.

La dnssec-policy de BIND y los gestores de claves de Knot y PowerDNS aplican estos tiempos por ti. El fallo habitual no está en la herramienta, sino en el paso de la zona padre: un DS que hay que pegar en el formulario web de un registrador.

Diagnóstico de un SERVFAIL

  1. ¿Es DNSSEC? dig name +cd devuelve datos mientras que dig name da SERVFAIL → fallo de validación. Busca una línea EDE: 6 (DNSSEC Bogus), 7 (Signature Expired), 8 (Signature Not Yet Valid), 9 (DNSKEY Missing), 10 (RRSIGs Missing).
  2. ¿Qué eslabón? Ejecuta delv name +rtrace y lee el primer paso que falla.
  3. DS frente a DNSKEY: calcula el DS a partir de las claves de la zona hija y compáralo con el de la zona padre:
DS en la zona padre frente al DS calculado a partir de la DNSKEY de la zona hija (bind9-utils 9.20.29)
$ dig +short DS isc.org @1.1.1.1
7250 13 2 A30B3F78B6DDE9A4A9A2AD0C805518B4F49EC62E7D3F4531D33DE697 CDA01CB2
$ dig +cd +noall +answer DNSKEY isc.org @1.1.1.1 | dnssec-dsfromkey -2 -f - isc.org
isc.org. IN DS 7250 13 2 A30B3F78B6DDE9A4A9A2AD0C805518B4F49EC62E7D3F4531D33DE697CDA01CB2
$ dig +short DS dnssec-failed.org @1.1.1.1
42069 13 2 62726F6B656E20636861696E206F662074727573742073656E642068 656C7021
$ dig +cd +noall +answer DNSKEY dnssec-failed.org @1.1.1.1 | dnssec-dsfromkey -2 -f - dnssec-failed.org
dnssec-failed.org. IN DS 50719 13 2 D602C971A02AF89B7661B99D6DD1B9E2EC876617631D04F633902A42CD4D6BBD

isc.org coincide. dnssec-failed.org es un dominio de prueba roto a propósito, servido por los servidores de nombres de Comcast (dns101.comcast.net y otros). Su DS identifica la clave 42069, que no existe, y el resumen es el texto ASCII «broken chain of trust send help!». En consecuencia, los resolvedores públicos lo rechazan:

dig @1.1.1.1 dnssec-failed.org A
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 59477
; EDE: 9 (DNSKEY Missing): (no SEP matching the DS found for dnssec-failed.org.)
  1. Fechas de la firma: compara el inicio y la caducidad de la RRSIG con la hora UTC actual. Un firmante o un validador con el reloj desajustado hace que la firma aparezca como «aún no válida» o «caducada».
  2. Los fallos que dependen del resolvedor tras un cambio de clave apuntan a las cachés (caso 4). Comprueba los TTL de los conjuntos DNSKEY y DS y la hora del cambio.

Qué permite DNSSEC

Una cadena de confianza que funciona es la base de los registros que necesitan autenticidad, no solo disponibilidad. DANE/TLSA fija claves TLS en el DNS y se usa para SMTP entre servidores de correo. El generador de registros TLSA crea esos registros. Las CA comprueban los registros CAA, y desde el 15 de marzo de 2026 los Baseline Requirements del CA/Browser Forum exigen validar con DNSSEC las consultas CAA cuando la zona está firmada. Por tanto, una cadena rota también puede bloquear la emisión de certificados.

Fuentes

Las consultas reales se ejecutaron el 20 de octubre de 2026 en nicolaka/netshoot:v0.14 (dig y delv de BIND 9.20.10). El laboratorio y dnssec-dsfromkey se ejecutaron en debian:trixie-20261005-slim con BIND 9.20.29 de Debian.