Instalación de Unbound como Resolvedor DNS
Unbound es un resolvedor DNS recursivo de alto rendimiento, seguro y validador de DNSSEC, diseñado para su uso tanto en servidores como en resolvedores de red locales. A diferencia de los resolvedores de proveedores externos como los de Google o Cloudflare, Unbound en tu propia infraestructura garantiza la privacidad de las consultas DNS y elimina la dependencia de terceros. Esta guía cubre la instalación de Unbound en Linux, validación DNSSEC, DNS-over-TLS y optimización de caché.
Requisitos Previos
- Ubuntu 22.04/Debian 12 o CentOS 9/Rocky Linux 9
- Mínimo 512 MB de RAM (1 GB recomendado para caché grande)
- Puerto 53 disponible (deshabilitar systemd-resolved si necesario)
- Acceso root al servidor
Instalación de Unbound
# Ubuntu/Debian
apt-get update
apt-get install -y unbound unbound-anchor
# CentOS/Rocky Linux
dnf install -y unbound
# Verificar la versión instalada
unbound -V
# Deshabilitar systemd-resolved si ocupa el puerto 53 (Ubuntu)
systemctl disable --now systemd-resolved
rm -f /etc/resolv.conf
echo "nameserver 127.0.0.1" > /etc/resolv.conf
# Habilitar e iniciar Unbound
systemctl enable --now unbound
# Verificar el estado
systemctl status unbound
Configuración del Resolvedor
El archivo de configuración principal es /etc/unbound/unbound.conf:
cat > /etc/unbound/unbound.conf << 'EOF'
server:
# Escuchar en todas las interfaces (o especificar una IP)
interface: 0.0.0.0
port: 53
# Activar IPv6 si el servidor lo tiene
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
# Número de hilos (uno por CPU disponible)
num-threads: 4
# Caché distribuida entre hilos
msg-cache-slabs: 4
rrset-cache-slabs: 4
infra-cache-slabs: 4
key-cache-slabs: 4
# Tamaño de caché (ajustar según RAM disponible)
msg-cache-size: 64m
rrset-cache-size: 128m
# Zona de trabajo de los hilos
so-rcvbuf: 1m
# Prefetch (renovar caché antes de que expire el TTL)
prefetch: yes
prefetch-key: yes
# Privacidad: usar puertos UDP aleatorios
outgoing-range: 8192
num-queries-per-thread: 4096
# Minimización de consultas (envía menos información a los servidores raíz)
qname-minimisation: yes
# Seguridad: agregar bit 0x20 para aleatorizar mayúsculas en consultas
use-caps-for-id: yes
# Duración mínima del TTL en caché (evitar TTLs de 0 que bypassan la caché)
cache-min-ttl: 60
cache-max-ttl: 86400
# Logging (minimal en producción)
verbosity: 1
log-queries: no
log-replies: no
log-tag-queryreply: no
logfile: "/var/log/unbound/unbound.log"
# Usuario que ejecuta Unbound
username: "unbound"
# Directorio de trabajo
directory: "/etc/unbound"
# Archivo de anclaje DNSSEC (actualizado por unbound-anchor)
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Hardening de seguridad
harden-glue: yes
harden-dnssec-stripped: yes
harden-below-nxdomain: yes
harden-referral-path: yes
harden-algo-downgrade: no
# Denegar consultas de zonas que no deben ser visibles externamente
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: 127.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
# Control remoto (para unbound-control)
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8953
server-key-file: "/etc/unbound/unbound_server.key"
server-cert-file: "/etc/unbound/unbound_server.pem"
control-key-file: "/etc/unbound/unbound_control.key"
control-cert-file: "/etc/unbound/unbound_control.pem"
EOF
# Crear directorio de logs
mkdir -p /var/log/unbound
chown unbound:unbound /var/log/unbound
# Generar los certificados para unbound-control
unbound-control-setup
# Verificar la configuración
unbound-checkconf /etc/unbound/unbound.conf
# Reiniciar el servicio
systemctl restart unbound
Validación DNSSEC
Unbound puede validar DNSSEC automáticamente usando el anclaje de confianza de la zona raíz:
# Inicializar/actualizar la clave de anclaje DNSSEC de la zona raíz
unbound-anchor -a /var/lib/unbound/root.key
chown unbound:unbound /var/lib/unbound/root.key
# Verificar que DNSSEC está funcionando
# Una respuesta con "ad" (Authenticated Data) indica validación DNSSEC exitosa
dig +dnssec cloudflare.com @127.0.0.1
# Buscar "flags: qr rd ra ad" en la respuesta
# Probar con un dominio firmado con DNSSEC
dig +dnssec iana.org @127.0.0.1 SOA
# Verificar que Unbound rechaza dominios con firma DNSSEC incorrecta
dig @127.0.0.1 dnssec-failed.org
# Debe devolver SERVFAIL porque tiene una firma DNSSEC rota intencionalmente
# Programar actualización automática del anclaje DNSSEC (cron diario)
echo "0 3 * * * unbound /usr/sbin/unbound-anchor -a /var/lib/unbound/root.key" \
> /etc/cron.d/unbound-anchor
Control de Acceso
# Añadir ACLs de acceso al archivo de configuración
cat >> /etc/unbound/unbound.conf << 'EOF'
# Control de acceso: quién puede hacer consultas
# Por defecto: denegar todo excepto localhost
server:
access-control: 0.0.0.0/0 refuse # Denegar por defecto
access-control: 127.0.0.0/8 allow # Permitir localhost
access-control: 10.0.0.0/8 allow # Permitir red interna
access-control: 192.168.0.0/16 allow # Permitir redes privadas
access-control: ::1 allow # Permitir IPv6 localhost
EOF
# Recargar configuración
unbound-control reload
Optimización de Caché
# Ver estadísticas de la caché en tiempo real
unbound-control stats_noreset
# Estadísticas relevantes:
# total.num.queries - Consultas totales recibidas
# total.num.cachehits - Hits en caché (cuanto mayor, mejor)
# total.num.cachemiss - Misses (consultas recursivas)
# total.num.recursivereplies - Respuestas recursivas resueltas
# cache.rrset.count - Entradas actuales en la caché
# Calcular el porcentaje de cache hit
unbound-control stats_noreset | awk '
/total.num.queries/ {queries=$2}
/total.num.cachehits/ {hits=$2}
END {printf "Cache hit ratio: %.1f%%\n", (hits/queries)*100}'
# Limpiar la caché de Unbound
unbound-control flush_zone . # Limpiar toda la caché
unbound-control flush empresa.com # Limpiar solo un dominio
# Ajustar el tamaño de caché en tiempo real (sin reiniciar)
# Los cambios en unbound.conf requieren reinicio
# Para cambios en caliente, usar unbound-control set-option
DNS-over-TLS (Reenvío Cifrado)
Configura Unbound para reenviar consultas mediante TLS:
cat >> /etc/unbound/unbound.conf << 'EOF'
# Reenvío de consultas externas mediante DNS-over-TLS
forward-zone:
name: "."
# Cloudflare DNS-over-TLS
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 1.0.0.1@853#cloudflare-dns.com
# Google DNS-over-TLS (alternativa)
forward-addr: 8.8.8.8@853#dns.google
forward-addr: 8.8.4.4@853#dns.google
# Reenvío mediante TLS
forward-tls-upstream: yes
EOF
unbound-checkconf
systemctl restart unbound
# Verificar que las consultas van cifradas
unbound-control stats | grep "num.query.tls"
Zonas Locales
Define resolución para dominios internos:
cat >> /etc/unbound/unbound.conf << 'EOF'
# Zona local para infraestructura interna
local-zone: "empresa.local." static
# Registros de hosts internos
local-data: "web.empresa.local. 3600 IN A 10.0.1.10"
local-data: "api.empresa.local. 3600 IN A 10.0.2.10"
local-data: "db.empresa.local. 3600 IN A 10.0.3.10"
local-data: "mail.empresa.local. 3600 IN A 10.0.4.10"
# Resolución inversa para la red interna
local-zone: "0.0.10.in-addr.arpa." static
local-data-ptr: "10.0.1.10 web.empresa.local"
local-data-ptr: "10.0.2.10 api.empresa.local"
# Bloquear dominio malicioso (redirigir a IP no válida)
local-zone: "malicioso.com." always_nxdomain
local-zone: "tracking.ad-network.com." always_refuse
EOF
systemctl restart unbound
# Verificar la resolución local
dig @127.0.0.1 web.empresa.local
dig @127.0.0.1 -x 10.0.1.10
Solución de Problemas
# Aumentar verbosidad para depuración (no usar en producción)
unbound-control verbosity 3
# Ver logs en tiempo real
tail -f /var/log/unbound/unbound.log
# Probar resolución con debug
dig @127.0.0.1 google.com +dnssec +multiline
# Verificar que Unbound puede llegar a los servidores raíz
unbound-control lookup google.com
# Ver la caché para un dominio específico
unbound-control dump_cache | grep "google.com"
# Verificar que el puerto 53 está escuchando
ss -ulnp | grep 53
# Comprobar si hay errores de DNSSEC
dig +dnssec @127.0.0.1 dnssec-failed.org
# Debe devolver SERVFAIL
# Restaurar verbosidad normal
unbound-control verbosity 1
Conclusión
Unbound ofrece resolución DNS recursiva con validación DNSSEC completa y privacidad mejorada gracias a la minimización de consultas QNAME, siendo una alternativa sólida y más privada a los resolvedores externos. Su flexibilidad para combinar resolución recursiva directa con reenvío DNS-over-TLS y zonas locales lo convierte en el resolvedor ideal para infraestructuras que requieren control total sobre la resolución DNS sin depender de terceros.


