Table of Contents

Activar DoT (DNS over TLS) y/o DNSSEC en sistemas GNU/linux

DNS mediante TLS (DoT, siglas en inglés de DNS over TLS) es un protocolo de seguridad para cifrar y ajustar las consultas y respuestas del sistema de nombres de dominio (DNS) a través del protocolo de seguridad de la capa de transporte (TLS). El objetivo del método es aumentar la privacidad y la seguridad del usuario mediante la prevención de escuchas ilegales y la manipulación de los datos del DNS a través de ataques de intermediario.

Las extensiones de seguridad para el sistema de nombres de dominio (Domain Name System Security Extensions o DNSSEC, por sus siglas en inglés) son un conjunto de especificaciones de la Internet Engineering Task Force (IETF) para asegurar cierto tipo de información proporcionada por el sistema de nombres de dominio (DNS) que se usa en el protocolo de Internet (IP). Se trata de un conjunto de extensiones para el DNS que proporcionan a los clientes DNS (o resolvers), la autenticación de origen de los datos DNS, denegación de existencia de autenticación y la integridad de los datos, pero no la disponibilidad o confidencialidad.

DNS vs DNSSEC: DoT garantiza una comunicación cifrada, integridad de los datos recibidos y que el servidor que contesta es el solicitado. Pero no garantiza que la información que se recibe sobre la IP del dominio es real. Para asegurar que la resolución de nombre recibida es la autentica se necesita “DNSSEC”. Este hace uso de PKI para comprobar que la cadena de peticiones DNS que se realiza entre los DNS Raiz, DNS de zonas, etc hasta llegar al servidor que le da resolución es legítima. Si se recibirá una contestación que no pudiera ser verificada correctamente, esta sería descartada. Lógicamente la implementación de DNSSEC ralentiza un poco la resolución de nombres, pero oferta muy buena seguridad en combinación con DoT ya que carece de cifrado.

La configuración presentada permite que toda solicitud DNS realizada en el sistema se haga sobre TLS, independientemente de la aplicación. Por lo que por ejemplo no sería necesario el uso de DoH en navegadores u otros programas. DNSSEC está en el ejemplo propuesto desactivado, lamentablemente existen todavía muchos subdominios con problemas que hacen que su activación pueda perjudicar en gran medida la navegación. Véase el apartado DNSSEC para comprender el motivo.

Configurar el fichero “/etc/systemd/resolved.conf” (En el ejemplo se usa IPv6, recordar que no todas las conexiones a Internet soportan IPv6).

[Resolve]
# Servidores DNS compatibles con DOT (Va variando el uso de los servidores, no siempre se usa el mismo). Listado DNS DoT: https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers
DNS=1.1.1.1 9.9.9.10 9.9.9.9 145.100.185.16 89.233.43.71 145.100.185.18 2a04:b900:0:100::37 2606:4700:4700::1111
# Servidores que se usarán si fallan los anteriores.
FallbackDNS=2606:4700:4700::1111 2620:fe::10 2001:4860:4860::8888 37.252.185.232 2606:4700:4700::1001
#Domains=
LLMNR=no
MulticastDNS=no
#DNSSEC=allow-downgrade
DNSSEC=false                # Si se desea activar DNSSEC "true" sería lo correcto. Otra opción disponible es "allow-downgrade", que permite no usar DNSSEC si el servidor no lo soporta.
#DNSOverTLS=opportunistic   # Con esta opción, si no hay posibilidad de usar DOT, se usará DNS en claro.
DNSOverTLS=yes              # Activamos resolución únicamente mediante DOT.                                                                           
#Cache=yes
#DNSStubListener=yes
ReadEtcHosts=yes

Editar el fichero /etc/hosts: Se pueden crear también enlaces simbólicos a /run/systemd/resolve/stub-resolv.conf, pero al usar el fichero /etc/resolv.conf con la dirección 127.0.0.53, si se usan VPN u otras aplicaciones que editen el fichero /etc/resolv.con temporalmente, dará menos problemas.

nameserver 127.0.0.53

Activamos el servicio y lo configuramos como activo al inicio del sistema.

systemctl enable systemd-resolved

NOTA: Si se va a suar DNSSEC hay que estar seguro de que todos los servidores definidos los soportan, porque no todos los servidores soportan DoT + DNSSEC. Se recomienda previamente leer la sección de DNSSEC de esta guía.

resolvectl

Este comando es una especie de “dig” que interactúa directamente con systemd.resolved.

Comprobar que systemd-resolved está resolviendo correctamente.

resolvectl query busindre.com

Consultar registros MX / AAAA (IPv6)

resolvectl query sigok.verteiltesysteme.net -t MX
sigok.verteiltesysteme.net: resolve call failed: Name 'sigok.verteiltesysteme.net' does not have any RR of the requested type
 
resolvectl query busindre.com -t MX
busindre.com IN MX 10 mxxt2.mbox.org                    -- link: enp2s0
busindre.com IN MX 0 mxxt3.mbox.org                     -- link: enp2s0
busindre.com IN MX 10 mxxt1.mbox.org                    -- link: enp2s0
 
-- Information acquired via protocol DNS in 267.2ms.
-- Data is authenticated: no
 
# Ejemplo de validación DNSSEC fallida de un dominio,
resolvectl query sigfail.verteiltesysteme.net
sigfail.verteiltesysteme.net: resolve call failed: DNSSEC validation failed: invalid
 
# Sin tener DNSSEC activado, algunos DNS como los de google, no devuelven resoluciones de dominios con firmas erroneas. Se puede probar con estos dos comandos.
dig @205.185.112.68 sigfail.verteiltesysteme.net # No Google DNS
dig @8.8.8.8 sigfail.verteiltesysteme.net        # Google DNS
 
 
# Estos dos comandos deben obtener el mismo resultado pese a que usen diferentes parámetros.
resolvectl -6 query busindre.com
resolvectl query busindre.com -t AAAA

Estado de la configuración de DNS de “systemd-resolved” actual.

resolvectl status
 
Global
       LLMNR setting: no
MulticastDNS setting: no
  DNSOverTLS setting: yes
      DNSSEC setting: no
    DNSSEC supported: no
  Current DNS Server: 2a04:b900:0:100::37
         DNS Servers: 1.1.1.1
                      9.9.9.10
                      9.9.9.9
                      145.100.185.16
Fallback DNS Servers: 2606:4700:4700::1111
                      2620:fe::10
                      2001:4860:4860::8888
          DNSSEC NTA: 10.in-addr.arpa
                      16.172.in-addr.arpa
                      ...

Estadísticas de uso (solicitudes DNS resueltas, cacheadas, etc).

resolvectl statistics
 
DNSSEC supported by current servers: no
 
Transactions
Current Transactions: 0
  Total Transactions: 1053
 
Cache
  Current Cache Size: 41
          Cache Hits: 451
        Cache Misses: 608
 
DNSSEC Verdicts
              Secure: 0
            Insecure: 0
               Bogus: 0
       Indeterminate: 0

Borrar la cache DNS.

resolvectl flush-caches

Obtener información de los dominios cacheados y información relevante relacionada.

killall -USR1 systemd-resolved # No terminará el proceso, no hay que preocuparse por ello.
journalctl -f -u systemd-resolved # La información se visualiza en los logs de journal.

Consultar el registro DNS OPENPGPKEY Record de una dirección de correo (pocos proveedores soportan dicho tipo de registro de DNS).

resolvectl openpgp XXX@XXX

NOTA: La herramienta “resolvectl” permite entre otras cosas, tener una configuración DNS diferente para cada interfaz de red, consultar las páginas de manual para más información.

Como visualizar los certificados de los servidores DoT.

echo | openssl s_client -connect 1.1.1.1:853 2>/dev/null |openssl x509 -dates -text

Configurar los logs en modo debug para systemd.resolved.

systemctl edit systemd-resolved.service
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
systemctl restart systemd-resolved.service
journalctl -f -u systemd-resolved

DNSSEC

Detectar cuando un servidor DNS soporta DNSSEC y si soporta validación o no.

# Se debe hacer una consulta a un dominio firmado y válido.
dig +short +dnssec sigok.verteiltesysteme.net @1.1.1.1
134.91.78.139
A 5 3 60 20200130030006 20191031030006 30665 verteiltesysteme.net. kSXIoZJ5jl94CKzXDCJAHW29VpbIkxCZ3RQXYdMZKmN3PxhYYWy7an0q x6EXkdq9Imb2IBBjUc81/9q1/sAwZkF0m11KL3rHgoywxDc7uXaSa/RB XOK2kFUwpg6oTvCM5FQWVn2OPuSkRJmlh71ruKlPV6fXYwvMN4wQQZ8+ d4I=
 
# Firma no valida (no se obtiene respuesta).
dig +short +dnssec sigfail.verteiltesysteme.net @1.1.1.1

No todos los servidores DNS funcionan de la misma manera, cuando se hace una petición, si se indica que la respuesta debe ser validada y el servidor DNS hace validaciones, entonces si las comprobaciones DNSSEC fallan, no se devolverá ninguna dirección IP y se indicará que falló la resolución. Por el contrario, si el servidor DNS no realiza validaciones, este devolverá igualmente la dirección IP, dejando del lado cliente la decisión de qué hacer con la resolución DNS (En el caso de systemd-resolved con DNSSEC=true será descartada). Veamos un ejemplo.

dig +short +dnssec sigfail.verteiltesysteme.net @194.150.168.168
# No se obtiene respuesta
 
dig +short +dnssec sigfail.verteiltesysteme.net @23.253.163.53
;; Warning: Client COOKIE mismatch
134.91.78.139
A 5 3 60 20200130030006 20191031030006 30665 verteiltesysteme.net. //This+RRSIG+is+deliberately+broken///For+more+informati on+please+go+to/http+//www+verteiltesysteme+net///////// //////////////////////////////////////////////////////// //8=

systemd-resolved realiza las peticiones DNSSEC sin solicitar la validación, ya que la validación la hace él mismo. En la configuración propuesta en la guía, DNSSEC está desactivado. Esto se debe a que muchos subdominios pueden no funcionar debido a problemas en la cadena de confianza que DNSSEC comprueba. Estos subdominios pueden incluso pertenecer a Google, Amazon, Mozilla, etc, veamos algunos ejemplos.

El error que se suele obtener en los logs es “failed-auxiliary”, que indica un problema en el “DNSSEC Authentication Chain”

# resolvectl query shavar.prod.mozaws.net
DNSSEC validation failed for question shavar.prod.mozaws.net IN AAAA: failed-auxiliary

Si preguntamos al mismo servidor DNS con dig y mediante el comando “resolvectl”, veremos que en uno funciona y en el otro no.

resolvectl query shavar.prod.mozaws.net # Usando el DNS 1.1.1.1 (resolvectl status)
shavar.prod.mozaws.net: resolve call failed: DNSSEC validation failed: failed-auxiliary
 
dig +short +dnssec shavar.prod.mozaws.net @1.1.1.1 # Contesta afirmativamente.
52.33.61.229
52.33.139.34
52.88.59.72

Esto se debe a que “resolvectl” realiza una serie de comprobaciones sobre la cadena de confianza que con dig no son realizadas.

Averiguar si servidores DNS hacen uso de DNSSEC a la hora de resolver nombres (independientemente de si el cliente lo solicita o no).

Algunos servidores DNS funcionan usando DNSSEC aunque el cliente no lo solicite, es decir, el servidor DNS recibe una solicitud DNS, este pregunta a su vez otros servidores para seguir la cadena y dependiendo del resultado obtenido, la reenvía de vuelta al cliente.

# En estas peticiones no está DNSSEC activado en la solicitud, pero se puede apreciar como los resolvedores de nombres responden en base a parámetros DNSSEC.
 
dig +short sigfail.verteiltesysteme.net @208.67.220.220   # No parece basarse en ningún tipo de verificación de DNSSEC.
134.91.78.139
dig +short sigfail.verteiltesysteme.net @1.1.1.1   # No se obtiene respuesta porque la firma es invalida.
dig +short sigfail.verteiltesysteme.net @8.8.8.8   # No se obtiene respuesta porque la firma es invalida.

Esos mismos servidores, como vimos en ejemplos anteriores con algunos dominios de Mozilla, Google y Amazon, pueden responder positivamente cuando el “fallo” DNSSEC se encuentra en algún punto de la cadena de confianza. Como se comentó anteriormente, systemd-resolved es mucho más estricto (leer), quizás demasiado. Teniendo todo esto en mente, para una navegación cómoda se recomienda no tener activo DNSSEC o bien usar la opción allow-downgrade (no supone seguridad). Después de todo, los servidores DNS a los que conectamos que soportan DoT suelen realizar internamente sus comprobaciones DNSSEC (se puede comprobar con los comandos mostrados en la guía).

Enlace de interés: https://dnsviz.net/

Curl usando DNS over HTTPS (DoH)

DNS mediante HTTPS (DoH, siglas en inglés de DNS over HTTPS) es un protocolo de seguridad para realizar una resolución remota del sistema de nombres de dominio (DNS) a través del protocolo HTTPS. Uno de los objetivos del método es aumentar la privacidad y la seguridad de los usuarios mediante la prevención de las escuchas ilegales y la manipulación de los datos del DNS a través de ataques de intermediario.​ A partir de marzo de 2018, Google y la Fundación Mozilla están probando versiones de DNS mediante HTTPS.​ Cloudflare está trabajando con Mozilla y afirman que destruyen todos los datos DNS diariamente.

# Usando el servidor DNS DoH: https://cloudflare-dns.com/dns-query
curl --doh https://cloudflare-dns.com/dns-query busindre.com

Conferencia sobre DoT: https://ftp.fau.de/fosdem/2019/Janson/dns_over_http.mp4

Activar DoH en Firefox

Herramientas > Herramientas de red > Activar DNS over HTTPS

NOTA: Es posible que futuras versiones ya lo traigan activado por defecto.

Crear un servidor DoT y DNS Normal mediante Nginx

Con Nginx es posible usando su funcionalidad de proxy reverso, contactar con otros servidores DNS (locales o externos) para devolverle al cliente las resoluciones que estos hagan. La posibilidad de cifrado TLS de Nginx facilita ofrecer DoT sin esfuerzo.

Hay que disponer de un certificado confiable, es decir, considerado “trusted”. A ser posible con la/s IP/s del servidor incluidas además de los dominios pertinentes. No todas las CAs permiten incluir la/s IP/s en el campo SAN (X509v3 Subject Alternative Name) de los certificados, por ejemplo “Let's Encrypt” no lo contempla.

De disponer de la IP en el certificado, la resolución de nombres será más compatible con clientes. Facilitando que que no se necesite comprobar que el nombre del dominio coincida con el del certificado. Recordemos que en caso de usar systemd-resolved, si el servidor no tiene la IP en el certificado, se debe especificar el nombre del dominio usando la sintaxis “IP#Nombre” de la siguiente manera.

DNS=163.12.28.238#dominio.org 2607:1f30:0:f5::1085:e960#dominio.com

Configuración de Nginx para servidor “DNS” (Puerto 53) y “DNS over TLS” (Puerto 853).

Esta configuración se basa en usar Nginx como proxy reverso para servicios DNS (Puerto 53). Si se desea que Nginx también haga peticiones a servidores DoT y no DNS, se debe usar la segunda configuración propuesta.

stream {
    upstream dns { # se ponen los servidores DNS a los que se va a realizar la solicitud.
        zone dns 64k;
	server [2001:4860:4860::8888]:53; # Google DNS primario IPv6
	server [2001:4860:4860::8844]:53; # Google DNS secundario IPv6
	server 8.8.4.4:53;
        server 1.1.1.1:53;
        server 9.9.9.10:53;
        server 8.8.8.8:53;
    }

    # Se configura Nginx para que escuche en el puerto 853 (DoT) y 53 (DNS).
    server {
        listen 853 ssl;
	listen [::]:853 ssl;

	listen 53 udp;
	listen [::]:53 udp;

        proxy_responses 1;
        proxy_pass dns;
    }
	ssl_certificate /etc/letsencrypt/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/privkey.pem;

        ssl_protocols        TLSv1.2 TLSv1.3;
        ssl_ciphers          HIGH:!aNULL:!MD5;
        
        ssl_handshake_timeout    10s;
        ssl_session_cache        shared:SSL:20m;
        ssl_session_timeout      4h;
        ssl_session_tickets             off;
        ssl_prefer_server_ciphers       on;

        log_format dns '[$time_local]   $remote_addr  $ssl_protocol-$ssl_cipher  $ssl_server_name  $status   $bytes_sent $bytes_received  $ssl_session_reused';
        access_log /var/log/nginx/dns.log dns;
}

Esta configuración, a diferencia de la anterior, obliga a Nginx a hacer conexiones DoT (Puerto 853) a los servidores DNS donde se reenvían las peticiones de clientes.

stream {
    upstream dns { # se ponen los servidores DNS a los que se va a realizar la solicitud.
        zone dns 64k;
	server [2001:4860:4860::8888]:853; # Google DNS primario IPv6
	server [2001:4860:4860::8844]:853; # Google DNS secundario IPv6
	server 8.8.4.4:853;
        server 1.1.1.1:853;
        server 9.9.9.10:853;
        server 8.8.8.8:853;
    }

    # Se configura Nginx para que escuche en el puerto 853 (DoT) y 53 (DNS).
    server {
        listen 853 ssl;
	listen [::]:853 ssl;

	listen 53 udp;
	listen [::]:53 udp;

        proxy_ssl on;
        proxy_pass dns;
        proxy_responses 1;
    }
	ssl_certificate /etc/letsencrypt/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/privkey.pem;

        ssl_protocols        TLSv1.2 TLSv1.3;
        ssl_ciphers          HIGH:!aNULL:!MD5;
        
        ssl_handshake_timeout    10s;
        ssl_session_cache        shared:SSL:20m;
        ssl_session_timeout      4h;
        ssl_session_tickets             off;
        ssl_prefer_server_ciphers       on;

        log_format dns '[$time_local]   $remote_addr  $ssl_protocol-$ssl_cipher  $ssl_server_name  $status   $bytes_sent $bytes_received  $ssl_session_reused';
        access_log /var/log/nginx/dns.log dns;
}

NOTA: La opción “proxy_responses 1;” es crucial para que no se queden sockets abiertos y haya problemas de funcionamiento y rendimiento.

Enlaces de interés: