6.2.4. dnsmasq

dnsmasq más que un servidor DNS es un proxy DNS que al responder a la petición de un cliente la cachea, a fin de que para la siguiente respuesta no sea necesaria la consulta remota. Por este motivo, algunas distribuciones lo incluyen en sus instalaciones para equipos de escritorio.

Sin embargo, permite también de forma limitada la definición de registros DNS por lo que puede usarse como tal, si nuestras pretensiones son modestas. En lo referente a este servicio sus limitaciones más evidentes son:

  • El tratamiento de varios dominios puede ser confuso y engorroso.

  • Tiene limitado el soporte DNSSEC: es capaz de validar registros de servidores externos o no hacerlo y pasar a los clientes el registro de firma (véase más adelantee <dnsmasq-dnssec>), pero no puede firmar automáticamente los registros propios, como sí hace bind.

Para discutir sobre la configuración supongamos que el servidor tiene por dirección 192.168.255.1 y que deseamos que nuestra red sea el dominio example.net.

Ver también

Para saber cómo están estructurados los ficheros de configuración, revise lo comentado en la configuración para DHCP.

6.2.4.1. Preliminares

Nota

Esta preparación del sistema es aplicable a la instalación de cualquier otro servidor DNS.

6.2.4.2. Principos de funcionamiento

dnsmasq por defecto:

  1. Levanta el servidor DNS, así que éste funcionará a menos que lo deshabilitemos incluyendo la directiva:

    port=0
    
  2. En principio, se usan como servidores de consulta, los servidores incluidos en /etc/resolv.conf.

    Nota

    Advierta que por ello la propia máquina en que está instalado dnsmasq no puede usarlo como servidor DNS, puesto que eso exigiría colocar en tal fichero 127.0.0.1 y el resultado es que dnsmasq se preguntaría a sí mismo. Ya veremos como solucionar esto.

  3. Hay dos fuentes principales para la definición de registros propios:

    • Las definiciones hechas en /etc/hosts, de modo que si queremos definir un registro de tipo A, basta con incluir una línea en este fichero.

    • Si se ha habilitado el servicio DHCP y se han declarado máquinas con nombre, se asignará dinámicamente este nombre en el servicio DNS.

En conclusión, que con solo instalar el paquete podremos hacer que el resto de máquinas de la red sean capaces de usar ésta cono servidor DNS. Además, las definiciones que hayamos hecho en /etc/hosts también serán resolubles.

6.2.4.3. Servidores de consulta

Puede interesarnos usar otros servidores de consulta distintos a las nombreado en /etc/resolv.conf. La razón principal puede ser que queramos usar dnsmasq como el servidor DNS para la propia máquina lo que nos obligaría a crear así /etC/resolv.conf:

# /etc/resolv.conf
domain example.net
search exameple.net
namserver 127.0.0,1

Si no tocáramos nada más, esto supondría que dnsmasq se preguntara a sí mismo y acabáramos por no obtener ninguna resolución. Para sustituir la lectura de este fichero por la de otro podemos crear un fichero /etc/dnsmasq.d/dns.conf con la siguiente configuración:

# /etc/dnsmasq.d/dns.conf

resolv-file=/etc/resolv.dnsmasq.conf

e incluir dentro del fichero referido por resolv-file los servidores de consulta:

# /etc/resolv.dnsmasq.conf

nameserver 1.1.1.1
nameserver 1.0.0.1

Ahora sí podríamos alterar /etc/resolv.conf para que incluya como servidor de nombres 127.0.0.1.

Una alternativa a esto es impedir que se lea /etc/resolv.conf y definir dentro de la propia configuración los servidores de consulta:

no-resolv
server=1.1.1.1
server=1.0.0.1
server=/google.com/8.8.8.8

en este caso puede usarse la directiva server varias veces para definir varios servidores de consulta y, además, puede restringirse el servidor de consulta a un dominio (o varios) exclusivamente. En el ejemplo, todas las resoluciones se hacen con 1.1.1.1 y 1.0.0.1, excepto los nombres del dominio google.com para los cuales se usará el servidor 8.8.8.8.

6.2.4.4. Definición estática de nombres

Ya se ha dicho que dnsmasq comparte las definición incluidas en /etc/hosts, lo que significa que una definición dentro de ese fichero como esta:

192.168.255.1     ns.example.net    ns
192.168.255.5     mail.example.net  mail

provoca que todos las máquinas que usen nuestro servidor sean capaces de hacer la resolución directa de tales nombres:

$ host mail.example.net
mail.example.net has address 192.168.255.10

Además, es posible añadir otros ficheros como fuente de registros:

no-hosts
addn-hosts=/etc/hosts.d/example.net

Como puede verse estas definiciones se corresponden, exclusivamente, con registros de tipo A. Este mismo tipo de registros también puede añadirse dentro de la propia configuración con la directiva host-record. Por ejemplo:

host-record=mail.example.net,192.168.255.5

Nota

La diferencia entre añadir directamente la definición en la configuración o usar ficheros aparte (el primer caso) no es sólo de pulcritud: para releer la configuración es necesario reiniciar el servidor mientras que los ficheros aparte de definición de máquinas se releen simplemente con madar una señal SIGHUP al servidor (o sea, haciendo un kill -1).

Cuando la interfaz posee una IP dinámica, es posible también hacer esta definición:

interface-name=ext.example.net,eth0

que calcula la IP consultando cuál es la que tiene asignada la interfaz suministrada.

Cualquier otro tipo de registro, sólo es posible incluirlo dentro de la configuración y no en fichero aparte con la directiva adecuada. Un registro MX podemos añadirlo así:

mx-host=example.net,mail.example.net

suponiendo que ya tengamos definida la máquina con nombre smtp. También es posible definir alias:

cname=smtp.example.net,mail.example.net

y ahorrarnos el dominio del objetivo (mail.example.net en este caso), si coincide:

cname=smtp.example.net,mail

Ver también

Para otro tipo de registros, consulte la página del manual.

6.2.4.5. Definición de zonas

Ya hemos apuntado en el apartado anterior cómo definir máquinas, y éstas se pueden definir de una forma anárquica, ya que dnsmasq permite asociar nombres e IP sin importar a que dominio pertenezcan estos nombres. Por ejemplo, si en /etc/hosts añadimos lo siguiente:

192.168.255.2     www.facebook.com
192.168.255.2     www.twitter.com
192.168.255.2     www.instagram.com

los clientes que resuelvan nombres con nuestro servidor obtendrán esa IP al intentar acceder a cualquiera de esos sitios web. Como se ve, a diferencia de lo que hacemos en bind no definimos una zona en concreto. Esa es una de las virtudes de dnsmasq que propicia que se use, por ejemplo, como sumidero DNS.

Ahora bien, si planteamos dar nombres DNS a los ordenadores de una LAN y usar dnsmasq para ello, lo que nos interesa es poder emular la filosofía de bind y crear zonas. O dicho de otro modo, supongamos que con bind tenemos esta configuración[1]:

# /etc/bind9/named.conf.local
zone "example.net" {
   type master;
   file "db.example.net";
   forwarders {};
}

# /var/cache/bind/db.example.net
# Definición del registro SOA...
@        IN    NS       ns
               MX       1 mail
ns       IN    A        192.168.255.1
mail     IN    A        192.168.255.1
smtp     IN    CNAME    mail
imap     IN    CNMAE    smtp

porque nuestro servidor tiene una red externa a la que accede a través de la interfaz eth0 y otra interna conectada a eth1 (192.168.255.1) y cuya red es la 192.168.255.0/24. Esta red interna es la que se quiere asociar al dominio example.net.

Sabemos qye una configuración así tiene este efecto:

$ host -t ns example.net
example.net name server ns.example.net
$ host ns.example.net
ns.example.net has address 192.168.255.1
$ host smtp.example.net
smtp.example.net is an alias for mail.example.net.
mail.example.net has address 192.168.255.1

Para lograr lo propio podemos escribir un fichero /etc/dnsmasq.d/dns.conf con esta configuración general:

# Puede descomentarse para depuración.
#log-queries

no-hosts  # No queremos consultar /etc/hosts (opcional)
expand-hosts

y /etc/dnsmasq.d/example.conf que defina la zona example.net:

auth-zone=example.net,eth1
auth-server=ns.example.net,eth1
domain=example.net,192.168.255.0/24

addn-hosts=/etc/hosts.d/eth1   # Aquí podemos meter registros A.

# Registro MX
mx-host=example.net,mail.example.net

# CNAMEs
cname=smtp.example.net,mail
cname=imap.example.net,mail

Por último podemos crear los registros A en /etc/hosts.d/eth1:

192.168.255.1  ns    mail

La justificación de esta configuración es la siguiente:

  • En dns.conf hemos añadido configuración general relativa al servicio DNS, esto es, configuración común a todas las zonas que pretendiéramos definir.

  • En eth1.conf hemos incluido configuración referente únicamente al dominio example.net correspondiente a la interfaz eth1 y la red 192.168.255.0/24. Si tuviéramos otros dominios, otras interfaces internas y otras redes, podríamos escribir ficheros con contenido análogo.

  • expand-hosts evita tener que añadir el dominio constantemente en el fichero /etc/hosts.d/eth1. Sin la directiva tendríamos que haber escrito:

    192.168.255.1  ns.example.net    mail.example.net
    

    Esta directiva, no obstante, sólo añade el dominio en las máquinas declaradas en ficheros hosts y no registros incluidos dentro de la propia configuración.

    Por otro lado, para que esta directiva tenga efecto es necesario añadir también la directiva domain, aunque esta está relacionada con el servicio DHCP.

  • auth-zone convierte a nuestro servidor dnsmasq en el servidor autoritario del dominio example.net, lo que implica que jamás se resolverán máquinas de este dominio recurriendo a los servidores externos de internet que hayamos configurado. Dicho de otro modo. www.example.net es una máquina que existe en internet. Si no incluimos esta directiva y no definimos nosotros la máquina www, dnsmasq nos devolverá la IP pública asociada a este nombre, porque la consultará al servidor externo. Con la directiva en cambio, devolverá un error de registro no encontrado.

    Hemos añadido, además, la interfaz eth1, lo que tiene el efecto de que dnsmasq calcule a partir de la configuración de esta interfaz cuál es la red asociada (192.168.255.0/24). De hecho, podríamos haber escrito directamente la red. Este segundo parámetro es opcional, pero al incluirlo y relacionar el dominio con la red, dnsmasq habilitará la resolución inversa. Por tanto:

    $ host 192.168.255.1
    1.255.168.192.in-addr.arpa domain name pointer ns.example.net.
    
  • auth-server es la directiva encargada de definir el registro NS de la zona que estamos definiendo. Por tanto, tiene el efecto de generar este registro:

    @     IN    NS    ns.example.net.
    

    Obviamente este nombre debe tener asociado alguna IP.

    Nota

    Cuando queramos definir con dnsmasq una zona resoluble desde internet, es necesario incluir obligatoriamente esta directiva. Esta directiva, además, hace que para las peticiones referidas por la interfaz indicada, dnsmasq no permita consultas recursivas, esto es, consultas que no pregunten por nombres de la propia zona. Es, pues, bastante probable que se quiera incluir esta directiva cuando la interfaz se trata de una interfaz externa. Para más información, consúltese esta respuesta en la lista de distribución del programa

  • addn-hosts nos permite indicar cuál será el fichero donde incluyamos los registros A.

  • El resto del fichero eth1.conf define registros de otro tipo: uno MX y dos CNAME.

DHCP

Como estamos configurando el dominio para una LAN y lo hemos asociado a una red (192.168.255.0/24) es probable que también nos interese ofrecer DHCP con el propio dnsmasq.conf. En ese caso bastaría con incluir un fichero /etc/dnsmasq.d/dhcp.conf con la siguiente configuración general:

dhcp-autoritative
# log-dhcp           # Descomentarlo en caso de querer depurar.

y dentro de /etc/dnsmasq.d/example.conf, añadir al final del archivo la configuración que deseemos para DHCP:

dhcp-range=192.168.255.64,192.168.255.127,10m

# Configuración adicional referente al DHCP

Vistas

dnsmasq dispone de localise-queries para que el caso de que si un mismo nombre está asociado a distintas IP, no se devuelvan todas sino que se devuelva aquella que pertenece a la red de la interfaz por la que se recibe la petición. Sin embargo, la directiva no se lleva bien con auth-server.

6.2.4.6. Gestión de una zona de internet

Bajo el epígrafe expondremos cuál es una configuración apropiada para la gestión de una zona de internet que poseamos, partiendo de las siguientes suposiciones:

  • Hemos contratado un VPS o un servidor dedicado con una dirección IPv4, que se encuentra asociada a su interfaz eth0.

  • Deseamos gestionar en dicha máquina el subdominio vps.example.net para lo cual en la zona example.net habrá declarado lo siguiente:

    mi-vps      IN       NS    vps
                          A    IPv4.DE.MI.VPS
    
  • No tiene por qué ser así, pero lo habitual es que todos los nombres resuelvan a la IP de la máquina, que es la IP de la interfaz.

Obsérvese que nuestro servidor gestionará la zona vps.example.net, pero en absoluto controlamos nuestra IP (que, simplemente, nos es concedida por nuestro proveedor como parte de su servicio) y mucho menos disponemos de la subred en que se incluye nuestra IP. En este contexto, es absurdo que nuestro dnsmasq pretenda encargarse de resolución inversa alguna[2].

La configuración puede ser esta:

# /etc/dnsmasq/dns.conf
no-resolv
server=1.1.1.1
server=1.0.0.1

no-hosts

auth-zone=vps.example.net
auth-server=mi-vps.example.net,eth0

# Nombres asociados a la propia máquina
interface-name=www.vps.example.net,eth0
interface-name=mail.vps.example.net,eth0

# Nombres asociados a otros máquinas
addn-hosts=/etc/hosts.d/vps.example.net

# MX
mx-host=vps.example.net,mail.vps.example.net

# CNAMEs
cname=smtp.vps.example.net,mail
cname=imap.vps.example.net,mail

que presenta algunas diferencias respecto a la propuesta para la definición de una zona:

  • No añadimos red o interfaz a la directiva auth-zone, porque no pretendemos realizar ninguna resolución inversa, al no ser dueños de ninguna subred.

  • No añadimos la directiva domain ni expand-host porque no somos dueños de ninguna subred.

  • Aunque la IP pública es fija (más nos vale), preferimos leerla de la interfaz (con interface-name), en vez de incluirla en la configuración (p.e. dentro del fichero :file: /etc/hosts.d/vps.example.net).

  • El fichero :file: /etc/hosts.d/vps.example.net lo creamos por si deseamos proporcionar nombre de nuestra zona a otras máquinas distintas de la de nuestro servidor, por ejemplo, otro VPS en el que no disponemos ningún servidor DNS, pero en el que configuramos algún servicio para el que queremos asignar un nombre del dominio vps.example.net.

6.2.4.7. Gestión de una zona interna

6.2.4.8. DNSSEC

dnsmasq tiene un soporte parcial para DNSSEC, ya que es capaz de comprobar la validez de un registro a través de su registro de firma para las consultas que haga a los servidores que tenga definidos; pero, sin embargo, no es capaz de generar registros automáticos de firma para los registros que el mismo gestiona (example.net en nuestro ejemplo).

Con respecto a DNSSEC, dnsmasq puede actuar de tres formas:

  1. Sin configuración específica, pasa la respuesta de su servidor de consulta, pero eliminado los datos referentes a DNSSEC, por lo que se perderá el bit AD y, en consecuencia, el cliente no sabrá si la respuesta está verificada o no.

    Nota

    En este caso, si el servidor de consulta no realiza comprobaciones no se obtendrá error jamás, mientras que se obtendrá un SERVFAIL si el servidor realiza comprobaciones y la verificación falla.

  2. Si se añade la directiva:

    proxy-dnssec
    

    se actúa como en el caso anterior, pero se transmite el bit AD al cliente, por lo que este podrá saber si se realizó verificación o no.

  3. Si se desea que el propio dnsmasq se encargue de la verificación, lo cual es útil, si el servidor de consulta no la realiza o no nos fiamos de él, podemos configurar del siguiente modo:

    dnssec
    dnssec-check-unsigned
    conf-file=/usr/share/dnsmasq-base/trust-anchors.conf
    

    Nota

    El fichero contiene los registros DS para la zona «.» que publica la IANA.

6.2.4.9. Bloqueo DNS

Es habitual que necesitemos evitar el acceso a determinados sitios web. Para ello existen proxies web, pero cuando el tráfico es seguro (y esto es ya lo más frecuente), la cabecera HTTP está cifrada. Puede aún seguirse filtrado mediante proxy usando la SNI, pero una solución alternativa bastante más ligera y sencilla, es a través de la petición DNS que se hace con la resolución[3] previa.

dnsmasq puede permitir el bloqueo de estos sitios, haciendo que la resolución de las máquinas o los dominios indeseados se haga a una IP inexistente o a la IP de una máquina en la que dispongamos un servidor web que devuelva una página con el aviso de prohibición.

Para lograrlo podemos crear un fichero /etc/dnsmasq.d/filter.conf con un contenido como éste:

# /etc/dnsmasq.d/filter.conf
address=/facebook.com/0.0.0.0      # No se puede acceder a máquinas del dominio completo
addn-hosts=/etc/hosts.banned.conf  # Para incluir máquinas individuales.

Con la configuración anterior, cualquier máquina del dominio facebook.com se resolverá a 0.0.0.0 con lo que el acceso será imposible y, además, se dispone un fichero para incluir direcciones de máquinas individuales. Podemos repetir tantas veces como deseemos la opción address, así que podremos bloquear tantos dominios como deseemos.

Nota

Está técnica recibe el nombre de sumidero de DNS y es muy empleada para evitar los sitios dedicados a albergar anuncios. Un ejemplo de software que se basa en esta técnica y usa al propio dnsmasq es pi-hole.

6.2.4.10. DNS dinámico

Advertencia

Es importante que definamos dominios para las redes a las que brindemos servicio DHCP:

dhcp-range=192.168.255.128,192.168.255.191,8h
domain=aula.ies,192.168.255.0/24

En dnsmasq, podemos lograr la inclusión dinámica en su propio DNS de las máquinas que reciben configuración de red, pero un soporte personalizado requiere algo de configuración.

En principio, todas las máquinas que tengan asociado un nombre pasan al DNS. Esto es aplicable a aquellas a las que en la configuración se les haya definido un nombre:

dhcp-host=00:11:22:33:44:55,profesor

pero también a aquellas cuyo cliente envía su propio nombre. Para estas segundas, no obtante, podemos evitar la inclusión incluyendo la directiva:

dhcp-ignore-names

El problema, pues, son aquellas que no se incluyen automáticamente. La razón, obviamente, es que dnsmasq no tiene nombre para ellas. Para resolverlo, dnsmasq implementa la directiva dhcp-generate-names que asigna como nombre de máquina a aquellas que no lo tienen la dirección MAC en que se sustituyen los dos puntos por guiones[4]:

dhcp-generate-names

La desventaja de este método es que no podemos elegir el formato del nombre. Si nuestra intención es personalizar el formato, entonces la directiva anterior es inútil y no hay más solución que utilizar dhcp-script que permite definir el script que se ejecutará cada vez que haya un cambio en las asignaciones del DHCP. La idea es que este script cree el nombre dinámico para las máquinas que no disponen de él, según el formato que definamos denhtro de él y gestione el contenido de un fichero hosts, en donde iremos metiendo y sacando equipos según obtengan o revoquen direcciones.

En tal caso para la configuración de dnsmasq, podemos crear un fichero /etc/dnsmasq.d/ddns.conf con el siguiente contenido:

addn-hosts=/tmp/dynamic.hosts
dhcp-scripts=/var/lib/dnsmasq/ddns.sh
dhcp-ignore-names  # Opcional

y añadir en su ruta correspondiente el script ddns.sh.

Notas al pie