Configuración de Servidor DNS con BIND9 en Ubuntu: Guía Completa para Sysadmins
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 30 minutos para instalación, 1-2 horas para upgrade in-place.
- Requisitos: Backup de /home, conexión a internet, 20+ GB libres.
- Resultado: Sistema actualizado con soporte extendido, drivers funcionando.
- Troubleshooting: dnf distro-sync, akmods para NVIDIA, journalctl -p err.
Por qué BIND9 sigue siendo relevante en 2026
Cuando el resto del stack se fue a la nube (Route 53, Cloudflare DNS, Google Cloud DNS) montar un servidor de nombres autoritativo en tu propio hardware parece un anacronismo. No lo es. Hay tres casos donde BIND9 sigue siendo la mejor opción, y este tutorial te los explica: dominios internos que no quieres exponer a un tercero, redes grandes que necesitan vistas (split-horizon DNS), y servidores secundarios para tu dominio público donde quieres control total del archivo de zona.
En Ubuntu 24.04 LTS la versión actual del paquete bind9 es la 1:9.18.39-0ubuntu0.24.04.7 (rama estable 9.18 — EOL upstream en junio 2026; Ubuntu 24.04 LTS recibe parches de seguridad hasta abril 2029 pero ISC recomienda migrar a 9.20 ESV para servidores de producción nuevos). En Ubuntu 24.10 el paquete trae la rama 9.20 con mejores defaults para DNSSEC y soporte HTTP/3 sobre DoH. Para servidores de producción quédate con 24.04 LTS.
Instalar bind9 en Ubuntu
El paquete bind9 en Ubuntu es un meta-paquete que trae el servidor (named), las utilidades (dig, nslookup, rndc), y los archivos de configuración en /etc/bind/. Instala también bind9-utils y bind9-doc si vas a usar el servidor desde otra máquina para hacer pruebas con dig.
sudo apt update
sudo apt install -y bind9 bind9-utils bind9-doc
sudo systemctl enable --now named
sudo systemctl status named --no-pager
El primer comando levanta el servicio; systemctl status confirma que está corriendo y que rndc puede hablar con el daemon. Si todo está bien verás active (running) y la línea running as: named -u bind que confirma que el proceso bajó privilegios al usuario bind después de abrir el puerto 53. Esa doble etapa (root → bind) es por seguridad: si alguien explota una vulnerabilidad en named, el código ya no corre como root.
Entender los archivos de configuración que Ubuntu crea
Ubuntu no usa un solo named.conf monolítico: lo divide en cuatro archivos en /etc/bind/. Es la convención que verás en RHEL, Debian y derivados, y vale la pena entenderla antes de modificarlos.
| Archivo | Propósito |
|---|---|
named.conf |
Incluye los otros tres con directivas include. No tocar salvo para añadir includes nuevos. |
named.conf.options |
Opciones globales: puerto, allow-query, forwarders, recursion, DNSSEC. Aquí va casi toda la configuración que toca seguridad. |
named.conf.local |
Definiciones de zonas (forward y reverse) servidas por este servidor. Cada zona apunta a su archivo de zona. |
named.conf.default-zones |
Zonas por defecto que Ubuntu incluye (localhost, broadcast, 127.in-addr.arpa). Déjalas en paz — son necesarios para que el servidor no recurse hacia sí mismo. |
/var/cache/bind/ |
Directorio de trabajo donde van los archivos de zona personalizados y el journal. |
La separación existe porque named recarga archivos individuales sin reiniciar el daemon. Si tocas named.conf.options el servicio no se reinicia — recarga la configuración con rndc reload o el systemd helper systemctl reload bind9.
Configurar named.conf.options para un servidor autoritativo
El default de Ubuntu en named.conf.options deja opciones pensadas para un resolver recursivo. Para un servidor autoritativo puro hay que cerrar la recursion salvo en tus redes internas, restringir allow-query, y desactivar la transferencia de zona a desconocidos. Esta configuración asume que ns1.ejemplo.local es el servidor y 192.168.5.0/24 tu LAN.
sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.bak.$(date +%F)
sudo tee /etc/bind/named.conf.options > /dev/null <<'EOF'
options {
directory "/var/cache/bind";
recursion no; # servidor autoritativo puro, NO recursivo
allow-query { localnets; }; # solo responde a tu red interna
allow-transfer { none; }; # nadie puede pedir AXFR, lo definimos por zona
listen-on { any; };
listen-on-v6 { any; };
version "none"; # oculta la versión a quien haga dig @servidor version
minimal-responses yes;
auth-nxdomain no; # cumple RFC1035 mejor
managed-keys-directory "/var/cache/bind/keys";
dnssec-validation auto;
# forwarders para zonas que NO servimos autoritativamente
# (si este servidor también hace recursive para tu LAN, cambia recursion a yes
# y allow-query a { any; } — pero por defecto va cerrado)
forwarders {
1.1.1.1;
9.9.9.9;
};
forward only;
};
EOF
sudo named-checkconf /etc/bind/named.conf.options
El bloque forwarders queda como red de seguridad: si alguien por error le pide al servidor una zona que no hosteas, named no intenta recursión real (porque recursion no), delega a Cloudflare y Quad9, y devuelve la respuesta. forward only le prohíbe intentar resolver por cuenta propia si los forwarders no responden. named-checkconf es tu validación: cualquier error de sintaxis lo imprime antes de recargar.
Crear archivo de zona para un dominio interno
El dominio ejemplo.local es para uso puramente interno; no delega a raíz pública. El SOA define los timers de refresco y el contacto del admin. Los registros NS apuntan al propio servidor. Por cada host añades línea A (IPv4) y AAAA (IPv6) si tienes.
sudo tee /var/cache/bind/db.ejemplo.local > /dev/null <<'ZEOF'
$TTL 86400
@ IN SOA ns1.ejemplo.local. admin.ejemplo.local. (
2026101201 ; serial (YYYYMMDDNN, incrementar en cada cambio)
3600 ; refresh
1800 ; retry
1209600 ; expire
86400 ; minimum (negative cache TTL)
)
IN NS ns1.ejemplo.local.
; servidores
ns1 IN A 192.168.5.10
ns2 IN A 192.168.5.11
; infraestructura
gateway IN A 192.168.5.1
nas IN A 192.168.5.20
proxmox IN A 192.168.5.2
; workstations
rog-laptop IN A 192.168.5.50
rog-escritorio IN A 192.168.5.51
; servicios
wiki IN CNAME nas
vault IN CNAME nas
jellyfin IN CNAME proxmox
ZEOF
sudo chown bind:bind /var/cache/bind/db.ejemplo.local
sudo chmod 644 /var/cache/bind/db.ejemplo.local
sudo named-checkzone ejemplo.local /var/cache/bind/db.ejemplo.local
El serial sigue el patrón YYYYMMDDNN porque muchos secundarios lo comparan como entero de 32 bits y un valor más alto siempre gana. Si haces dos cambios el mismo día, el segundo va 02, el tercero 03. named-checkzone revisa sintaxis y verifica que cada nombre en NS, MX y CNAME apunte a algo real dentro de la zona. Si dice OK puedes seguir.
Crear archivo de zona inversa (PTR records)
Sin zona inversa los logs de muchos servicios (SSH, mail servers, fail2ban) no resuelven IP → nombre y quedan ilegibles. La zona inversa para 192.168.5.0/24 es 5.168.192.in-addr.arpa. Cada registro PTR apunta la IP al hostname canónico.
sudo tee /var/cache/bind/db.192.168.5 > /dev/null <<'REOF'
$TTL 86400
@ IN SOA ns1.ejemplo.local. admin.ejemplo.local. (
2026101201 ; serial
3600 ; refresh
1800 ; retry
1209600 ; expire
86400 ; minimum
)
IN NS ns1.ejemplo.local.
; PTR records — orden INVERSO: el último octeto primero
10 IN PTR ns1.ejemplo.local.
11 IN PTR ns2.ejemplo.local.
1 IN PTR gateway.ejemplo.local.
2 IN PTR proxmox.ejemplo.local.
20 IN PTR nas.ejemplo.local.
50 IN PTR rog-laptop.ejemplo.local.
51 IN PTR rog-escritorio.ejemplo.local.
REOF
sudo chown bind:bind /var/cache/bind/db.192.168.5
sudo chmod 644 /var/cache/bind/db.192.168.5
sudo named-checkzone 5.168.192.in-addr.arpa /var/cache/bind/db.192.168.5
La convención es “orden inverso“: para PTR de 192.168.5.10 escribes 10 IN PTR ns1.ejemplo.local., con la última parte de la IP primero. Confuso la primera vez; lo internalizas cuando ves el primer dig -x 192.168.5.10 devolver el hostname correcto en lugar del NXDOMAIN de antes.
Registrar las zonas en named.conf.local
Hasta ahora los archivos existen pero named no sabe que tiene que servirlos. named.conf.local es donde declaras la zona y apuntas al archivo.
sudo tee /etc/bind/named.conf.local > /dev/null <<'LEOF'
zone "ejemplo.local" {
type master;
file "/var/cache/bind/db.ejemplo.local";
allow-transfer { 192.168.5.11; }; # ns2 puede pedir AXFR
also-notify { 192.168.5.11; };
};
zone "5.168.192.in-addr.arpa" {
type master;
file "/var/cache/bind/db.192.168.5";
allow-transfer { 192.168.5.11; };
also-notify { 192.168.5.11; };
};
LEOF
sudo named-checkconf
sudo systemctl reload bind9
El allow-transfer solo permite AXFR al secundario en 192.168.5.11. Si no tienes secundario y el servidor es single-node, pon allow-transfer { none; }. also-notify le dice que avise al secundario cuando hay cambios — sin esto los segundos tardan hasta el refresh (1 hora en este ejemplo) en enterarse. rndc reload o systemctl reload bind9 aplica cambios sin cortar consultas en vuelo.
Verificar que todo responde
Antes de declararlo productivo, prueba desde la propia máquina y desde otra en la LAN. Los tres comandos cubren los casos típicos.
# 1. Forward lookup A record
dig @127.0.0.1 nas.ejemplo.local A +short
# 2. Forward lookup CNAME (debe devolver la IP del target)
dig @127.0.0.1 wiki.ejemplo.local +short
# 3. Reverse lookup PTR (clave para logs legibles)
dig @127.0.0.1 -x 192.168.5.20 +short
# 4. Verifica el SOA y los NS records
dig @127.0.0.1 ejemplo.local SOA +short
dig @127.0.0.1 ejemplo.local NS +short
# 5. Comprueba que NO hay recursion abierta
dig @127.0.0.1 google.com +short
# deberia devolver SERVFAIL o reenviar al forwarder, no recursion real
El último dig es la prueba de seguridad: si la respuesta viene recursiva (siguiendo la cadena hasta los root servers) tienes recursion yes abierto al mundo y cualquier atacante puede usar tu servidor como amplificador de DDoS. Con recursion no el servidor responde SERVFAIL o delega a los forwarders externos.
Hardening extra para producción
La configuración base ya está bien para una LAN. Para servidores expuestos a Internet (nunca recomendado para un solo admin) o redes grandes añade estas capas.
| Capa | Qué hace | Cómo |
|---|---|---|
| Rate limiting | Cap por cliente para mitigación de amplificación | rate-limit { responses-per-second 20; }; en options |
| RPZ (Response Policy Zones) | Bloquea dominios maliciosos o de ad-tracking a nivel DNS | response-policy { zone "rpz.local"; }; con archivo de zonas RPZ |
| DNSSEC signing | Firma criptográfica que valida el origen | dnssec-keygen + dnssec-signzone sobre el archivo de zona |
| chroot jail | Aísla named en /var/named/chroot por si hay exploit | apt install bind9-chroot y reconfigurar paths |
| Logging dedicado | Separar queries normales de las sospechosas | channel queries { file "/var/log/named/queries.log"; }; con category queries { queries; }; |
| actualizar unattended-upgrades | CVE parchadas sin intervención manual | sudo dpkg-reconfigure -plow unattended-upgrades |
Para un homelab basta rate-limit + DNSSEC. RPZ es overkill salvo que estés hosteando DNS para una familia o una microempresa. El chroot añade fricción operativa sin mucho beneficio real en Ubuntu 24.04 — el bind9 de Ubuntu ya corre como usuario no-root por diseño.
Troubleshooting común
Estos son los tres errores que más vas a ver, y cómo diagnosticarlos.
“zone ejemplo.local/IN: refused” al hacer dig: la causa típica es allow-query demasiado restrictivo. Si el cliente está fuera de la red listada en allow-query { localnets; }, named devuelve REFUSED. Verifica con named-checkconf -p /etc/bind/named.conf | grep allow-query.
“zone ejemplo.local/IN: not loaded due to errors” en journalctl -u named: error de sintaxis en el archivo de zona. named-checkzone ejemplo.local /var/cache/bind/db.ejemplo.local da la línea exacta. El 80% de las veces es un punto final faltante en un registro, o un nombre relativo sin punto final cuando debería ser FQDN.
AXFR denied desde el secundario: el allow-transfer del maestro no lista al secundario, o el firewall entre ambos bloquea puerto 53/TCP. Verifica con rndc zonestatus ejemplo.local en el maestro, y desde el secundario dig @192.168.5.10 ejemplo.local AXFR para ver exactamente qué pasa.
¿Vale la pena montar BIND9 hoy?
Depende del caso. Para dominios públicos pequeños Route 53 o Cloudflare DNS son más baratos en tiempo de administración y te dan anycast global incluido — no tiene sentido montar BIND9 autoritativo para un dominio .com con 10 registros A. Para dominios internos en LAN, dnsmasq cubre el 90% de los casos en 20 líneas de config, y Unbound es mejor si quieres validación DNSSEC estricta sin las complicaciones de BIND9.
Donde BIND9 sigue ganando: redes empresariales con split-horizon DNS (vistas distintas para empleados vs invitados vs VPN), organizaciones que firman sus zonas con DNSSEC manualmente, y entornos donde necesitas controles granulares por ACL sobre qué redes pueden resolver qué vistas. La curva de aprendizaje es más empinada, pero una vez que tu archivo de zona está bien hecho, named se queda corriendo meses sin tocar.
Preguntas frecuentes
¿Por qué Configuración de Servidor DNS con BIND9 en Ubuntu: Guía Completa para Sysadmins es relevante para sysadmins Linux?
Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.
¿Qué necesito para empezar con Configuración de Servidor DNS con?
Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.
¿Cuáles son los errores más comunes con Configuración de Servidor DNS con?
Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.
¿Cuándo usar Configuración de Servidor DNS con y cuándo una alternativa?
Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.
¿Cómo migro desde una configuración previa a Configuración de Servidor DNS con?
Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.
Lee también
- Guía Fedora 44: Novedades, Instalación y Upgrade para Sysadmins Linux
- Configura VLANs en Linux con nmcli: Guía paso a paso para sysadmins
- Protege tu SSH: Guía esencial para configurar Fail2ban en Linux
- Guía Definitiva: Configura Kubernetes con kubeadm en Ubuntu para Sysadmins Linux
- Configura Prometheus y Grafana: Guía DevOps para SysAdmins Linux
