Por qué es conveniente usar NSEC3 en vez de NSEC en un dominio DNSSEC

Para empezar con los principios básicos, puedes leer Introducción a DNSSEC.

Gracias a DNSSEC un atacante malicioso no podrá manipular un registro DNS porque su firma digital RRSIG no puede ser falsificada. Pero, ¿puede falsificar la no existencia de un registro? Es decir, ¿puede negar falsamente que un registro DNS dado no exista?.

La respuesta es que no. Cuando DNSSEC gestiona una zona, añade multitud de registros propios. Los más evidentes son las firmas digitales RRSIG, pero hay más. Por ejemplo, los registros NSEC.

Los registros NSEC proporcionan authenticated denial of existence. Es decir, una prueba criptográfica de que un registro DNS no existe.

Su funcionamiento se describe en el RFC 4034 y el RFC 4035. Simplificando mucho, DNSSEC ordena todos los registros de la zona de forma canónica y genera registros NSEC para cubrir los huecos.

Por ejemplo, si una zona tiene los registros registro1 y registro3, pero NO registro2, una petición de DNS de registro2 se responderá indicando que el registro no existe y, además, aportará una prueba criptográfica de ello. Dicha prueba consiste en el registro NSEC asociado al nombre registro1 en el campo authority de la respuesta DNS, indicando que el siguiente nombre de la zona es registro3.

Es decir, el registro NSEC recibido prueba criptográficamente, fuera de toda duda, que entre registro1 y registro3 no hay nada. Veamos un ejemplo:

registro1.z.bt.jcea.es. 26      IN      NSEC    registro3.z.bt.jcea.es. A RRSIG NSEC
registro1.z.bt.jcea.es. 26      IN      RRSIG   NSEC 8 5 30 20170620042725 ...

Este es un ejemplo real de mi servidor DNS. Aquí el NSEC certifica dos cosas:

  1. Que entre registro1 y registro3 no hay nada. Prueba por tanto que registro2 no existe.

  2. Que el nombre registro1 contiene registros A (dirección IPv4), RRSIG y NSEC.

    Con ello sabremos, por ejemplo, que un atacante no ha eliminado la respuesta AAAA (dirección IPv6) de registro1, aunque puede haber eliminado algunas respuestas A si las hubiera, siempre que haya dejado alguna de las originales.

Por supuesto, el registro NSEC lleva su propia firma digital RRSIG.

Una vez que entendemos el funcionamiento y la utilidad de los registros NSEC, veremos también su problema: La enumeración de la zona.

Efectivamente, un atacante podría hacer lo siguiente de forma trivial:

  1. Preguntar por un nombre DNS que es canónicamente anterior a cualquier nombre "normal". El servidor DNS, si está usando DNSSEC con NSEC, nos dirá que dicho nombre no existe y, para probarlo, nos dará un registro NSEC a través del cual aprendemos cuál es el primer nombre canónico de la zona.
  2. Nos guardamos dicho nombre, generamos un nombre DNS nuevo inmediatamente superior canónicamente al nombre que acabamos de aprender y volvemos a hacer una consulta DNS.
  3. Si hemos acertado de casualidad con un nombre que existe, saltamos al punto 2.
  4. Si el nombre no existe, lo normal, el servidor DNS nos dará amablemente otro NSEC con el siguiente nombre válido. Saltamos al punto 2.

De esta manera sencilla y con unas pocas peticiones DNS, podemos obtener el listado de toda la zona. Obsérvese que no solo obtenemos el listado de nombres, sino que también podemos saber qué tipos de registro DNS existen y hacer las peticiones correspondientes para obtener sus valores.

Funcionalmente esto es equivalente a permitir transferencias de zona hacia máquinas arbitrarias de Internet. Típicamente no querremos que esto se pueda hacer.

Tres años más tarde apareció el RFC 5155, definiendo un nuevo tipo de registro DNSSEC: NSEC3.

Los registros NSEC3 solucionan dos problemas diferentes: la enumeración de zonas que permite NSEC y la posibilidad de excluir de DNSSEC delegaciones de dominios que, a su vez, no tienen DNSSEC. Olvidémonos de ese segundo caso, que no nos interesa ahora mismo.

NSEC3 funciona de forma muy similar a NSEC pero evita la enumeración de zona haciendo que la cadena formada por los registros NSEC3 enlacen hashes criptográficos de los nombres humanos.

Cuando requerimos un registro DNS que no existe, nos llega un NSEC3 conteniendo dos hashes. Esos dos hashes definen un rango para el que se garantiza que no existe nigún nombre DNS en la zona cuyo hash esté en medio de esos dos. El verificador tendría que calcular el hash del nombre DNS solicitado y comprobaría que, efectivamente, ese hash está en el rango indicado por la respuesta NSEC3 y, por tanto, ese nombre verdaderamente no existe.

Funcionalmente es similar a NSEC, pero en vez de ordenar los nombres DNS de forma canónica, lo que ordena son sus hashes.

Para evitar ataques de diccionario, cada dominio bajo DNSSEC NSEC3 define otro registro DNS adicional llamado NSEC3PARAM. Ese registro indica el algoritmo de hash a utilizar, el número de iteraciones y la sal a emplear. De esta forma un ataque de diccionario no se puede reutilizar en otros dominios y el coste en sí es ajustable en función del número de iteraciones especificado.

Un ejemplo de la misma zona de antes transformada a NSEC3 podría ser:

51PKTFM618079E60H7F0Q6IF0VT6P0D1.z.bt.jcea.es. 30 IN NSEC3 1 0 10 673A6224876B0486 OEPHDNT06U7U9UURA3UAPV240OVO88SP A RRSIG
51PKTFM618079E60H7F0Q6IF0VT6P0D1.z.bt.jcea.es. 30 IN RRSIG NSEC3 8 5 30 20170620071663 ...

Como vemos, la respuesta es similar al caso NSEC, pero ahora la cadena indica el rango de hashes cubierto por la respuesta NSEC3.