Admin Libre - Administración de sistemas y redes

DNSSEC con nsd y ldns
Por Francisco Gaitán el 14 de Noviembre de 2022

DNSSEC es una extensión de seguridad sobre el sistema de nombres de dominio diseñada para evitar que el usuario reciba datos alterados al consultar una zona DNS. Queda definida en los siguientes RFCs:

  • RFC 4033: Introducción y requisitos para la seguridad de DNS
  • RFC 4034: Registros de recursos para las extensiones de seguridad de DNS
  • RFC 4035: Modificaciones de protocolo para las extensiones de seguridad de DNS

Estos RFCs son de especial interés a la hora de configurar DNSSEC:

  • RFC 4641: Prácticas operacionales para DNSSEC
  • RFC 7583: Consideraciones para sincronizar la renovación de llaves DNSSEC

Basándome en el artículo DNSSEC with NLnetLabs' LDNS and NSD voy a configurar DNSSEC para mi dominio que denominaré example.com en este artículo. Esta no pretende ser una guía exhaustiva sobre implementación de DNSSEC sino unas breves notas que sirvan de referencia.

Utilizaré la herramienta ldns-signzone que se encuentra en el paquete ldns-utils para firmar la zona y nsd para servirla.

Configuración de DNSSEC para un nombre de dominio

Estos son los pasos que he dado para configurar DNSSEC. Parto del dominio example.com registrado en Porkbun con su zona configurada y servida por un servidor OpenBSD con nsd y con el paquete ldns-utils para firmar la zona y al menos un servidor secundario.

  1. Generar llave para el dominio example.com
  2. Firmar y verificar la zona
  3. Configurar y recargar nsd para la nueva zona firmada
  4. Añadir el registro DS en el registrador
  5. Añadir el registro DNSKEY en el registrador
  6. Comprobar que funciona

Generar llave para el dominio example.com

A día de hoy el algoritmo recomendado es ECDSA Curve P-256 con SHA-256 definido en el RFC 6605, el cual corresponde al número 13 en ldns. El parámetro -k indica que el registro DNSKEY contiene la llave KSK.

$ ldns-keygen -a13 -k example.com 
Kexample.com.+013+14834

Se han creado tres archivos:

  • Kexample.com.+013+14834.ds contiene el registro de recurso DS definido en la sección 5 del RFC 4034.
  • Kexample.com.+013+14834.key contiene la clave pública que más tarde se podrá consultar a través del registro DNSKEY
  • Kexample.com.+013+14834.private contiene la clave privada que hay que proteger bien

Firmar y verificar la zona

Para firmar la zona se especifica solamente la primera parte del nombre de los archivos generados, sin la parte de la extensión correspondiente a .ds, .key o .private. Usaré esta configuración:

  • -n para usar registros NSEC3 en vez de NSEC (diferencias entre ambos)
  • -u para usar el serial de la zona como el número de segundos desde el 1 de Enero de 1970
  • -o example.com para especificar el origen de la zona
$ ldns-signzone -n -u -o example.com example.com Kexample.com.+013+14834

Una vez hecho esto verifico la zona firmada para comprobar que todo esté correcto:

$ ldns-verify-zone -V4 example.com.signed
Zone is verified and complete

Por defecto las claves expiran a los 30 días, aunque se puede especificar más duración con el parámetro -e. Antes de que caduquen es necesario actualizar la zona incrementando el serial, firmarla de nuevo y recargarla.

Configurar y recargar nsd para la zona firmada

Si no hay ningún problema cambio la configuración de nsd.conf para especificar el archivo firmado, que quedaría algo así:

[...]
zone:
	name: "example.com"
	zonefile: "master/example.com.signed"
	[...]
[...]

Hago lo mismo para los servidores secundarios:

[...]
zone:
	name: "example.com"
	zonefile: "slave/example.com.signed"
	[...]
[...]

Una vez hecho el cambio recargo la configuración de nsd tanto en el servidor maestro como en los esclavos. En OpenBSD sería así:

$ doas rcctl reload nsd

Añadir el registro DS en el registrador

Una vez se haya propagado la zona firmada y pase el tiempo TTL el siguiente paso es subir a la zona padre los datos del registro DS a través del registrador de dominios. Los datos se encuentran en el archivo con extensión .ds que generado anteriormente:

example.com. IN      DS      14834 13 2 8b6c6df9335d3d41bedb294e125a57d1457bae532f2b854e12a9297d7994fcae

Este proceso depende del registrador y del registro. Para los dominios .com y .org en Porkbun funciona simplemente añadiendo el registro DS a la configuración DNSSEC:

  • Key Tag: 14834
  • DS Data Algorithm: 13
  • Digest Type: 2
  • Digest: 8b6c6df9335d3d41bedb294e125a57d1457bae532f2b854e12a9297d7994fcae

Añadir el registro DNSKEY al registrador

Para dominios .eu en Porkbun es necesario subir el registro DNSKEY en lugar del DS. Los datos están en el fichero .key (ojo, nunca la clave privada de extensión .private).

example.com. IN      DNSKEY  257 3 13 vF9wHxJYN57Lr+CCPfCHLCpuJBUCaFkBSyF/hySHnphcizIKjFrp1oXl4jA1pVwc0m9A1nPDsJugreVu/4wfGw== ;{id = 1553 (ksk), size = 256b}

Estos serían los campos para el registro DNSKEY o keyData:

  • Flags: 257
  • Protocol: 3
  • Key Data Algorithm: 13
  • Public Key (lo muestro acortado): vF9wHxJY...cizIKjFrp1oXfGw==

Si no funciona es posible que haya que subir los datos del registro DS y DNSKEY a la vez.

Comprobar que funciona

Una vez añadido el registro compruebo que el dominio resuelve:

$ dig +short +dnssec example.com 
203.0.113.1
A 13 2 3600 20221212180833 20221114180833 14834 example.com. O9xZhZ8C7qLsW9jfWqpeLHeMv39XFKKCDLUffrVK3EPuWuuIBS5QqbvD p8CIsP+9RaFbEq57V6crNJYYaX7YQw==

Al hacer whois se reflejará que el dominio usa DNSSEC:

DNSSEC: signedDelegation
DNSSEC DS Data: 14834 13 2 8B6C6DF9335D3D41BEDB294E125A57D1457BAE532F2B854E12A9297D7994FCAE

Para comprobar la configuración puedes usar dnsviz.net.

Mantenimiento de las zonas

Cada zona firmada tiene asignadas dos fechas que aparecen en el registro RRSIG:

  • Una de comienzo referida como inception
  • Una de vencimiento referida como expiration

El resultado de la consulta será válido si ésta se realiza en una fecha entre ambas. Para evitar problemas de resolución desde sistemas con reloj inexacto el programa ldns-signzone por defecto establece la fecha de comienzo una hora antes de la hora actual.

Para mantener la validez de las zonas hay que incrementar el número de serie de la zona sin firmar para a continuación firmarla de nuevo y publicarla mediante nsd-control o recargando nsd antes de su fecha de vencimiento. Como la validez de la firma tiene la duración de un mes y continuamente va rotando la hora, firmando los días 1 y 15 de cada mes te aseguras de que todas las zonas se mantengan actualizadas, aunque también es posible aumentar el tiempo de validez con la opción -e de ldns-signzone y eitime.

Tal y como explica su autor en el artículo, para firmar una zona con una validez de 180 días y haciendo ceros la parte correspondiente a horas, minutos y segundos se usarían estos parámetros:

$ ldns-signzone -e $(eitime -z 180) -n -u -o example.com example.com Kexample.com.+013+14834

Para cambiar la llave de forma correcta lee DNSSEC Key Rollover con el método de doble KSK.

Destacado

Contacto

Si has encontrado algún error o quieres comentarme algo mándame un correo a webmaster@adminlibre.org