Transferencia segura de zonas con TSIG

Introducción

TSIG (Transaction SIGnature, RFC 2845) es un método para firmar las transacciones y mensajes de DNS mediante el uso de claves simétricas (secretas) compartidas. Esto incluye los mensajes de consulta recursiva, notificación o consultas dig, aunque TSIG suele utilizarse sobre todo para proteger la transferencia de zonas de un dominio entre un servidor de DNS primario y su(s) secundario(s). TSIG opera con cifrado simétrico, es decir, los servidores implicados en la transacción comparten una misma clave. Esto nos permitirá restringir quién puede transferir las zonas DNS entre servidores. Es el caso que aplicaremos en este documento.

Estrictamente hablando, TSIG no es parte de DNSSEC, pero asegurar la comunicación entre los DNS autoritativos suele ser un paso previo a asegurar las zonas con DNSSEC. Conviene saber que TSIG no cifra los datos en tránsito. Su firma digital preserva la integridad de las comunicaciones maestro-esclavo, no la confidencialidad, ya que los datos de una zona son esencialmente públicos pero, si se requiere confidencialidad, se debe configurar una VPN.

Software utilizado

  • Un servidor DNS primario (hostname: foo; IP: 5.6.7.8): OpenBSD 5.3 y BIND 9.4.2-P2
  • Un servidor DNS secundario (hostname: bar; IP: 1.2.3.4): OpenBSD 5.3 y NSD 3.2.15

Para elaborar este documento se ha empleado un servidor DNS primario sobre OpenBSD 5.3, sin ningún paquete externo (secure by default), con BIND auditado y parcheado por el equipo de desarrollo de OpenBSD. Por su parte, el servidor DNS secundario se basa también en OpenBSD 5.3 pero con NSD3 (forma parte también del sistema base de OpenBSD) en lugar del problemático (y demasiado ubicuo) bind9. Sin embargo, todo lo que se explica a continuación es independiente del sistema operativo y puede aplicarse en cualquier sistema de tipo Unix. Los servidores de nombres bind9 y nsd3 suelen estar disponibles mediante paquetes externos en cualquier otra plataforma de tipo Unix/Linux.

Configuración de TSIG

Para configurar TSIG es recomendable crear una clave por cada servidor esclavo. De esa forma, si un servidor esclavo se ve comprometido, solo será necesario reemplazar la clave almacenada en ese host.

Creación de la clave

Para crear la clave TSIG usaremos dnssec-keygen(8), una utilidad incluida con bind9 para generar claves DNSSEC:

dnssec-keygen -a HMAC-SHA256 -b 112 -n HOST keyname
  • HMAC-SHA256 es el algoritmo utilizado para el cifrado.
  • 112 es la longitud de la clave (o el número de bits). La actual recomendación de NIST es usar HMAC-SHA256, con 112 bits.
  • HOST: HOST es la palabra clave utilizada para generar una clave para un cifrado de clave simétrico. Por convención, se suele usar como nombre de clave el nombre de host de ambos servidores ('foo' y 'bar' en este ejemplo), finalizado en un punto.

En nuestro caso:

$ dnssec-keygen -a HMAC-SHA256 -b 112 -n HOST foo-bar.
Kfoo-bar.+163+14005

163 identifica el algoritmo utilizado (HMAC_SHA256) y 14005 es la huella (útil en DNNSEC porque se permiten varias claves por zona).

Si recibimos un error al usar el algoritmo HMAC-SHA256 (private key is invalid) deberemos actualizar nuestra versión de bind9, evitando así tener que usar algoritmos débiles como HMAC-MD5.

El comando anterior nos creará dos pequeños ficheros de texto, uno con extensión .key y otro .private:

Kfoo-bar.+163+14005.key  
Kfoo-bar.+163+14005.private

El fichero .key contiene un registro DNS KEY que puede usarse en un fichero de zona. El fichero con extensión .private es el que nos interesa para nuestro caso: incluye información del algoritmo y la clave que necesitamos (aunque el fichero .key contendrá igualmente la clave secreta). Este es su contenido:

$ cat Kfoo-bar.+163+14005.private 
Private-key-format: v1.3
Algorithm: 163 (HMAC_SHA256)
Key: 6f5p3ntxg81bTgkpeX4=
Bits: AAA=
Created: 20130514083805
Publish: 20130514083805
Activate: 20130514083805

La línea Key: contiene la clave secreta (“6f5p3ntxg81bTgkpeX4=” en este ejemplo), que por supuesto deberemos proteger y guardar a buen recaudo y que usaremos para configurar bind9, nsd o el servidor DNS de nuestra elección con soporte TSIG. No es necesario copiar el fichero completo, basta con copiar la línea con la clave a nuestro fichero de configuración en nuestro servidor primario y secundario, como se explica a continuación.

Configurar servidor DNS primario

Ahora que ya tenemos la clave, debemos incluirla tanto en la configuración del servidor DNS primario como en el secundario. Empezamos con el primario, editamos named.conf (bind9):

key foo-bar. {
  algorithm hmac-sha256;
  secret "6f5p3ntxg81bTgkpeX4=";
};

Ahora debemos especificar que nuestro secundario (1.2.3.4) usará la clave foo-bar.:

server 1.2.3.4 {
  keys {foo-bar. ;};
};

Permitimos la transferencia solo a cada zona que posea la clave (asociada como acabamos de ver a la IP del secundario):

allow-transfer {
      key foo-bar.;
};

Por ejemplo:

zone "example.com" {
    type            master;
    file            "master/db.example.com";
    allow-transfer {
        key foo-bar.;
    };
};

Es una doble seguridad: no basta con conocer la clave, sino que debe proceder de la IP declarada para el secundario.

Configurar servidor DNS secundario

La configuración del servidor secundario también deberemos modificarla. En nuestro caso, usaremos NSD3 (un servidor de nombres autoritativo incluido en el sistema base de OpenBSD pero disponible en cualquier otro sistema de tipo Unix), mucho más ligero, seguro y moderno que bind9. Editamos /etc/nsd.conf:

## TSIG key 
key:
        name: "foo-bar."
        algorithm: hmac-sha256
        secret "6f5p3ntxg81bTgkpeX4="

## slave zones
# example.com zone
zone:
        name: "example.com"
        zonefile: "slave/example.com"
        # the master is allowed to notify and will provide zone data.
        allow-notify: 5.6.7.8 foo-bar.
        request-xfr: 5.6.7.8 foo-bar.

Si preferimos usar bind9 en el secundario, tendríamos que editar named.conf, como hicimos con el primario, y añadir lo siguiente:

/* TSIG Signature */
key "foo-bar." {
        algorithm hmac-sha256;
        secret "6f5p3ntxg81bTgkpeX4=";
};
/* Master server IP */
server 5.6.7.8 {
        keys { foo-bar.; };
};

Recargamos la configuración de los servidores DNS (reload o restart), y ya deberían comunicarse con TSIG entre ellos.

Comprobación

Para comprobar que la conexión TSIG funciona, modificamos un registro de zona en el primario (por ejemplo, cambiamos su número de serie). Al recargar el servidor (rndc reload), el maestro debería notificar al secundario que ha habido cambios e inmediatamente el esclavo debe intentar transferir la zona. Si TSIG está correctamente configurado deberíamos ver en los logs del primario algo parecido a esto:

May 14 10:48:26 foo named[18123]: zone example.com/IN: loaded serial 2013051401
May 14 10:48:26 foo named[18123]: zone example.com/IN: sending notifies (serial 2013051401)
May 14 10:48:26 foo named[18123]: client 1.2.3.4#57028: transfer of 'example.com/IN': AXFR-style IXFR   started: TSIG foo-bar
May 14 10:48:26 foo named[18123]: client 1.2.3.4#57028: transfer of 'example.com/IN': AXFR-style IXFR ended

Y en el secundario:

[1368521223] nsd[3508]: info: Zone example.com serial 2013051301 is updated to 2013051401.

Si algo ha ido mal, obtendremos mensajes “denied” en los logs. Deberemos revisar los ficheros de configuración (named.conf o nsd.conf), pues lo más probable es que hayamos cometido alguna errata.

Conclusión

Habitualmente, en los servidores DNS se utiliza el control de acceso basado en IP para controlar las actualizaciones y transferencias de zona entre ellos, pero hoy día esto resulta claramente insuficiente. TSIG añade una capa de seguridad que permite preservar la integridad de los datos y evita que alguien no autorizado (sin clave TSIG) inicie una transferencia de zona entre el servidor primario y el (o los) secundario(s). Ahora las transferencias de nuestras zonas entre servidores autoritativos han quedado restringidas a aquellos que posean una clave.

Referencias

es/security/dns/tsig.txt · Last modified: 2013/05/16 00:42 by mvidal
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC0 1.0 Universal
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki