Ir al contenido

Configurar un DNS de horizonte dividido maestro/esclavo con Bind

Instalación de Bind

La razón de existencia del DNS es responder con una dirección IP a la consulta por un nombre determinado. El comportamiento normal y común es brindar la misma respuesta sin importar dónde se originó la solicitud.

Sin embargo, hay requisitos y casos de uso en los que es necesario configurar el servidor DNS con un conjunto diferente de direcciones para el mismo nombre de dominio.
Lo que haremos será crear dos respuestas diferentes para algunas zonas, basadas en la IP de origen de una solicitud. Así, si una máquina con una IP en la subred 192.168.202.0/24 (llamémosla interna) consulta nuestro DNS, recibirá una dirección IP interna como respuesta. Cuando la misma consulta sea iniciada por una máquina fuera de esa subred (llamémosla externa), el servidor DNS devolverá otra dirección IP.
No tiene sentido dar la misma respuesta para ambos casos. Porque los usuarios de la red interna deben acceder a los servicios a través de las direcciones IP de la LAN (que será mucho mejor en términos de rendimiento, así como la latencia) en lugar de acceder a través de la dirección de Internet pública.
En este artículo, nos centraremos en la implementación de esta función en la propia configuración del DNS.

El primer, y necesario, paso consiste en instalar Bind. Para ello vamos a recurrir al trabajo de Ondřej Surý quien se ha encargado de disponibilizar paquetes BIND 9.16.6 para Debian GNU/Linux 9 y 10.

$ apt-get -y install apt-transport-https lsb-release ca-certificates curl
$ wget -O /etc/apt/trusted.gpg.d/bind.gpg https://packages.sury.org/bind/apt.gpg
$ sh -c 'echo "deb https://packages.sury.org/bind/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/bind.list'
$ apt-get update

Un detalle importante tiene que ver con los archivos de registro (logs) personalizados. En caso que hagamos uso de esta característica, será necesario crearlos antes de iniciar bind ya que no lo hace de manera automática. De lo contrario encontraremos mensajes de error como

ago 06 08:21:46 nssv named[2837]: isc_stdio_open '/var/log/named/rate_limit.log'
ago 06 08:21:46 nssv named[2837]: configuring logging: permission denied
ago 06 08:21:46 nssv named[2837]: loading configuration: permission denied
ago 06 08:21:46 nssv named[2837]: exiting (due to fatal error)

Así que, creamos los archivos y les asignamos los permisos necesarios.

$ mkdir -p /var/log/named
$ chmod 0775 /var/log/named
$ cd /var/log/named
$ touch {lame,queries,query-error,rate_limit,security}.log
$ chmod 664 *.log
Ningún sistema o instalación tiene un tiempo de actividad perfecto del 100% y, dado que el DNS puede ser un componente bastante crítico de la red, se recomienda tener un DNS secundario para proporcionar una copia de seguridad en caso de que el primario falle. Podríamos simplemente tener dos servidores DNS iguales que tengan la misma configuración y datos. Aunque esto funcionaría perfectamente, requeriría que hicieramos todos los cambios dos veces. Una en el primario y otra en el secundario.
Configurando un servidor como maestro y el otro como esclavo, el esclavo replicará sus datos de zona desde el maestro. De esta manera, cuando se hacen cambios en alguna zona en el maestro, el esclavo recibe una notificación y se hace cargo de los cambios casi instantáneamente sin necesidad de hacer ninguna configuración en el lado del esclavo.
El principal archivo de configuración para bind es /etc/bind/named.conf. Incluye punteros a otros archivos que bind necesita para comprobar las configuraciones. Veamos un archivo named.conf típico.

# cat /etc/bind/named.conf
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

La configuración anterior sólo indica a bind que busque en los archivos /etc/bind/named.conf.options, /etc/bind/named.conf.local, /etc/bind/named.conf.default-zones.
El archivo /etc/bind/named.conf.options contiene el conjunto de opciones generales para bind. Cosas como las siguientes se mencionan en ese archivo.

  • Escuchar en puerto e interfaz
  • Permitir consulta
  • Permitir la transferencia a las direcciones de origen
  • Permitir la recursión o no
  • Ubicación del archivo PID
  • Lista de IPs permitidas para consultar este servidor DNS
  • Habilitar/Deshabilitar DNSSEC para la transferencia de zonas
  • Ubicación de la caché… etc
# cat /etc/bind/named.conf.options
options {
        directory       "/var/cache/bind/";
        dnssec-validation auto;
        auth-nxdomain no;
        listen-on-v6 { none; };
        listen-on port 53 { 127.0.0.1; 10.10.20.2;};
        allow-query     { any;};
        allow-recursion { localhost; ::1; 10.10.20.0/24; };
        allow-transfer { none; };
        pid-file "/var/run/named/named.pid";
        notify yes;
};

La característica más importante de bind que permite esta configuración de horizonte dividido se llama “vistas”. Las vistas en bind permiten alojar un conjunto de configuración para algunos, y uno distinto para otros.
Bueno, técnicamente, incluso si no se configura ninguna vista… bind creará una vista y esa vista se sirve internamente a todas las consultas de todas las fuentes.
Las vistas en bind se crean usando la cláusula view como se muestra a continuación.

view "ejemplovista" {
};

Las secciones de vistas están organizadas debajo de la sección de opciones que vimos antes. Así que vamos a mantener nuestras vistas en el archivo /etc/bind/named.conf.options, que ya incluimos en named.conf.
Para definir las direcciones de origen que serán aplicables a la vista utilizaremos declaraciones acl.

acl "ejemploacl" { 10.10.10.0/24; 10.10.20.0/24; };
     view "ejemplovista" {
		match-clients { "ejemploacl"; };
	 };

Sólo hay que tener en cuenta que es necesario definir la declaración acl fuera de la declaración views.
Se puede colocar casi todo lo que la declaración de opciones soporta. Cosas como la recursividad, el tipo (es decir, si actuar como maestro o esclavo), las zonas, las firmas, etc.

acl "ejemploacl" { 10.10.20.0/24; };
view "ejemplovista" {
        match-clients { "ejemploacl"; };
		zone "prueba.ejemplo.edu.ar" {
				type master;
				file "prueba.ejemplo.edu.ar.zona";
		};
};

Otro caso perfecto de uso de las vistas es permitir la recursión sólo para nuestros clientes internos y negar la recursión para los clientes externos. Esto se puede lograr fácilmente usando views. Esto se debe a que views soporta la opción de recursión (se puede permitir o negar la consulta dns recursiva a una dirección de origen particular)
También la sentencia match-clients soporta una entrada comodín llamada any, que es realmente útil para hacer vistas que se apliquen a todo el mundo. Como el ejemplo que se muestra a continuación…

acl "ejemploacl" { 10.10.20.0/24; };
view "vistainterna" {
        match-clients { "ejemploacl"; };
		recursion yes;
		zone "prueba.ejemplo.edu.ar" {
				type master;
				file "prueba.ejemplo.edu.ar.int.zona";
		};
};
view "vistaexterna" {
		match-clients { any; };
		recursion no;
		zone "prueba.ejemplo.edu.ar" {
				type master;
				file "prueba.ejemplo.edu.ar.ext.zona";
		};
};

Es una medida de seguridad común para permitir la recursión sólo a los clientes conocidos. Esto se debe a que la recursión plantea muchos riesgos de seguridad.
De contar con servidores distribuidos en diferentes ubicaciones geográficas, para proporcionar el mismo servicio, se puede utilizar la sentencia views para hacer que el dns responda con la dirección IP del servidor más cercano al solicitante. Usando esto se puede obtener una red distribuida con latencia reducida, similar a una red CDN. Basta añadir los rangos de IP públicas de la ubicación/país de origen en la lista match-client o en la lista acl.
Lo único que hay que hacer es reiniciar Bind para borrar su caché:

# systemctl restart bind9

También se puede utilizar el comando rndc para vaciar toda la caché:

# rndc flush

Luego recargamos la configuración de bind:

# rndc reload

BIND soporta el vaciado de todos los registros asociados a un nombre de dominio concreto con el comando rndc flushname. En este ejemplo, se pueden vaciar todos los registros relacionados con el dominio unau..edu.ar:

# rndc flushname cyberciti.biz

También es posible vaciar las vistas de BIND. Por ejemplo, las vistas interna y publica pueden ser vaciadas usando el siguiente comando:

# rndc flush interna
# rndc flush publica
Etiquetas: