Configuración de DNSDist 2.x y TLS con Let’s Encrypt
dnsdist se utiliza junto con BIND porque este último, por sí solo, no soporta los protocolos modernos de resolución cifrada como DNS sobre HTTPS (DoH) ni DNS sobre TLS (DoT). De esta manera, actúa como un proxy que recibe las consultas seguras en HTTPS o TLS, las descifra y las reenvía a BIND mediante DNS tradicional en el puerto 53. De esta manera, BIND puede seguir cumpliendo su función como servidor autoritativo o recursivo, mientras dnsdist añade cifrado, control de tráfico, balanceo de carga y protección frente a ataques, ofreciendo un servicio DNS más seguro, eficiente y moderno.
Esta guía configura dnsdist 2.x con TLS (DoT y DoH) utilizando certificados Let’s Encrypt, incluye la configuración de AppArmor y los permisos de archivo adecuados. Se asume que no hay un usuario dnsdist dedicado.
1. Instalar dnsdist 2.x
Aunque la instalación desde el repositorio de PowerDNS requiere un poco más de trabajo siempre ofrece la última versión estable (actualmente 2.x), que incluye funciones actualizadas y correcciones de errores.
Primero, necesita crear el archivo /etc/apt/sources.list.d/pdns.list
con este contenido:
deb [signed-by=/etc/apt/keyrings/dnsdist-20-pub.asc] http://repo.powerdns.com/debian bookworm-dnsdist-20 main
Poner esto en /etc/apt/preferences.d/dnsdist-20
:
Package: dnsdist*
Pin: origin repo.powerdns.com
Pin-Priority: 600
y ejecutar los siguientes comandos:
install -d /etc/apt/keyrings; curl https://repo.powerdns.com/FD380FBB-pub.asc | tee /etc/apt/keyrings/dnsdist-20-pub.asc &&
sudo apt update &&
sudo apt install dnsdist
2. Certificados SSL
Dado que el host no cuenta con servidor web vamos a instalar certbot en modo standalone.
apt install python3-certbot
Verifique la instalación
certbot --version
Obtener el certificado
certbot certonly --standalone -d dns.dominio.edu.ar
Reemplace
dns.dominio.edu.ar
con su dominio actual. Esto genera los archivos en /etc/letsencrypt/live/dns.midominio.edu.ar/.
Ubicación de los certificados
Certbot deja los certificados y claves en:
/etc/letsencrypt/live/dns.dominio.edu.ar/fullchain.pem
/etc/letsencrypt/live/dns.dominio.edu.ar/privkey.pem
Renovación automática
Certbot instala una tarea cron para renovar certificados automáticamente,
Para que con cada actualización certboot reinicie dnsdist, cree un archivo de hook en /etc/letsencrypt/renewal-hooks/deploy/recarga-dnsdist.sh
:
#!/bin/bash
systemctl reload dnsdist
Y dele permisos de ejecución
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/recarga-dnsdist.sh
2. Permiso, permiso
Averigue con qué usuario se ejecuta dnsdist.
systemctl show -p User --value dnsdist.service
ó
systemctl status dnsdist
en cuya salida ver, por ejemplo
Main PID: 121471 (dnsdist)
Agregue ese usuario al grupo the ssl-cert (predeterminado en Debian para letsencrypt):
usermod -aG ssl-cert dnsdist
Confirme que la clave sea legible para el grupo:
chmod 640 /etc/letsencrypt/live/dns.daminio.edu.ar/privkey.pem
chgrp ssl-cert /etc/letsencrypt/live/dns.daminio.edu.ar/privkey.pem
3. Configurar AppArmor
Edite el perfil principal de dnsdist:
nano /etc/apparmor.d/usr.sbin.dnsdist
Dentro del bloque de perfil { ... }
, agregar los siguientes permisos de lectura para archivos SSL:
# Permitir que dnsdist lea las claves de LetsEncrypt
/etc/letsencrypt/live/dns.dominio.edu.ar.edu.ar/privkey.pem r,
/etc/letsencrypt/live/dns.dominio.edu.ar.edu.ar/fullchain.pem r,
/etc/letsencrypt/archive/dns.dominio.edu.ar.edu.ar/* r,
/etc/letsencrypt/renewal/dns.dominio.edu.ar.edu.ar.conf r,
Verificar la sintaxis:
apparmor_parser -T /etc/apparmor.d/usr.sbin.dnsdist
Recargar el perfil:
apparmor_parser -r /etc/apparmor.d/usr.sbin.dnsdist
3. Actualizar la configuración de dnsdist
Edite el archivo de configuración de su dnsdist (ej., /etc/dnsdist/dnsdist.conf
) y defina:
-- Certificado y llave TLS
local ArchCert = "/etc/letsencrypt/live/dns.dominio.edu.ar/fullchain.pem"
local ArchLlave = "/etc/letsencrypt/live/dns.dominio.edu.ar/privkey.pem"
-- Upstream backend (BIND)
newServer({
address="127.0.0.1:53",
name="bind-backend",
checkInterval=10
})
setServerPolicy(firstAvailable)
-- DNS-over-TLS (DoT) en puerto 853
addTLSLocal("0.0.0.0:853", ArchCert, ArchLlave)
addTLSLocal("[::]:853", ArchCert, ArchLlave)
-- DNS-over-HTTPS (DoH) en puerto 443
addDOHLocal("0.0.0.0:443", ArchCert, ArchLlave, "/dns-query")
addDOHLocal("[::]:443", ArchCert, ArchLlave), "/dns-query"
-- ACL: permitir a todos (ya que DoH/DoT requieren auth/TLS de todos modos)
setACL({"0.0.0.0/0", "::/0"})
-- Refuerzo de seguridad
setMaxUDPOutstanding(65535)
setMaxTCPClientThreads(50)
setMaxTCPConnectionsPerClient(20)
setMaxTCPQueriesPerConnection(100)
-- Límite de tasa (por IP)
addAction(MaxQPSIPRule(100), DropAction())
-- Socket de control (admin local)
controlSocket("127.0.0.1:5199")
-- Logging
setVerbose(false)
setVerboseHealthChecks(true)
4. Recargar dnsdist
systemctl restart dnsdist
Verificar logs:
journalctl -u dnsdist -f
Probar localmente:
dig @127.0.0.1 dominio.edu.ar