Taller DNS Recursivo

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 10

TALLER DNS RECURSIVO

¡Bienvenidos!

El formato de este taller consiste en que yo realizaré instalación y configuración


de un DNS recursivo, usando Bind, en un linux Ubuntu 20.04

Todos los pasos serán realizados en tiempo real conectado a una máquina virtual con
la instalación básica de paquete de Ubuntu.

Lo que verán en pantalla es mi consola, conectado por ssh a la máquina. Tendré un


sistema de múltiples consolas llamado tmux, que me permite tener varios comandos al
mismo tiempo. En la línea superior verán un indicador en qué consola virtual me
encuentro, y avisaré ante cualquier cambio.

Quedará disponible este guión escrito, incluyendo los comandos listos para copiar y pegar.

Comenzamos entonces.

Lo primero es instalar Bind 9. Utilizaremos el paquete predeterminado de nuestro sistema


operativo. Ubuntu tiene una versión bastante avanzada, y que es mantenida por gente de la
misma organización ISC.

Lo instalamos desde los repositorios oficiales:

$ sudo apt install bind9

Al finalizar, tendremos el servicio "bind9" listo para iniciar, con parámetros por defecto que
permiten una rápida configuración.

En el directorio /etc/bind/ tenemos el archivo de configuración más importante, named.conf.


La distribución Ubuntu separa la configuración en 3 archivos distintos, named.conf.options
con las instrucciones globales que se definen en la directiva options, named.conf.local
donde se definen las zonas locales, y named.conf.default-zones donde se encuentran
archivos de zonas que es buena idea tenerlas siempre activas, como localhost y sus
reversos.

Si miramos el named.conf.options, vemos que se define el directorio donde se guardarán


archivos de cache, está activa la validación dnssec y en modo automático, de forma que
Bind manejará automáticamente la rotación de llaves de la raíz, y la utilización de IPv6 para
dar el servicio.

1
Para demostrar el comportamiento sin validación, cambiaremos la directiva dnssec-
validation por no. Luego la volveremos a activar.

Activaremos la recursión, pero al mismo tiempo es muy importante definir qué IPs tendrán
acceso a esto. Definimos una lista de acceso:

$ cd /etc/bind
$ sudo vi named.conf.options

acl clientes {
127.0.0.0/16;
};

Y luego ya podemos activar recursión, autorizando esta red, y desactivamos validación:

$ sudo vi named.conf.options
dnssec-validation no;

recursion yes;
allow-query {
clientes;
};

Con estos cambios, iniciamos named y ya podemos comenzar a probar nuestro nuevo
recursivo

$ sudo systemctl start named

Luego de cada reinicio o reconfiguración, es conveniente estar mirando los archivos de logs.
En nuestro caso el comando siguiente nos muestra los relacionados a named:

$ sudo journalctl -u named

Se ve todo bien, podemos lanzar nuestra primera consulta recursiva, dando explícitamente
la opción +rec:

$ dig @localhost www.google.com a +rec

2
Nuestra primera consulta tarda un poco. En mi caso la obtuve en 716 milisegundos. Esto es
porque nuestro recursivo tiene el caché vacío, y tiene que comenzar la resolución desde la
raíz. Pero si consultamos de nuevo, vemos que obtenemos respuesta en 0 milisegundos!
Nuestro caché ya tiene esta respuesta y no tarda nada en responder.

Si miramos los logs, vemos algo extraño. Tenemos mensajes de error relacionados a IPv6.
Esto es porque lamentablemente nuestro sistema de virtualización no da soporte a
conectividad IPv6, pese a que el host sí lo tiene. Para mantener nuestros logs limpios,
podemos desactivar la conectividad IPv6 en nuestro recursivo. Esto se logra con la
siguiente configuración global:

$ sudo vi named.conf.options
server ::/0 { bogus yes; };

Ahora recargamos la configuración, repetimos la consulta, y vemos desaparecer los


mensajes de error:

$ sudo rndc reconfig

Es importante ir revisando que la recursión no esté abierta a clientes no autorizados. Si su


servidor es accesible por otras IPs fuera de las definidas en el ACL, es bueno revisar que
desde ahí no se obtenga recursión sino REFUSED. En nuestra prueba podemos simular
esto usando IPv6 localmente, ya que en nuestro ACL no permitimos el rango IPv6:

$ dig @::1 www.google.com a

Bind tiene soporte nativo para qname minimization. Por default se encuentra en un estado
"relajado", que es preferible en estos momentos frente a un modo estricto. Esto porque hay
muchos dominios con configuraciones incorrectas que hacen fallar qname-minimization a
menudo.

VALIDACIÓN DNSSEC

¿Recuerdan que desactivamos la validación dnssec? ¿Cómo podemos probarlo? Existe un


nombre que está explícitamente con firmas incorrectas, que sirve de prueba. Si consultamos
a nuestro resolver, ¿qué sucede?

3
$ dig @localhost www.dnssec-failed.org a

Como vemos, obtuvimos dos registros A de respuesta, con status NOERROR. Esto indica
que nuestro resolver pudo ubicar el nombre, pero no verificó las firmas. Corrijamos de
inmediato este error!

$ sudo vi named.conf.options
dnssec-validation auto;

Recargamos y volvemos a probar:

$ sudo rndc reconfig


$ dig @localhost www.dnssec-failed.org a

y perfecto! Nuestra consulta ahora dió status SERVFAIL, y no hay respuesta. DNSSEC nos
está protegiendo, arrojando error en vez de una respuesta ante nombres que no cumplen
con una validación correcta. Podemos confirmar que es un error DNSSEC usando la opción
+cd, que desactiva validación en forma explícita para esa consulta, y debiéramos tener
resultados:

$ dig @localhost www.dnssec-failed.org a +cd

Por otro lado, un nombre de dominio correctamente firmado vendrá con el bit "ad",
indicando que el resolver pudo validarlo correctamente:

$ dig @localhost www.lacnic.net a

RPZ Y FILTROS

Como vimos en los módulos teóricos, una de las funciones más recurrentes es aplicar filtros
locales a ciertos nombres que no queremos que sean resueltos, como por ejemplo filtros
parentales.

Probemos en un inicio con un nombre en específico, para simular el comportamiento.

4
$ sudo vi named.conf.options
response-policy {
zone "rpz.localhost";
};

$ sudo vi named.conf.local
zone "rpz.localhost" {
type primary;
file "/var/lib/bind/rpz.localhost.zone";
};

Creamos la zona. Pondremos como demo la dirección www.lacnic.net que será bloqueado
con NXDOMAIN. La forma de lograr un NXDOMAIN en RPZ es con un alias a la raíz
(CNAME .). Otra cosa importante es que los nombres deben ser relativos y no absolutos.

$ sudo vi /var/lib/bind/rpz.localhost.zone
$ORIGIN rpz.localhost.
@ 300 IN SOA localhost. hsalgado.vulcano.cl (
2022091101
60
60
432000
60
)

300 IN NS localhost.

www.lacnic.net 300 IN CNAME .

También es posible utilizar wildcard (*) para calzar expresiones regulares.

Recargamos la configuración de bind, y probamos:

$ sudo rndc reconfig


$ dig @localhost www.lacnic.net a

y recibimos NXDOMAIN con un SOA en el ADDITIONAL que corresponde a nuestra zona


especial de bloqueo.

5
Bind tiene un comportamiento conservador respecto a la relación entre RPZ y DNSSEC. Al
modificar las respuestas la validación DNSSEC se puede romper, ya que esa es su labor.
Por eso, Bind por defecto responde con el registro real en caso de recibir una consulta
pidiendo los registros DNSSEC. Si queremos romper incluso este caso, y filtrar las
respuestas sin importar si quebramos DNSSEC, se le debe agregar a la directiva "response-
policy" del named.conf.options, el valor "break-dnssec yes".

Existen diversos servicios que entregan zonas RPZ listas con cientos de dominios con
malware y bloqueos. En ese caso se deben utilizar zonas secundarias que transfieren de un
primario que mantiene estos nombres, según la configuración de cada servicio externo.

Aprovecharemos también de configurar un archivo de logs nuevo para dejar las consultas
por dominios bloqueados con RPZ. Para ello tenemos que crear un "canal", indicándole
dónde vamos a loguear, y la categoría correspondiente.

$ sudo vi named.conf.options
logging {
channel rpzlog {
file "rpz.log" versions 10 size 1024;
print-time yes;
print-category yes;
print-severity yes;
severity info;
};
category rpz { rpzlog; };
};

Recargamos y lanzamos de nuevo una consulta que gatille RPZ:

$ sudo rndc reconfig


$ dig @localhost www.lacnic.net a

El archivo de logs queda en el directorio de cache por default. Ahí podemos revisar su
contenido:

$ cat /var/cache/bind/rpz.log

6
ZONAS INTERNAS PRIVADAS

Otra situación bastante común es el uso de zonas internas de una organización, donde
puede existir un subdominio que es invisible para las redes externas, pero sí se dispone de
autoritativos internos que sí responden.

Por ejemplo, supongamos que nuestra empresa tiene el nombre de dominio


"curso.localhost", que es una zona pública, pero dentro queremos tener un subdominio
"intranet.curso.localhost" que es accesible sólo desde la red interna, y que no está delegado
desde la zona real.

Para ello, la técnica que veremos acá es la de declarar una zona "forwarder" desde nuestro
resolver.

Si suponemos que los DNS autoritativos internos que contienen la zona


"intranet.curso.localhost" se ubican en las direcciones IPs 127.0.20.1 y 127.0.21.1:

$ sudo vi named.conf.local
zone "intranet.curso.localhost" {
type forward;

forwarders {
127.0.20.1;
127.0.21.1;
};

forward only;
};

Además debemos desactivar la validación DNSSEC para este nombre, debido a que al ser
inexistente en la zona real "curso.localhost", tendremos un NSEC que nos indicará que el
nombre no existe. Al desactivar DNSSEC podemos llegar a resolverlo.

$ sudo vi named.conf.options
validate-except {
"intranet.curso.localhost";
};

Si ahora recargamos, cualquier consulta a este nombre interno no será resuelto usando la
recursión en el árbol DNS público, sino será "forwardeado" a los dos servidores internos

7
indicados, y la respuesta será retornada al cliente final, logrando hacer funcionar un nombre
solo para clientes internos.

Importante en el caso particular de este ejemplo, la zona "localhost" es manejada


internamente por el resolver, por lo que es posible obtener una respuesta autoritativa en vez
de forward. Para solucionarlo habría que editar el named.conf.default-zones y comentar las
líneas que definen la zona localhost. Pero lo más recomendable es utilizar un subdominio
de un dominio personal que tengan, para evitar secuestrar nombres externos que
eventualmente podrían escapar a la internet pública.

MANEJO DE EXCEPCIONES DNSSEC

Como vimos en la parte teórica, es necesario en ciertos momentos desactivar la validación


DNSSEC para algún dominio en forma momentánea. Es muy importante hacer esto luego
de un análisis detallado del problema, en lo posible con alguna confirmación de los
operadores del dominio, para no quedar vulnerables frente a un ataque. Desactivar
DNSSEC para un dominio podría ser muy riesgoso.

Dicho esto, el mecanismo es agregar un "negative trust anchor", el concepto de Bind para
desactivar validación. Esto se hace con el comando nta de rndc:

$ sudo rndc nta dominio.com

Esta desactivación queda por 1 hora, y luego se reactiva la validación. Si el dominio persiste
con el problema, hay que volver a evaluar y repetir el comando. Además, Bind cada 5
minutos verifica si las firmas se corrigen, en cuyo caso reactiva la validación antes de la
hora.

Con el comando:

$ sudo rndc nta -dump

Se puede ver qué llaves ancla negativas existen, y su hora de expiración.

8
ERRORES DE UPSTREAM CON COOKIES Y EDNS

Dentro de las labores habituales de operación de un recursivo se encuentra buscar fallas en


nombres de dominio que no se pueden resolver.

Existen muchos dominios que están muy mal configurados, que funcionar casi de milagro.
Es complejo hacer un catálogo de todos los errores, pero hay uno en particular que se repite
bastante frecuentemente, y sobre todo con un servicio famoso en Internet que no quiero
nombrar, pero tengan por seguro que se toparán con el.

Estos errores se ocasionan con el uso de "cookies", y con el uso de EDNS.

El uso de cookies está estandarizado y en operación, pero existen ciertos DNS autoritativos
que no saben cómo reaccionar ante la utilización de cookies. Bind por defecto las utiliza en
modo recursivo cuando contacta a los DNS autoritativos upstream, así que hay que estar
atentos.

Estos errores se pueden detectar fácilmente en forma manual. Si una consulta dirigida al
autoritativo con dnssec normal:

$ dig @server <zona> soa +dnssec +norec

da error, SERVFAIL, FORMERR o se queda sin respuesta, prueben enviándola sin cookies:

$ dig @server <zona> soa +dnssec +nocookie +norec

Si acá tienen respuesta, entonces está claro el problema. La solución es agregar una
directiva "send-cookie" especial para ese servidor, identificándolo por su dirección IP, en la
configuración global pero fuera de la sección options:

$ sudo vi named.conf.options
server 6.6.6.6 { send-cookie no; };

Si siguen teniendo errors con +nocookie, puede ser que el servidor incluso esté fallando con
EDNS. Esto es un error muy grave, en el DNS Flag Day del año 2020 se definió que este
tipo de errores serían castigados marcando el autoritativo como "dead" (muerto). Pero
sabemos que a veces es necesario hacer excepciones!

La prueba definitiva en este caso sería:

$ dig @server <zona> soa +noedns +norec

9
Si acá tienen respuesta, entonces se puede poner una excepción más radical en la
configuración global:

$ sudo vi named.conf.options
server 6.6.6.6 { edns no; };

¡Con esto damos por finalizado el taller! Ahora es tiempo que ustedes tomen manos a la
obra. En el sitio del curso podrán encontrar las instrucciones para descargar la imagen de la
máquina virtual, o bien armarla ustedes. Luego deberán repetir estos comandos y ejecutar
una serie de pruebas, que será su evaluación final. ¡Mucha suerte!

10

También podría gustarte