Configuración de un servidor DNS en debian

Introducción teórica

En el principio fue /etc/hosts...

En el protocolo TCP/IP cada máquina está identificada por su dirección IP, que es una dirección numérica constituida por 32 bytes. No obstante, este modo de identificar a las máquinas es difícil de recordar para un ser humano que prefiere, para referirse a las cosas, poner un nombre.

Por esta causa, en los orígenes de internet, cuando había pocas máquinas conectadas, el problema se resolvió de un modo muy sencillo: mediante un fichero que asociaba cada dirección ip al nombre del equipo. Este fichero, que sigue existiendo en los sistemas operativos modernos, se llama hosts y se encuentra en /etc/hosts en los sistemas UNIX (linux entre ellos) y en C:\Windows\System32\drivers\etc\hosts en los sistemas windows modernos.

En un principio el fichero hosts se intercambiaba entre las máquinas interconectadas y, de este modo, se resolvían las direcciones ip en nombres. Su sintaxis es muy sencilla. El fichero consta de líneas en cada una de las cuales se indica una dirección ip y el nombre o los nombres asociados a esa dirección. Por ejemplo:

127.0.0.1      localhost.localdomain     localhost

esta línea asocia los nombres localhost y localhost.localdomain a la dirección de loopback. De este modo, referirse a localhost es equivalente a referirse a la dirección de loopback 127.0.0.1. Cualquier línea que comience con una almohadilla (#) se considera un comentario y no se lee. Es como se ve muy sencillo de implementar, pero sólo servía cuando internet tenía pocos ordenadores. Cuando su número empezó a crecer, se requirieron otras soluciones más imaginativas y surgió el DNS (Sistema de Nombres de Dominio). Pese a ello, los sistemas operativos siguen consultando el fichero hosts y, antes de recurrir a los servidores DNS para averiguar la IP a la que está asociado un nombre, buscan en este fichero. Por este motivo si incluyésemos, por ejemplo, la siguiente línea:

127.0.0.1      localhost.localdomain     localhost     www.google.es

al hacer un ping a google no respondería el servidor de google, sino nuestra propia máquina a través de la interfaz de loopback.

DNS

Cuando creció demasiado el número de nodos en internet, la solución de intercambiar un fichero de hosts que contuviese todas las máquinas se volvió ineficaz y se pensó en una resolución de nombres organizada de forma jerárquica. La idea consiste en disponer unos nodos raíz (los nodos root o "."), que tengan información sobre cuáles son los servidores autoritativos del primer nivel, tales como edu., com., org., tk., etc. Cada uno de estos, a su vez, conoce cuáles son los servidores autoritativos de las direcciones de segundo nivel que dependen jerarquicamente de ellos, y así sucesivamente.

Estructura jerárquica de las consultas DNS

El árbol expuesto es algo más complejo, ya que no existe nunca una única máquina autoritativa para un dominio. Si fuera así, y esta máquina cayera, sería imposible resolver todos los subdominios que dependen de ella.

Sea como sea, si nuestra máquina desea conocer la dirección del servidor www.iescdl.tk, preguntará a su servidor dns. Si éste tiene la dirección en su caché, responderá directamente; pero, si no es así, realizará una búsqueda iterativa en el árbol jerárquico: preguntará primero a los servidores raíz, los cuales le informarán de cuáles son los servidores autoritativos de la zona tk. Sabidos estos servidores, se informará a través de alguno de ellos de cuáles son los servidores autoritativos para el dominio iescdl.tk, y conocidos estos, podrá informarse a través de uno de ellos de cuál es la dirección deseada: www.iescdl.tk. Para agilizar este proceso los servidores cachean también las direcciones de estos servidores autoritativos, de manera que si el cliente preguntase luego por otra máquina de este dominio, no habría que empezar la búsqueda por los servidores raíz, sino que se podría recurrir directamente al servidor autorizativo de la zona iescdl.tk. Para entender esto un poco mejor se puede observar qué ocurre cuando se hace una consulta con la opción +trace.

Los servidores DNS escuchan en el puerto 53 y usan tanto paquetes UDP como paquetes TCP.

Resolviendo nombres

Antes de pasar a instalar algún servidor DNS es muy pertinente saber qué servidores está usando nuestro sistema y cómo se prueba la resolución de nombres.

El nombre de la propia máquina

Es recomendable saber cómo linux da nombre a la propia máquina, lo cual, en principio, no tiene nada que ver con TCP/IP. La forma de averiguar el nombre (que es el que aparece en el prompt de la terminal) es a través del comando hostname:

usuario@cubo:~$ hostname
cubo

Para cambiar el nombre no hay más que usar hostname apropiadamente:

$ hostname ns

El nombre no tendrá reflejo en el prompt, porque este se calcula al iniciar sesión, así que habrá que salir y volver a entrar para poder verlo. Sin embargo, este cambio no es permanente: es necesario almacenar el nuevo nombre en /etc/hostname, para lo cual lo más rápido es hacer lo siguiente:

$ hostname ns
$ hostname > /etc/hostname

Si se quiere darle también un dominio a la máquina, entonces es necesario tocar el fichero /etc/hosts:

$ cat /etc/hosts
127.0.0.1    localhost
127.0.1.1    ns.iescdl.tk  ns

Obsérvese la segunda línea en la que se ha dejado el nombre a secas y el nombre con el dominio. De esta manera hostname será capaz de averiguar cuál es el dominio:

$ hostname -d
iescdl.tk

También podríamos haber usado el comando dnsdomainname:

$ dnsdomainname
iescdl.tk

Además de lograr esto, al introducir el nombre en /etc/hosts, hemos logrado que cualquier comando resuelva el nombre ns.iescdl.tk como 127.0.1.1. Esto ocurre en debian cuando el sistema no tiene una ip permanente. Si la tiene, es conveniente ponerle la ip real.

Cómo se resuelven nombres

Cuando el sistema intenta resolver un nombre, hace lo que se indique en el fichero /etc/nsswitch.conf:

$ grep dns /etc/nsswitch.conf 
hosts:          files dns

Lo habitual (si no se usa además algún método más exótivo como ldap) es lo mostrado arriba: primero se consulta el fichero /etc/hosts y luego al servidor de nombres. En los sistemas linux la declaración de los servidores DNS se encuentra dentro del fichero /etc/resolv.conf:

domain iescdl.tk
search iescdl.tk
nameserver 8.8.8.8
nameserver 8.8.4.4

Las entradas que comienzan por nameserver son las ips de los servidores DNS. También puede haber una entrada domain que debería contener el dominio de la propia máquina; y una entrada search que sirven para indicar los dominios con los que se completará el nombre. Por ejemplo:

$ host ns

intentará resolver el nombre ns, si este no existe añadirá iescdl.tk y volverá a repetir la búsquda. Es posible indicar varios dominios separados por espacio y en ese caso se irá probando secuencialmente uno a uno hasta que se encuentre un nombre que resuelva o se agote la lista sin encontrar ninguno.

host

Uno de los dos clientes para comprobar resoluciones de nombres es host. Su uso más simple es indicándole el nombre que quiere resolverse:

$ host www.iescdl.tk
172.22.0.2

Para hacer la resolución, se usan los servidores declarados en /etc/hosts. Sin embargo, puede usarse otro arbitrario incluyéndolo como segundo parámetro:

$ host www.iescdl.tk 194.179.1.100
80.80.80.80

También puede especificarse un tipo de registro particular (los tipos de registros se explican un poco más adelante al hablar de la configuración del servidor):

$ host -t mx iescdl.tk

También es útil conocer cómo podemos consultar todas las resoluciones de un servidor DNS, para lo cual se necesita tener permisos para la transferencia de toda la zona (AXFR). Esto no será posible en un servidor público, pero suele ser posible hacer consulta a nuestro servidor local de nuestro propio dominio. Por ejemplo: para obtener todos los registros A del dominio iescdl.tk:

$ host -l -t a iescdl.tk

dig

dig es otro cliente, algo más verborreico y que da más información. La consulta básica se hace igual:

$ dig www.iescdl.tk

Esta consulta, sin embargo, devuelve información de los registros A. Si se quiere consultar otro tipo de registro hay que declararlo explícitamente:

$ dig iescdl.tk MX

Esta es una diferencia bastante notoria con host, que devuelve información de todos los registros que cumplen con la búsqueda. dig devuelve mucha información:cuando se quiere una información escueta en que sólo se incluya la resolución a la manera de host puede incluirse entonces el modificador +short:

$ dig www.iescdl.tk +short
172.22.0.2

Si se quiere obtener el registro, tal como lo hubiéramos visto escrito en el fichero de definición se puede usar lo siguiente:

$ dig +nocmd www.iescdl.tk +noall +answer
iescdl.tk.              85985   IN      A       172.22.0.2

Para la resolución inversa puede usarse la opción -x:

$ dig -x 172.22.0.2 +short
www.iescdl.tk

Esta última resolución también puede hacerse preguntando por el registro PTR correspondiente (ya se entenderá esto cuando se aprenda a configurar servidores):

$ dig 2.0.22.172.in-addr.arpa PTR +short
www.iescdl.tk

Si se quieren obtener (en caso de tener permisos) todas las máquinas de un dominio, se puede usar el tipo AXFR:

$ dig iescdl.tk AXFR

dig ofrece otra funcionalidad bastante interesante: +trace, que permite rastrear cómo se realiza la petición. Cuando se hace una consulta de este modo, no se logran resoluciones gracias a ninguna caché, sino que se realizan todas las consultas necesarias para obtener la resolución. Veamos un ejemplo:

$ dig +trace +nocmd www.iescdl.tk
.                       334822  IN      NS      j.root-servers.net.
.                       334822  IN      NS      a.root-servers.net.
.                       334822  IN      NS      e.root-servers.net.
.                       334822  IN      NS      k.root-servers.net.
.                       334822  IN      NS      b.root-servers.net.
.                       334822  IN      NS      m.root-servers.net.
.                       334822  IN      NS      f.root-servers.net.
.                       334822  IN      NS      h.root-servers.net.
.                       334822  IN      NS      l.root-servers.net.
.                       334822  IN      NS      c.root-servers.net.
.                       334822  IN      NS      i.root-servers.net.
.                       334822  IN      NS      d.root-servers.net.
.                       334822  IN      NS      g.root-servers.net.
;; Received 512 bytes from 192.168.1.1#53(192.168.1.1) in 74 ms

tk.                     172800  IN      NS      a.ns.tk.
tk.                     172800  IN      NS      b.ns.tk.
tk.                     172800  IN      NS      c.ns.tk.
tk.                     172800  IN      NS      d.ns.tk.
;; Received 274 bytes from 199.7.83.42#53(199.7.83.42) in 140 ms

iescdl.tk.              300     IN      NS      ns.iescdl.tk.
iescdl.tk.              300     IN      NS      ns2.afraid.org.
;; Received 92 bytes from 194.0.41.1#53(194.0.41.1) in 304 ms

www.iescdl.tk.          86400   IN      A       80.80.80.80
iescdl.tk.              86400   IN      NS      ns.iescdl.tk.
;; Received 80 bytes from 80.80.80.80#53(80.80.80.80) in 94 ms

La forma de interpretar esto es la siguiente:

  • Se realiza una petición al servidor DNS que tiene configurada la máquina que realiza la consulta. En este caso es un servidor local en 192.168.1.1. Esta petición devuelve cuáles son los servidores raíz.
  • Se toma uno de esos servidores raíz, que en la consulta ha sido 199.7.83.42 (o sea, l.root-servers.net), y se pregunta por cuáles son los servidores autoritativos para la zona tk.
  • Se toma uno de esos servidores (en el ejemplo 194.0.41.1, que se corresponde con d.ns.tk) y se le pregunta por los servidores autoritativos del dominio iescdl.tk.
  • Se toma uno de los servidores devueltos (80.80.80.80, que es ns.iescdl.tk) y este por fin es capaz de resolver la dirección.

Debe realizarse una puntualización: todas estas consultas las hace directamente nuestra máquina cliente con la información recibida en el paso anterior. Cuando se realiza una consulta normal, el cliente sólo hace una única consulta a su servidor y este es el que se encarga de hacer todas las consultas necesarias para obtener la información.

El servidor dnsmasq

Las distribuciones de linux suelen incluir un paquete con dnsmasq, un sencillito servidor dhcp y dns, que en muchos casos cumple sombradamente con ambas cometidos. Se pueden consultar los apuntes sobre dhcp para acceder a una pequeña discusión sobre cuándo usarlo.

Tanto para dns como para dhcp, el fichero de configuración es /etc/dnsmasq.conf.

dnsmasq como servidor dns

De modo predeterminado dnsmasq trae habilitado el servidor dns (no así el dhcp). Su funcionamiento es la mar de sencillo: se harán consultas dns a los servidores que se encuentran en /etc/resolv.conf, como se hace normalmente y se cachearán estas consultas. El número máximo de nombres que se cachean viene determinado por la variable cache-size (150 es el valor predeterminado). O sea, dnsmasq no es más que una caché de nombres de dominio.

No obstante lo anterior, es posible definir nuestros propios nombres de máquinas, incluyéndolos en el fichero /etc/hosts. Por ejemplo, incluir:

172.22.0.2     www.iescdl.tk
172.22.0.1     router.iescdl.tk

haría que todas las máquinas de nuestra red que usasen como servidor dns, la máquina en la que instalamos dnsmasq sean capaces de resolver estos dos nombres. Digamos que dnsmasq nos permite compartir nuestro /etc/hosts con los clientes.

Opciones útiles de configuración son:

  • cache-size=<numero_de_nombres>, determina el número máximo de nombres de dominio que cacherá dnsmasq.
  • no-hosts, que hace que no se resuelvan los nombres contenidos en /etc/hosts.
  • addn-hosts=<file>, que resuelve los nombres que haya en el fichero file (esto no implica que no se lea /etc/hosts). Se puede incluir varias veces la opción, de modo que se leerán todos los ficheros. Si el fichero es un directorio, entonces se leerán todos los ficheros que contenga ese directorio.
  • ttl-local=<seg>, tiempo en segundos que se cachearán los nombres locales (lo predeterminado es que no se cacheen).
  • localise-queries, devuelve la respuesta dns dependiendo de la interfaz por la que se recibió la petición. Esto es útil cuando se quiere que un mismo nombre tenga varias ips asociadas.
  • address=/<nombre_dominio>/<direccion_ip>, permite definir un nombre de dominio.

dnsmasq como servidor dhcp

La explicación a esto se halla en los apuntes de dhcp.

El servidor bind9

Antes de la configuración

Conceptos previos

Antes de comenzar cualquier configuración es necesario algunos conceptos:

  • Servidor autoritativo: es el servidor DNS que tiene la información de un determinado dominio. En cambio, si para resolver un dominio necesita consultar otros servidores entonces no es autoritativo. Obsérvese que un servidor es autoritativo para un dominio o un conjunto de dominios; y no autoritativo para los restantes. Esto último, claro está, si el servidor no se niega a resolver nombres que no gestiona él, o dicho de otro modo, si el servidor permite consultas recursivas.
  • Servidor maestro: es el servidor que contiene primariamente la información del dominio.
  • Servidor esclavo: es un servidor que replica la información de dominio de un servidor maestro, gracias a que se sincroniza con éste, y cualquier cambio que se realiza en el servidor maestro se propaga al esclavo.
  • Resolución directa: es la resolución que permite obtener una dirección ip a partir de un nombre.
  • Resolución inversa: es la resolución que permite obtener el nombre a partir de una dirección ip.
  • Vista: es la perspectiva desde la que un cliente ve un servidor DNS, la cual habitualmente depende de la ip que tenga dicho cliente. Esta diferente perspectiva se traduce en que el servidor podrá resolver de diferente forma los nombres. Por ejemplo, supóngase un servidor que da servicio tanto a una red interna como a internet. Para los mismos nombres de máquina los clientes situados en internet deberán obtener direcciones públicas (o la dirección pública, si sólo se dispone de una), mientras que los clientes internos podrán obtener direcciones privadas.
  • Consulta recursiva: es aquella que realiza un servidor DNS, cuando al no conocer la respuesta a una petición, procura averiguarla consultándole a su vez, a otro servidor.

Instalación del servidor dns

El servidor DNS más conocido es BIND, que fue totalmente rescrito para la última versión oficial, la versión 9. La instalación en debian es análoga a la de cualquier otro paquete:

$ aptitude install bind9

La orden instalará el servidor, que como tiene incluido en su configuración los servidores raíz, ya es capaz de resolver dominios. Para comprobarlo, basta con usar el comando dig:

$ dig @localhost www.iescastillodeluna.tk

Se ha incluido @locahost, porque probablemente no se haya cambiado aún /etc/resolv.conf para que la máquina use nuestro propio servidor:

# echo nameserver 127.0.0.1 > /etc/resolv.conf

Aunque quizás también hubiéramos querido definiir domain y search en este fichero.

Enjaulamiento

El servicio dns es tristemente célebre por sus repetidos... problemas de seguridad. Por ello es muy recomendable enjaular el servicio dentro de un directorio que llamaremos /var/lib/chroot-dns.

Paremos el servicio para hacer los cambios:

# invoke-rc.d bind9 stop

Antes de empezar, no obstante, es también recomendable, evitar que el posible atacante conozca la versión de nuestro servidor. Para ello en named.conf.options puede añadirse:

version "3.1416";

o cualquier otro número de versión absurdo.

Procedamos ahora a enjaular. Lo primero es crear los directorios necesarios:

# mkdir -p /var/lib/chroot-dns/{etc,dev,var/{cache,run}}

Dentro de dev, necesitamos tener ficheros especiales null y random:

# mknod /var/lib/chroot-dns/dev/null c 1 3
# mknod /var/lib/chroot-dns/dev/random c 1 8
# chmod 666 /var/lib/chroot-dns/dev/*

Pasamos /etc/bind a su nueva ubicación:

# mv /etc/bind /var/lib/chroot-dns/etc
# ln -s /var/lib/chroot-dns/etc/bind /etc

Otro tanto hacemos con /var/cache/bind:

# mv /var/cache/bind /var/lib/chroot-dns/var/cache
# ln -s /var/lib/chroot-dns/var/cache/bind /var/cache

Y con /var/run/named:

# mv /var/run/named /var/lib/chroot-dns/var/run
# ln -s /var/lib/chroot-dns/var/run/named /var/run

Asignamos ahora permisos:

chown -R bind:bind /var/lib/chroot-dns/*

Y cambiamos el servicio de log:

# echo '$AddUnixListenSocket /var/lib/chroot-dns/dev/log' > /etc/rsyslog.d/dns-chroot.conf
# invoke-rc.d rsyslog restart

Listo. Ahora indiquémosle a bind, cuál es el directorio en que se hallará enjaulado. Para ello ha de editarse el fichero /etc/default/bind y dejar una línea del siguiente modo:

OPTIONS="-u bind -t /var/lib/chroot-dns"

Reiniciemos el servicio:

# invoke-rc.d bind9 start

Si el sistema es gestionado por systemd (caso de jessie) necesita añadir el parámetro -f a las opciones.

En el momento de revisar estos apuntes, existe en jessie un bug que hace que systemd no atienda a la configuración del anterior fichero. con lo que el cambio no entrá efecto. Por tanto, es muy conveniente que compruebe con qué parámetros se ejecutó bind9 (si no cargan los parámetros especificados, lea con atención el enlace: en él se explica cómo arreglarlo):

# invoke-rc.d bind9 status

Casos de estudio

Basaremos todas nuestras configuraciones en esta red:

Esquema de la red

La red, cuando se complete la configuración más compleja, debería funcionar del siguiente modo:

  1. El servidor principal resuelve el dominio iescdl.tk como maestro y tiene definidas tres vistas distintas:
    • La que se ve desde internet.
    • La que ven las redes 172.22.0.0/24 y 192.168.10.0/24, y el propio servidor.
    • La que ven las redes 172.31.0.0/24 y 192.168.20.0/25.
    Además también es servidor esclavo del subdominio frances.iescdl.tk y maestro de ingles.iescdl.tk.
  2. El servidor de la primera intranet será servidor esclavo de los subdominios frances.iescdl.tk e iescdl.tk.
  3. El servidor de la segunda intranet será el servidor maestro del subdominio ingles.iescdl.tk y servidor esclavo de iescdl.tk.
  4. En el servidor principal hay también un servidor dhcp que se encarga de servir direcciones a las dos redes internas. Además se habilita la asignación dinámica de nombres, de modo que al asignarse una dirección se le otorgue un nombre a la nueva máquina.

Obviamente esta configuración planteada no es la más lógica: sería más recomendable hacer una configuración simétrica en la que los dos servidores internos fueran servidor maestros de sus respectivas subredes o bien en la que ambos fueran los servidores esclavos. No se hace, simplemente, para abarcar más circunstancias y poder analizar más casos.

Cómo resolver directamente el problema es enormemente complejo y, por tanto, escasamente didáctico. Por ello, nuestro modus operandi consistirá en no considerar partes de las red ni redundancias del servicio e irlas añadiendo paulatinamente. Esto obligará no sólo a crear nuevos ficheros de configuración, sino a enmendar algunos ya escritos.

El plan de estudio será el siguiente:

  1. Configuración básica: solo consideraremos la red 172.22.0.0/16 y el dominio iescdl.tk, para el cual sólo existirá un servidor maestro en el servidor princial
  2. Configuración con subdominios: añadiremos las redes 192.168.10.0/24 y 192.168.20.0/25, de manera que para la primera red el servidor maestro sea el principal; y para la segunda, el servidor interno.
  3. Configuración con resolución inversa en redes sin clase: para la red 192.168.20.0/25, que no es una red pura de clase C, añadimos la resolución inversa, que es más complicada que la resolución de clases puras.
  4. Configuración con servidor esclavo: para añadir redundancia haremos que el servidor principal haga de secundario de la red interna 192.168.20.0/25 y el servidor interno de la red 192.168.0.0/24.
  5. Configuración con actualizaciones dinámicas: habilitaremos el servidor dhcp para que al conceder direcciones, registre también nombres en el servidor dns.
  6. Configuración con vistas: Añadiremos una vista para que los clientes de internet obtengan la ip pública al preguntar por máquinas del dominio iescdl.tk.
  7. Configuración con actualizaciones en dos o más vistas: añadiremos la red 172.31.0.0/16 y una tercera vista para ella y para la red 192.168.20.0/25. Esto provocará que las actualizaciones automáticas se tengan que propagar de la vista en la que se realizan a la otra.

Configuración básica

Configuración de un servidor maestro capaz de hacer resoluciones directas e inversas de un dominio propio

Para poner en práctica este caso sólo consideraremos la red 172.22.0.2, a la que corresponderá el dominio iescdl.tk.

DominioRedServidor
MaestroEsclavo
iescdl.tk172.22.0.0/16172.22.0.2-

Antes, sin embargo, es necesario familizarse con los ficheros de configuración y los distintos tipos de registro que pueden definirse en un servidor DNS.

Los ficheros de configuración

Toda la configuración de bind9 se encuentra dentro del directorio /etc/bind. El fichero básico de configuración es named.conf. Ese fichero, mediante sentencias include incluye los contenidos de otros dos (named.conf.options y named.conf.local), de manera que por regla general en debian no se habrá de tocar el fichero habitual sino los otros dos.

Esquemáticamente, los ficheros del directorio son:

named.conf,
es realmente el fichero de configuración. debian, sin embargo, delega parte de las configuraciones en otros dos ficheros, que vienen descritos a continuación.
named.conf.options,
es la parte de la configuración que se encarga de algunas opciones. La más importante es la definición de los forwarders. Estos son servidores a los que nuestro servidor DNS consultará las direcciones que no conoce, en vez de hacerlo directamente a los servidores raíz. Si estos servidores no son accesibles, entonces nuestro servidor preguntará a los servidores raiz. Si no se quiere, sin embargo, esto último se puede añadir la directiva:
forward only
named.conf.local,
es el fichero destinado a la definición de nuestras propias zonas. Siempre que se quiera incluir la definición de un dominio propio, habrá que declararla aquí y, después crear un fichero de tipo db.*, donde se desglosen las máquinas.
db.*,
distintos ficheros que definen cada una de los dominios. Por ejemplo, db.local, define la zona para la interfaz de loopback. db.root contiene la resolución de los servidores raíz. También es interesante db.empty, que es un fichero que se puede tomar como plantilla para definir nuestros propios dominios.

Además, el sistema está organizado de modo que se espera que la definición de nuestros dominios (sus ficheros db.*), se incluya dentro de /var/cache/bind.

Configuración inicial

Supongamos que para el dominio iescdl.tk definimos una máquina ns, que será el servidor de nombres, una máquina mail que será el servidor de correo, una máquina www que será el servidor web, una maquina ftp que será el servidor ftp y que coincide con el servidor web, y el router:

zona iescdl.tk
NombreIP
ns172.22.0.2
www172.22.0.2
ftpwww
mail172.22.0.2
smtpmail
pop3mail
imapmail
router172.22.0.1

Lo primero es indicarle a nuestro servidor si usaremos forwarder. Es aconsejable usar alguno, en vez de recurrir a los servidores raíz. Puede escogerse el de nuestro ISP, los de openDNS (208.67.222.222 ó 208.67.220.220) o incluso los de google que son fáciles de recordar (8.8.8.8 ó 8.8.4.4), por ejemplo. Tal cosa se hace descomentando las líneas apropiadas en named.conf.options.

forwarders {
   194.179.1.100;
   8.8.8.8;
   8.8.4.4;
};

Obsérvese que en este fichero hay una línea que dice:

directory "/var/cache/bind";

Es esta línea la que determina que, si no se especifica la ruta de algún fichero, este sea el directorio en el que se busque.

Declaremos ahora las zonas de resolución directa e inversa para el dominio iescdl.tk en named.conf.local:

zone "iescdl.tk" {
   type master;
   file "db.iescdl.tk";
};

zone "22.172.in-addr.arpa" {
   type master;
   file "db.iescdl.tk.rev";
};

Obsérvense las dos declaraciones de zone: la primera sirve para declarar el fichero que definirá la resolución directa de nombres, esto es, la conversión de una ip simbólica a una ip numérica. La segunda sirve para hacer lo contrario: preguntar por el nombre de una ip numérica. La palabra que acompaña a zone no es caprichosa: en el primer caso está claro: el nombre del subdominio; el segundo es algo más enrevesado: consiste en poner los bytes de la parte red en orden inverso (en vez de 172.22, 22.172) y añadir in-addr.arpa. Si la parte de red no son octetos completos entonces la cosa se complica bastante.

Dentro de cada declaración hay dos líneas. La segunda línea es el fichero en que asociaremos nombres a ips. La primera es el tipo (type), que puede ser master, slave o forward. Los dos primeros tipos declaran si el servidor es maestro o esclavo En esta configuración, sin embargo, sólo estamos configurando un maestro, así que es tipo es master. forward indica que para un determinado dominio se usará un servidor dns de apoyo. Por ejemplo:

zone "google.es" {
   type forward;
   forwarders {};
}

Si incluyésemos esto, el subdominio google.es se resolvería recurriendo directamente a los servidores raíz, ya que la lista de forwarders se dejó vacía.

Volvamos a nuestra configuración. Queda, por último, escribir los ficheros db.iescdl.tk y db.22.172. Para ello lo mejor es copiar db.empty y no empezar de cero:

# cd /var/cache/bind
# cp /etc/bind/db.empty db.iescdl.tk
# cp /etc/bind/db.empty db.22.172

Estos ficheros de definición de zonas se construyen incluyendo registros, así que antes de continuar con la configuración es necesario conocer qué tipos de registros pueden escribirse.

Registros y tipos de registros

Dentro de los ficheros db.* se incluyen las definiciones de las distintas zonas. Para ello se usan registros que tienen la siguiente forma:

<nombre_registro> [<TTL>] IN <tipo_de_registro> <valor_registro>

TTL, que es accesorio, es el tiempo en segundos de vigencia del nombre. Es accesorio, porque existe unha directiva global (también llamda TTL) que permite hacer una definición que se aplique a todos los registros.

En los servidores DNS hay distintos tipos de registros que cumplen distintas funciones, y los valores de nombre_registro y valor_registro depende de qué tipo de registro se esté definiendo.

SOA

En todo fichero de definición de zona hay un registro SOA, que sirve definir algunos aspectos de la propia zona y del resto de registros de la zona. Un registro SOA típico tiene el siguiente aspecto:

@   IN    SOA   localhost.  root.localhost. (
                       1   ; Serial
                  604800   ; Refresh
                   86400   ; Retry
                 2419200   ; Expire
                   86400 ) ; Negative Cache TTL

Obsérvese antes de nada que el nombre de registro es @. Este símbolo significa, simplemente, esta zona o este dominio. Si intentasemos pasar a lenguaje natural este trozo de código podríamos decir: el registro SOA para este dominio tiene el valor ... o una cosa parecida.

En cuanto al valor de registro, lo primero es la máquina que mantiene el archivo, lo segundo el correo electrónico de la persona encargada de mantenerlo (la @ está sustituida por un punto (.). El resto de parámetros son interesantes:

  • La versión del fichero: cada vez que hay un cambio en este fichero el valor se incrementa en uno.
  • El tiempo de de actualización, que es el tiempo en segundos que pasa hasta que un servidor esclavo vuelve a pedir una transferencia completa de la zona.
  • El tiempo de reintento, que es el tiempo en segundos que espera un servidor esclavo para volver a pedir una transferencia de zona, en caso de que fallase el anterior intento.
  • El tiempo de expiración, que es el tiempo en segundos que un servidor secundario considerará su propia información como fiable si no ha logrado volver a transferir los datos de zona del servidor primario. Tras este tiempo, el servidor secundario dejará de resolver los nombres del dominio.
  • El tiempo de vida, que es el tiempo en segundos que los servidores DNS deben considerar como válida la información del resto de registros. Por ejemplo, la información de un registro A que indica cuál es el nombre asociado a una ip. Durante este tiempo, estos servidores podrán mantener en su caché el dato sin tener que volverlo a preguntar al servidor autoritativo. Hay una directiva $TTL que permite alterar este valor.
A

Es el tipo de registro que indica cuál es el nombre de una dirección ip. Así por ejemplo, si la máquina www tiene la ip 172.22.0.2, el registro quedará así:

www            IN     A      192.168.20.31

Hay que hacer notar algo al respecto. Obsérvese que se ha incluido el nombre de la máquina, pero no el dominio. Esto es debido a que los registros aparecen dentro de los fichero db.* que ya se citaron y cada uno de estos ficheros desarrolla un dominio. Cuando el nombre no acaba con un punto, el software añade el dominio que se esté definiendo con el fichero. Si el fichero definía el dominio iescdl.tk entonces el registro anterior es equivalente a este otro:

www.iescdl.tk. IN     A      192.168.20.31

Es posible resolver un mismo nombre a dos direcciones ips distintas:

www     IN     A      192.168.20.31
               A      192.168.20.32

En este caso, el comportamiento habitual del servidor es devolver ambas resoluciones, pero cambiar alternativamente el orden en que se devuelven. Habitualmente, los clientes intentan la primera resolución y, si esta falla, intentan la segunda. El propósito de ir alterando el orden es balancear la carga entre ambas máquinas.

Existe una directiva $ORIGIN que permite cambiar el dominio de referencia dentro de estos ficheros. Ya se verá más adelante.

Los registros (estos de tipo A y los que se explicarán a continuación) tienen de modo predeterminado la vigencia que se hubiera indicado en el registro SOA (el campo TTL que se incluyó en último lugar). También es posible indicaresto mediante una directiva:

$TTL 86400

Sin embargo, es posible indicar un tiempo TTL particular para un registro, incluyendo el valor antes de la palabra IN:

www     300     IN     A      192.168.20.31

Indicar particularmente el TTL de un registro es aplicable al resto de tipos que se explican a continuación.

NS

Es el registro que define cuál es el servidor de nombres para el dominio que se espefique en el nombre de registro. Por ejemplo:

iescdl.tk.      IN      NS    ns

significa que la máquina ns.iescdl.tk (se ha puesto sólo ns, pero no se ha acabado en un punto el nombre) gestiona el dominio iescdl.tk (ojo con . final porque de lo contrario sería el dominio iescdl.tk.iescdl.tk). Como cuando nos queremos referir al propio dominio, se puede poner una @, la sentencia anterior podría ser simplemente:

@              IN      NS    ns

Por supuesto, esto no está del todo completo ya que ¿quién es la máquina ns.iescdl.tk? Así que a la línea anterior habría que añadir un registro de tipo A que lo indique:

ns             IN      A     172.22.0.2

Por tanto, para definir la máquina que hace de servidor de dominio necesitamos dos líneas:

@              IN      NS    ns
ns             IN      A     172.22.0.2
MX

Son los registros que indican cuál es el servidor de correo, es decir, los que indican a qué máquina deben ir dirigidos los correos de la forma xxx@iescdl.tk. Obsérvese que en la dirección de correo sólo se expresa el dominio, así que cuando un servidor de correo tiene que buscar al servidor de correo destino, no puede basarse exclusivamente en la dirección de correo: necesita consultar con dns cuál es la máquina que se encarga de la labor. Los registros se escriben así:

@              IN      MX    10 mail

Esto siginifica que el servidor de correo de este dominio (@) es la máquina llamada mail (o sea, mail.iescdl.tk). El extraño 10 indica la prioridad del servidor de correo, ya que para un mismo dominio puede haber definidos varios. Cuanto menor sea el número, mayor será la prioridad. Como en el caso anterior, la definición no está completa, porque no se conoce cuál es la ip Por ello se necesita un registro A que complemente a este:

mail           IN      A     172.22.0.2

Obsérvese que si en un dominio definimos un servidor de correo tendremos dos registros así:

@              IN      NS    ns
@              IN      MX    10 mail

En estos casos, podemos ahorrarnos la parte común y escribir simplemente:

@              IN      NS    ns
                       MX    10 mail
CNAME

Son registros que permiten dar un nombre alternativo a una máquina. Por ejemplo, si la máquina mail queremos que también se llame smtp podemos hacer:

smtp            IN     CNAME  mail
PTR

Son registro que hacen lo contrario que A, o sea, asociar ip numéricas a nombres de equipos:

2.0              IN     PTR    ns.iescdl.tk.

Obviamente no aparecerá ningun registro de este tipo en el fichero db.iescdl.tk, sino en db.iescdl.tk.rev

TXT

Son registros que nos permiten, simplemente, incluir información adicional sobre el propio registro. En muchas ocasiones se utlizan para identificar al propietario del registro.

@              IN      TXT   "Dominio IESCDL.TK"
                       NS    ns
                       MX    10 mail
SRV

Los registros SRV (abreviatura de SeRVice) sirven para declarar qué máquinas del dominio contienen determinados servicios y, además, establecer una preferencia para el caso en que varias máquinas ofrezcan un mismo servicio (esto último, sería una generalización de la prefeencia que permite establecer el registro MX para servidores de correo).

Tienen un aspecto algo más complicado que los vistos hasta ahora. Veámoslo con un ejemplo para el protocolo http:

_http._tcp.www   IN   SRV  0   2   80     www
                      SRV  0   1   80     www2
                      SRV  1   1   8080   w3

En estas líneas, _http._tcp.www viene a decir: cuando pidamos una página web (o sea protocolo de capa de aplicación http de la capa de transporte tcp) a la dirección www.iescdl.tk, dicho servicio se ofrecerá a través de tres máquinas www.iescdl.tk, www2.iescdl.tk y w3.iescdl.tk. Los número que acompañan a cada máquina indican la prioridad (cuando más pequeña, más prioritaria), el peso y el puerto de escucha. En el ejemplo, el servicio lo ofrecerán siempre www.iescdl.tk y www2.iescdl.tk por elpuerto 80, puesto que son más prioritarias, y sólo en caso de que ambas sean inaccesibles, se ofrecerá a través de w3.iescdl.tk por elpuerto 8080. Además, el peso de www.iescdl.tk es el doble de el de www2.iescdl.tk, por lo que dos de cada tres veces la petición debería ser resuelta como www.iescdl.tk.

Por supuesto, es necesario tener registros de tipo A que indiquen cuáles son las direcciones ip de www.iescdl.tk, www2.iescdl.tk y w3.iescdl.tk.

Desgraciadamente estos registros no son consultados por todos los servicios (de hecho, el servicio web no está entre ellos). Para más información consúltese esto.

Definición de las zonas

Volvamos a los ficheros de definición de zona. Teniendo en cuenta cómo se escribían los registros, el fichero para la resolución directa puede dejarse así:

Contenido de db.iescdl.tk

Obsérvese la última línea:

*              IN      CNAME www

Esta línea permite que cualquier nombre de máquina que no se haya definido, en vez devolver un error, resuelva a la máquina www, que es la que previsiblemente tiene el servidor web.

La resolución inversa, por su parte, puede hacerse así:

Contenido del fichero db.iescdl.tk.rev

Recuérdese que la zona es 22.172.in-addr.arpa, así que al escribir los registros debe incluirse lo que falta para completar la dirección: 2.0 y 1.0 (recuérdese que deben escribirse al revés). Aunque hay varios nombres que responden a la dirección 172.22.0.2 al hacer la resolución inversa es recomendable que sólo se indique uno.

Comprobación de los ficheros

Antes de levantar el servidor (o si lo hemos levantado y no funciona) es útil comprobar si tenemos erratas en los ficheros que hemos escrito. Para ello existen dos utilidades: named-checkconf y named-checkzone. Se usan del siguiente modo:

# named-checkconf /etc/bind/named.options.local
# named-checkzone castillo /var/cache/bind/db.iescdl.tk

Para usar el primero no hay más que indicar cuál es el fichero de configuración que se quiere probar. Para el segundo, hay que incluir como primer parámetro el dominio que define el fichero de zona.

El comando rdnc

rndc permite realizar algunas acciones interesantes. Por ejemplo, si se quiere borrar la caché basta con:

# rndc flush

Si se hace:

# rndc dumpdb  -cache

Lograremos volcar la caché en el fichero named_dump.db dentro de /var/cache/bind. En este fichero puede abservarse, por ejemplo, el tiempo que aún resta antes de que un determinado nombre vuelva a resolverse usando un dns externo. Obviamente este tiempo en la resta del TTL de registro y el tiempo que ha trascurrido desde que se realizó la consulta.

Por último,

# rndc reload

permite recargar los ficheros de zona sin reiniciar el servidor. Puede especificarse también una zona en particular:

# rndc reload iescdl.tk

También puede especificarse la vista de la que se recargara la zona:

# rndc reload iescdl.tk in vista-particular

Configuración con subdominios

Configuración de tres dominio: el dominio de segundo nivel (iescdl.tk) y uno de los de tercero (ingles.iescdl.tk) los gestiona el servidor principal; el otro de tercer nivel (frances.iescdl.tk) es delegado al servidor interno de esa red

El caso es un poco más enrevesado de lo que la lógica impondría: lo más sencillo, sería que todos los dominios los gestionase el servidor principal. Sin embargo, el hecho de que uno de ellos sea gestionado por otro servidor permite ver cómo se delegan subdominios.

Sin embargo, haremos una simplificación (al menos por ahora): no se configurará la resolución inversa de la red de inglés, debido a que no es una red pura de clase C y esto complica la configuración: se añadirá más tarde.

Esquemáticamente podemos representar así lo que queremos hacer:

DominioRedServidor
MaestroEsclavo
iescdl.tk172.22.0.0/16172.22.0.2-
frances.iescdl.tk192.168.10.0/24172.22.0.2-
ingles.iescdl.tk192.168.20.0/25192.168.20.2-

Configuración del dominio de primer nivel

En la declaración de zonas hay que introducir algunos cambios:

zone "iescdl.tk" {
   type master;
   file "db.iescdl.tk";
   forwarders {};
};

zone "22.172.in-addr.arpa" {
   type master;
   file "db.iescdl.tk.rev";
};

zone "frances.iescdl.tk" {
   type master;
   file "db.frances.iescdl.tk";
};

zone "10.168.192.in-addr.arpa" {
   type master;
   file "db.frances.iescdl.tk.rev";
}

Obsérvese que para el dominio iescdl.tk, se han eliminado los forwarders, incluyendo una lista de forwarders vacía. En otro caso, no se podrá hacer la resolución del dominio de segundo nivel ingles.iescdl.tk, porque al no estar gestionada aquí, se intentaría resolver acudiendo a los servidores externos. Se nota en este fichero la ausencia del dominio inglés, pero esto es debido a que no es gestionado aquí, sino delegado gracias al fichero de definición de la zona iescdl.tk.

En cuanto a los ficheros de definición de zonas, habría que escribir db.iescdl.tk, db.iescdl.tk.rev, db.frances.iescdl.tk y db.frances.iescdl.tk.rev. Todos los ficheros se escriben de modo semejante a como se hizo en el apartado anterior, excepto db.iescdl.tk que tiene que delegar inglés en uno de los servidors internos. Esta delegación se logra incluyendo estal líneas:

ingles     IN      NS     ns.ingles
ns.ingles  IN      A      192.168.20.2

Esto indica que ns.ingles.iescdl.tk es el servidor de nombres del subdominio ingles.iescdl.tk y que dicha máquina tiene la ip 192.168.20.2. Obsérvese que, como nuestro dominio es iescdl.tk, éste se añade automáticamente al no incluirse un punto final. Ahora bien, existe la directiva $ORIGIN, que permite modificar el dominio de referencia, así que lo de arriba también puede escribirse así:

$ORIGIN ingles.iescdl.tk.
@     IN      NS     ns
ns    IN      A      192.168.20.2

Si hubiera más delegaciones de subdominios, habría que repetir esto más veces. Haciendo estos cambios el fichero queda así:

Configuración de iescdl.tk con subdominio frances.iescdl.tk

Se ha añadido una delegación también para francés, aunque estrictamente no es necesario.

Configuración de los dominios de segundo nivel

La definición de los dominios de segundo nivel ha de hacerse la de frances en el propio servidor principal y la de inglés en el servidor interno de esta red. Se definen exactamente igual que se hizo para definir un dominio simple. Eso sí, en los servidores internos de francés e inglés habrá que forzar a que, cuando no sepa resolver, se recurra al servidor principal: así serán capaces de resolver cualquier máquina de los dominios iescdl.tk, frances.iescdl.tk e ingles.iescdl.tk. Por tanto, en el named.conf.options del servidor de inglés habría que escribir:

forwarders {
   192.168.20.1;
};

Y otro tanto parecido (pero 192.168.10.1) en el de francés. Además, en ambos servidores de segundo nivel se debería fijar dnssec-validation a no:

dnssec-validation no;

Investigar la validación...

Obsérvese que, si francés se hubiera delegado y no se definiera en el propio servidor principal, inglés seguiría siendo capaz de resolver los otros dos dominios, puesto que el servidor principal, aunque no gestionara francés, sí sabría como resolverlo.

Los ficheros que permiten esta configuración pueden descargarse de aquí.

Configuración con servidor esclavo

Configuración del modelo anterior con la adición del servidor esclavo en la contraparte.

En este caso no vamos a añadir ninguna red, sino redundacia a la configuración anterior: el servidor de francés hará de servidor esclavo de los dominios iescdl.tk y frances.iescdl.tk, el servidor de inglés del dominio iescdl.tk y el servidor principal hará de servidor esclavo del dominio inglés.iescdl.tk.

DominioRedServidor
MaestroEsclavo
iescdl.tk172.22.0.0/16172.22.0.2192.168.10.2
192.168.20.2
frances.iescdl.tk192.168.10.0/24172.22.0.2192.168.10.2
ingles.iescdl.tk192.168.20.0/25192.168.20.2172.22.0.2

Hay que hacer dos retoques a la configuración anterior:

  1. En la declaración de zonas (named.conf.local) hay indicar las zonas en las que se actuará como esclavo y decir, en las zonas en las que se actúa como maestro, a qué servidores (esclavos) se les transferirán registros.
  2. En la definición de zonas (db.*) habrá que incluir el servidor esclavo como servidor de nombres.

En el servidor principal hay dominios que deberán transferirse a servidores esclavos (iescdl.tk y frances.iescdl.tk) y dominios de los que se deberá requirir los registros al servidor maestro (ingles.iescdl.tk). Es por esto que ilustrando cómo debe configurarse él, se debería saber configurar los otros dos dominios. Su named.conf.local debería quedar así:

Configuración del servidor principal haciendo de esclavo del servidor interno.

Obsérvese que las zonas de las que es maestro han quedado de esta forma:

zone "iescdl.tk" {
   type master;
   file "db.iescdl.tk";
   also-notify { 192.168.10.2; 192.168.20.2; };
};

Se añade un also-notify con la dirección de los servidores esclavos. Las zonas esclavas quedan así:

zone "ingles.iescdl.tk" {
   type slave;
   masters { 192.168.20.2; };
};

En ellas se declara cuál es el servidor maestro. La segunda parte de la configuración es tocar los ficheros de definición para incluir los servidores también como servidor de nombres. En el caso del servidor principal habría que tocar los ficheros db.iescdl.tk, db.iescdl.tk.rev, db.frances.iescdl.tk y db.frances.iescdl.tk.rev. Por ejemplo:

Configuración del servidor principal haciendo de esclavo del servidor interno.

Las modificaciones consisten básicamente en añadir nuevos registros NS para los servidores esclavos. El resto de ficheros de definición debe modificarse análogamente.

Los servidores internos también habrá que modiifcarlos: el de francés no había sido necesario configurarlo hasta ahora, porque no gestionaba ningún subdominio: ahora habrá que incluir en su named.conf.local las cuatro zonas de las que es servidor esclavo (iescdl.tk, frances.iescdl.tk y las respectivas resoluciones inversas. El servidor de inglés, por su parte, también necesita modificación: de algunas zonas es maestro y de otras esclavo.

Sobre la adición en los ficheros de definición de los servidores esclavos y la cláusula also-notify hay que hacer una precisión: son redundantes, porque bind enviará notificaciones a los servidores de nombres que encuentre en el fichero de definición. also-notify está pensado para incluir otros servidores esclavos que no se encuentren incluidos en estos ficheros de definición. Por tanto, para nuestro caso, podríamos habernos ahorrado todas las cláusulas also-notify.

Configuración con resolución inversa en redes sin clase

Adición de la resolución inversa para la red de inglés (192.168.20.0/25)

Hasta ahora, cuando se han tratado resoluciones inversas, se han usado redes puras de clase C o de clase B. En general, lo expuesto es válido cuando se forman redes cuyas partes de red y de equipo son octetos completos. Ahora bien, ¿cómo se obra cuando esto no es así? Este es el caso de la red de inglés.

Una posible solución muy poco pulcra es meter la resolución inversa de todas las subredes dentro del fichero que resuelva la red completa (en este caso, 20.168.192.in-addr.arpa). Esta solución, para el caso que nos ocupa, no sería del todo mala, puesto que sólo hay una subred: sin embargo, cuando se usa una subred es porque el resto de subredes (o al menos parte de ellas) también van a usarse.

El RFC 2317 propone otra solución que permite dividir las subredes en ficheros distintos y que se basa en el uso del registro CNAME. La idea es la siguiente: se crean zonas distintas para cada subred, cuyo nombre es arbitrario. El propio RFC propone nombres que haga uso de la notación CIDR, lo cual en este caso significaría crear la zona 0/25.20.168.192.in-addr.arpa. Sin embargo, no es exigencia del método que esto sea así y, de hecho, el uso de la barra da problemas si se quiere configurar la actualización dinámica del dominio con bind. También es bastante usada la notación con rangos (1-127.20.168.192.in-addr.arpa). Sin embargo, ninguna de estas notaciones es adecuada si se quiere actualizar a través del servidor dhcp porque, como se entenderá más adelante, es necesario que el registro empiece con la ip puesta en orden inverso. Por ello, vamos nosotros a proponer una del tipo 20.168.192.subnet0-25.in-addr.arpa. De ser así, la declaración de las zonas de resolución inversa en el servidor de inglés queda así:

zone "20.168.192.in-addr.arpa" {
   type master;
   file "db.super-ingles.iescdl.tk.rev";
   also-notify { 192.168.20.1; };
};

zone "20.168.192.subnet0-25.in-addr.arpa" {
   type master;
   file "db.ingles.iescdl.tk.rev";
   also-notify { 192.168.20.1; };
};

El fichero de definición de la subred se hace como se ha venido viendo, así que db.ingles.iescdl.tk.rev debería tener este aspecto:

Contenido del fichero db.ingles.iescdl.tk.rev.txt

Ahora bien obsérvese que:

2   IN PTR  ns.ingles.iescdl.tk.

equivale, por la definición de la zona, a:

2.20.168.192.subnet0/25.in-addr.arpa.   IN PTR   ns.ingles.iescdl.tk.

y no a 2.20.168.192.in-addr.arpa, que es lo que se necesita para poder hacer la resolución inversa. Para resolver este inconveniente se puede incluir un registro CNAME en la zona 20.168.192.in-addr.arpa:

2   IN    CNAME 2.20.168.192.subnet0-25.in-addr.arpa.

Si se llenase el archivo con registros CNAME para cada una de las resoluciones necesarias se resolvería el problema. Ahora bien, esto exige escribir mucho. Para evitarlo, bind dispone de la directiva $GENERATE que permite generar automáticamente estas entradas:

Contenido del fichero db.castillo.rev.txt

Obsérvese cómo se indica el rango de números y que el signo $ representa el número para cada entrada automática.

Queda, además, incluir estas dos zonas como esclavas en el servidor principal. Todos los ficheros de configuración necesarios pueden obtenerse de aquí.

Configuración con actualizaciones dinámicas

Adición de un servidor DHCP en el servidor principal que sirve direcciones a la redes internas de francés e inglés y genera automáticamente nombres para las nuevas máquinas

Por tanto, no se añaden nuevas redes ni nuevos servidores DNS, pero será necesario habilitar un servidor DHCP en el servidor principal y reconfigurar su DNS para que admita actualizaciones automáticas.

Configuración del servidor DNS

La primera de las adiciones es la generación y definición de una clave que servirá para impedir que cualquiera pueda añadir registros indiscriminadamente. La generación puede hacerse con dnssec:

# dnssec-keygen -r /dev/urandom -a hmac-md5 -b 256 -n HOST rnc-key

...que generará un fichero K*.key que contendrá el valor de la clave generada. Este valor habría que copiarlo en un fichero, pero debian ya provee de un fichero adecuado con una clave que puede usarse (no obstante, puede generarse la clave y sustituir la clave generada de debian por la generada por nosotros):

# cat /etc/bind/rnc.key
key "rndc-key" {
        algorithm hmac-md5;
        secret "JY58MD+sP4FymdhgP1HoNw==";
};

Esta clave servirá para validar al cliente que intente realizar un actualización de registros en el servidor dns. En este caso concreto, el cliente será siempre el servidor dhcp del servidor principal; en cambio, el servidor dns no siempre es el mismo: cuando se añada una resolución de francés, el servidor será el principal, pero cuando se añada una de inglés el servidor será el interno que corre en dicha red. Por ello, lo más sencillo es tomar este misma clave y migrar al servidor de inglés, sobreescribiendo la que haya en él:

# scp /etc/bind/rndc.key root@192.168.20.2:/etc/bind/rndc.key

A continuación habrá que incluir la clave en la configuración del servidor y permitir actualizaciones automáticas. Esto debemos hacerlo tante en el servidor principal como en el de inglés. En el principal, debe añadirse lo siguiente al fichero named.conf:

include "/etc/bind/rndc.key";
controls {
   inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; };
};

La sentencia controls indica que se aceptarán conexiones sólo por la interfaz de loopback (inet), sólo para la máquina localhost y con la clave rndc-key: todo congruente con que sea el servidor dhcp de la propia máquina el que se encarga de pasar los nuevos nombres. Por otro lado, en la declaración de zonas (named.conf.local) debe incluirse la sentencia apropiada para permitir la actualización:

zone "frances.iescdl.tk" {
   type master;
   file "db.frances.iescdl.tk";
   also-notify { 192.168.10.2; };
   update-policy { grant "rndc-key" zonesub any; };
};

zone "10.168.192.in-addr.arpa" {
   type master;
   file "db.frances.iescdl.tk";
   also-notify { 192.168.10.2; };
   update-policy { grant "rndc-key" zonesub any; };
};

Con esto debería bastar para tener lista la actualización dinámica en el dominio frances.iescdl.tk, porque en el servidor esclavo, no es necesario cambiar nada. Ahora debe pasarse a hacer lo análogo en el servidor de inglés. A su named.conf hay que añadir:

include "/etc/bind/rndc.key";

acl rndc-users {
   192.168.20.1;
};

controls {
   inet 192.168.20.2 allow { rndc-users; } keys { "rndc-key"; };
};

Recuérdese que en este caso las actualizaciones se recibirán del servidor principal (192.168.20.1). Las declaraciones de zona deberían quedar así:

zone "ingles.iescdl.tk" {
   type master;
   file "db.ingles.iescdl.tk";
   also-notify { 192.168.20.1; };
   update-policy { grant "rndc-key" zonesub any; };
};

zone "20.168.192.in-addr.arpa" {
   type master;
   file "db.super-ingles.iescdl.tk.rev";
   also-notify { 192.168.20.1; };
};

zone "20.168.192.subnet0-25.in-addr.arpa" {
   type master;
   file "db.ingles.iescdl.tk.rev";
   also-notify { 192.168.20.1; };
   update-policy { grant "rndc-key" zonesub any; };
};

La zona 20.168.192.in-addr.arpa no recibirá actualizaciones puesto que simplemente tiene la cláusula GENERATE que remite a la zona 20.168.192.subnet0-25.in-addr.arpa.

Antes de configurar el servidor dhcp, es útil realizar una prueba manual para ver si se realiza la actualización:

root@servidorprincipal:~# cat | nsupdate -k /etc/bind/rndc.key
server ns.iescdl.tk
zone 10.168.192.in-addr.arpa
update add 100.10.168.192.in-addr.arpa. 86400 IN PTR fantasma.frances.iescdl.tk.
send
zone frances.iescdl.tk
update add fantasma.frances.iescdl.tk. 86400 IN A 192.168.10.100
send

Hecho esto, nuestra máquina debería ser capaz de resolver fantasma.frances.iescdl.tk. En principio, debería haberse añadido un registro al fichero db.frances.iescdl.tk y otro a db.192.168.10, pero puede ocurrir que en vez de eso se hallan creado ficheros .jnl, que son ficheros temporales y que en algún momento volcarán la información en el fichero correspondiente. Si queremos forzar a que esto ocurra podemos hacer:

# rndc freeze
# rndc unfreeze

Las dos órdenes en realidad suspenden las actualizaciones y las vuelven a reiniciar, pero el efecto secundario es que se escriben los cambios en el db.* correspondiente.

Para comprobar si el dominio inglés se actualiza automáticamente, conviene realizar una prueba similar. Adviértase que la prueba, en este caso, también tiene que hacerse en el servidor principal.

Configuración del servidor DHCP

Démosle una vuelta de tuerca a lo anterior: en vez de actualizar manualmente el dns, vamos a hacer que automáticamente un servidor dhcp vaya añadiendo los nombres de máquina al dominio, según conceda ips. Las estrategias pueden ser tres:

  • Que el nombre de máquina se fije en el fichero de configuración dhcpd.conf para una mac determinada.
  • Que el propio cliente indique cuál es el nombre que quiere que se le adjudique.
  • Que el servidor dhcp genere automáticamente nombres para las máquinas que se unen a la red.

Con estas ideas se puede escribir el siguiente fichero dhcpd.conf:

Configuración del servidor dhcp (dhcpd.conf)

El fichero contiene las explicaciones pertinentes, pero es aconsejable remarcar algunos aspectos:

  • El nombre que obtendrá la máquina lo determina la cláusula ddns-hostname. En este fichero se usa primero la opción host-name, y si no, un nombre generado automáticamente a partir de la dirección ip asignada (la opción comentada es para usar la dirección MAC). La opción host-name nunca se fija en este fichero, porque se espera que los clientes la fijen en su fichero /etc/dhcp/dhclient.conf:
    send option host-name "este-nombre-quiero";
    No obstante, para las máquinas conocidas que tienen un nombre (pagano y bautizado), ddns-hostname se redefine para que se les asigne ese mismo nombre.
  • La cláusula:
    primary 127.0.0.1
    indica al dhcp cuál es el servidor maestro dns al que comunicará las nombres. Este, a su vez, comunicará estas actualizaciones a los esclavos.
  • La opción:
    option domain-search        "frances.iescdl.tk", "iescdl.tk";
    permite pasar al cliente dos dominios de búsqueda: de este modo, si se indica un nombre de máquina sin dominio, si no es de la zona frances.iescdl.tk, se intentará hallar iescdl.tk.
  • El valor de la cláusula ddnds-rev-domainname es lo que se añade a la dirección ip puesta al revés para apuntar el registro PTR. Cuando se trata de una red pura (caso de frances.iescdl.tk) su valor basta con que sea in-addr.arpa, ya que para poder obtener, por ejemplo, la resolución de 192.168.10.100 necesitamos apuntar el registro 100.10.168.192.in-addr.arpa. Sin embargo, esto no es así para las redes no puras. Recordemos que tal y como hicimos esta resolución inversa necesitamos registros de la forma 100.20.168.192.subnet0-25.in-addr.arpa. Así pues, el valor de la cláusula en este caso será subnet0-25.in-addr.arpa. Esta es la razón por la que optamos por esta notación: la dirección ip completa en orden inverso siempre tiene que aparecer a la izquierda.
  • El nombre que obtiene la máquina no es excesivamente bonito: la máquina con ip 192.168.10.100 tendría como nombre host-192-168-10-100.frances.iescdl.tk. Puede complicarse un poco la sentencia para que quede mejor. Por ejemplo:
    option name  code 1234 = string;
    option name "pc";
    ddns-hostname = concat(config-option name,binary-to-ascii(10,8, "-", reverse(1,suffix(leased-address,2))));
    Esto permitiría obtener un nombre del tipo pc100-10.frances.iescdl.tk.

Configuración con vistas

Se añade una vista externa para que las máquinas de internet al consultar en el servidor las máquinas del dominio iescdl.tk, reciban la ip pública.

En este caso la configuración de las redes y los servidores es la misma: simplemente hay que configurar el servidor principal para que resuelva de distinto modo según cuál sea la ip de origen. El caso no es complicado porque la vista externa no va a recibir actualizaciones automáticas.

VistaDominioRedServidor
MaestroEsclavo
Externaiescdl.tk80.80.80.80172.22.0.2-
Internaiescdl.tk172.22.0.0/16172.22.0.2192.168.10.2
192.168.20.2
frances.iescdl.tk192.168.10.0/24172.22.0.2192.168.10.2
ingles.iescdl.tk192.168.20.0/25192.168.20.2172.22.0.2

Los cambios hay que hacerlos en el fichero donde se declaran las zonas, pero antes hay que comentar una línea en named.conf:

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

Esto es debido a que la declaración de zonas hay que hacer siempre dentro de una vista si estas se usan y named.conf.default-zones contiene declaraciones de zonas. Así pues, esta línea se vuelve a incluir dentro de las vistas que se incluyen en el fichero named.conf.local:

Configuración de named.conf.local con dos vistas

Obsérvense varias cosas:

  • Cómo es necesario definir qué clientes veran una vista y qué clientes otra, se ha definida una acl con los clientes que verán una de las vistas.
  • Las listas se definen con la cláusula view.
  • recursion determina si el servidor dns, además de sus zonas, resolverá el resto de dominios de internet. Obviamente para la el exterior es mejor que no.
  • allow-transfer indica las máquinas a las que se les permitirá realizar las transferencias de zona. Un servidor esclavo, por ejemplo, necesita tener permiso de transferencia. De modo predeterminado, se permite la transferencia a cualquier máquina. En el caso de la vista externa, se impide.
  • La cláusula match-clients dentro de cada vista permite indicar cuáles son los clientes de cada vista.
  • bind, para determinar qué vista verá un determinado cliente, procede a comprobar las cláusulas match-clients en el mismo orden en que se definieron las vistas dentro del fichero. Obsérvese que la vista vista-externa es para cualquier máquina (any), pero está colocada en segundo lugar, así que si la consulta es local o procede de las redes 172.22.0.0/16, 192.168.10.0/24 o 192.168.20.0/25, la vista que tendrá efecto es la vista-interna, porque es la primera.
  • Las tranferencia de zonas no dará ningún problema, porque el servidor interno ve la vista-interna. Tampoco la actualización, porque el servidor dhcp está en la misma máquina: a la hora de crear vistas hay que tener en cuenta cuál vista verán los servidores esclavos o, en caso de que se configure una actualización dinámica, el servidor dhcp.

Configuración con actualizaciones en dos o más vistas

A la configuración anterior se añade la red 172.31.0.0/16 y una tercera vista para esta red y para la 192.168.20.0/25.

La dificultad añadida de este nuevo caso es que a esta tercera vista queremos también que sea notificadas las actualizaciones automáticas. Ahora mismo, para la zona frances.iescdl.tk, el servidor dhcp notifica al servidor maestro (vista interna del servidor principal) el nuevo nombre y esta vista difunde la actualización a los servidores esclavos (francés). Para la zona ingles.iescdl.tk, el servidor dhcp notifica al servidor interno de inglés el nombre y este difundo el cambio a la vista interna del servidor principal. Sin embargo, ahora no habra una única vista interna y, sin embargo, queremos que ambas vistas reciban las notificaciones. La táctica para lograr esto es hacer que las actualizaciones se realicen primeramente en una vista y que esta vista la notifique a la otra.

Para resolver este embrollo podemos escribir así el named.conf.local:

Configuración de named.conf.local con dos vistas dinámicas

Véase que hay dos acls: adsl y tic, cada una con las redes que deben ver una vista particular. En ambas, sin embargo, se encuentra localhost, ya se verá por qué. Es necesario desdoblar las resoluciones directa e inversa de iescdl.tk para que se obtengan ips de la red 172.22.0.0 o 172.31.0.0 dependiendo de qué máquina sea la que pregunte. Por otro lado, es en la vista vista-tic es la que se van a recibir las notificaciones exteriores: ya sea del servidor dhcp (caso de la zona frances.iescdl.tk), ya sea del servidor dns de inglés (caso de la zona ingles.iescdl.tk).

La configuración propuesta funciona del siguiente modo:

  1. La actualización de frances.iescdl.tk es provista por el servidor dhcp. Esto es una conexión local, pero se usa la clave rndc-key para ello. Como vista-adsl tiene esta cláusula:
    match-clients { !key rndc-key; adsl; }; 
    aunque la conexión es local y está declarada primero, no es elegida a causa de la clave; así que la actualización acaba en la zona maestra que está declarada en vista-tic. Esta vista a su vez, propaga la actualización al servidor esclavo de francés y a localhost. Esta propagación, sin embargo, no usa la clave, así que es vista por vista-adsl y recibe la actualización la zona esclava. De este modo, la actualización está disponible en ambas vistas.
  2. Por su parte, la actualización de ingles.iescdl.tk es realizada primero en el servidor interno de ingles. Este difunde la actualización al servidor principal, que la recibe por su vista-tic, puesto que el origen es la red 192.168.20.0/25. La vista esclava que hay definida aquí, a su vez, la difunde a localhost, difusión que es vista por vista-adsl al estar declarada antes. De nuevo, la actualización acaba siendo conocida por ambas vistas.

Otra solución (quizás menos enrevesada y que, además, permitiría más de una vista esclava, es hacer uso de la cláusula notify-source, que indica con que dirección de origen se realizarán las notificaciones:

Configuración de named.conf.local con dos vistas

En este caso, en vista-tic se incluye la cláusula:

notify-source  172.31.0.2;

lo cual significa que todas las notificaciones que haga a servidores esclavos tendrán como dirección de origen tal dirección ip. Además las notificaciones (also-notify) que antes hacía a 127.0.0.1 (y que iban dirigidas a la vista-adsl, ahora se dirigen a 172.22.0.2:

also-notify { 172.22.0.2; };

Esto hecho en las zonas maestras del servidor principal debe ir acompañado con que en las zonas esclavas se indique que el servidor maestro es la dirección 172.31.0.2. Por ese motivo, tanto en las zonas esclavas de la vista-adsl como en del servidor esclavo de frances hay que escribir:

masters { 172.31.0.2; }:

La configuración final puede descargarse de aquí.

Bibliografía

  1. Cómo funcionan las consultas DNS
  2. Subdomains of in-addr.arpa Domains
  3. Views in BIND 9: Vistas.
  4. A DNS Primer: Excelente artículo sobre DNS. La página tiene artículos interesantes sobre otras masterias.