Cuando una zona de BIND9 no carga, el alcance del fallo rara vez es discreto. La mitad de tus servicios fallan “aleatoriamente”, alguien culpa a la red y tu teléfono de guardia desarrolla una personalidad propia.
La buena noticia: la mayoría de los incidentes “la zona no carga” provienen de un pequeño conjunto de errores de sintaxis, problemas de archivos/permisos y algunas peculiaridades específicas de BIND. La mejor noticia: puedes diagnosticarlos rápido si dejas de adivinar y empiezas a leer lo que te está diciendo named.
Guion de diagnóstico rápido (primero/segundo/tercero)
Esta es la secuencia que encuentra el cuello de botella más rápido. Está orientada a triaje en producción: obtén señal, detén la hemorragia y luego pule.
Primero: confirma si la zona está cargada y qué versión está activa
- Pregunta a BIND qué piensa:
rndc zonestatusyrndc status. Si BIND nunca cargó la zona, estás persiguiendo un problema de archivo o un error de sintaxis, no un comportamiento extraño de caché. - Consulta el servidor directamente:
dig @127.0.0.1para SOA y NS. Si obtienesSERVFAILo no aparece la bandera autoritativa, no estás sirviendo lo que crees.
Segundo: lee el error que BIND ya imprimió
- Journald o syslog:
journalctl -u named(o-u bind9) te dice el fallo exacto de parseo, número de línea y a menudo el token que rompió el archivo. - Busca líneas de “loading”: quieres el nombre de la zona, la ruta del archivo y una razón. Si el log dice “permission denied”, no abras Vim—arregla la propiedad y SELinux/AppArmor.
Tercero: valida offline con las herramientas de comprobación
named-checkconf: detecta problemas a nivel de configuración (vista equivocada, zona duplicada, sintaxis mala de ACL, include faltante).named-checkzone: detecta errores de sintaxis en la zona (nombres propietarios malos, SOA roto, combinaciones ilegales de CNAME, datos fuera de zona).
Si la producción está en llamas
- Revertir rápido: restaura el último archivo de zona conocido bueno, incrementa el serial, recarga. DNS no es lugar para depurar en vivo con un pager gritando.
- Mantén una pista de auditoría: copia la zona rota aparte para que puedas aprender de ella más tarde. Post-incidente no recordarás qué “pequeño cambio” lo causó todo.
Qué significa realmente “la zona no carga” en BIND9
“La zona no carga” es una mentira conveniente que nos contamos. En BIND9 típicamente significa una de estas cosas:
- BIND no puede leer el archivo de zona: ruta errónea, permisos, confinamiento SELinux/AppArmor, chroot desajustado o include faltante.
- BIND puede leerlo pero no puede parsearlo: errores de sintaxis, combinaciones de registros ilegales o nombres/formatos TTL/clase rotos.
- BIND lo carga y luego lo rechaza: datos fuera de zona, registros requeridos faltantes (SOA) o políticas de integridad, especialmente en defaults más recientes y compilaciones endurecidas.
- BIND carga una versión más antigua de la que editaste: cambiaste el archivo equivocado, la vista equivocada o la zona es generada y sobrescrita por automatización.
- BIND lo carga, pero los clientes siguen fallando: porque la zona está cargada pero es incorrecta—delegaciones rotas, NS faltantes, glue malo, comodines que no funcionan o fallos de DNSSEC provocando validaciones erróneas.
Operativamente, tu tarea es averiguar en cinco minutos a qué clase de fallo perteneces. Todo lo demás son ejercicios de dedos.
Hechos interesantes y contexto (porque DNS arrastra historia)
- BIND es anterior a la mayoría de tus herramientas: se originó en UC Berkeley en los años 80 y se convirtió en el servidor DNS de facto en los inicios de Internet.
- Los archivos de zona están pensados para editarse a mano: su formato por líneas precede a YAML, JSON y la expectativa moderna de esquemas estrictos y parsers amigables.
- El punto final no es decoración: en DNS significa “nombre absoluto”. Sin él, los nombres son relativos al origin actual, y así es como creas accidentalmente
ns1.example.com.example.com. - Los números serial son un apretón de manos del protocolo: el serial del SOA impulsa las transferencias de zona (AXFR/IXFR). Seriales malos no solo te molestan—dejan secundarios con datos antiguos.
- El caché negativo es una característica: RFC 2308 hizo que NXDOMAIN sea cacheable usando el TTL mínimo/negativo del SOA. Puedes “arreglar” un registro y aun así ver fallos hasta que las cachés expiren.
- El TTL fue diseñado para un mundo lento: es una perilla de control gruesa de una era en la que todos esperaban que la caché ahorrara ancho de banda y CPU.
- DNSSEC hizo los fallos más ruidosos: sin DNSSEC muchos errores degradaban en “respuesta equivocada”. Con DNSSEC pueden convertirse en
SERVFAILen resolutores que validan. - Los mensajes de error de BIND mejoraron con las décadas: las versiones antiguas eran crípticas; BIND moderno normalmente te dice el número de línea y el token. La gente simplemente no los lee.
- Las views complican la resolución de problemas: el DNS de horizonte dividido es útil, pero también significa que “la zona está bien” puede ser verdad en una view y falsa en otra.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estos son comandos reales que puedes ejecutar durante un incidente. Cada uno incluye qué significa la salida y la decisión que tomas a continuación.
Tarea 1: Comprueba la salud del servicio y qué unidad estás manejando
cr0x@server:~$ systemctl status bind9 --no-pager
● bind9.service - BIND Domain Name Server
Loaded: loaded (/lib/systemd/system/bind9.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2025-12-31 08:10:22 UTC; 1h 12min ago
Docs: man:named(8)
Main PID: 1321 (named)
Tasks: 12 (limit: 9456)
Memory: 98.3M
CGroup: /system.slice/bind9.service
└─1321 /usr/sbin/named -f -u bind
Significado: BIND está en ejecución. “La zona no carga” no es “el demonio está caído”.
Decisión: ve a los registros y al estado de la zona; no pierdas tiempo reiniciando salvo que necesites forzar una recarga tras una corrección.
Tarea 2: Extrae los últimos errores de journald
cr0x@server:~$ journalctl -u bind9 -n 60 --no-pager
Dec 31 09:14:02 server named[1321]: zone example.com/IN: loading from master file /etc/bind/zones/db.example.com failed: file not found
Dec 31 09:14:02 server named[1321]: zone example.com/IN: not loaded due to errors.
Dec 31 09:14:02 server named[1321]: managed-keys-zone: loaded serial 0
Significado: No es sintaxis. Es ruta. BIND no puede abrir el archivo.
Decisión: verifica el stanza de zona en named.conf y la ruta en el sistema de archivos; revisa chroot y rutas include.
Tarea 3: Valida la configuración de named primero (rápido, barato, decisivo)
cr0x@server:~$ sudo named-checkconf -z
/etc/bind/named.conf.local:24: zone 'example.com': master file /etc/bind/zones/db.example.com: file not found
Significado: La configuración referencia un archivo que no existe en esa ubicación.
Decisión: corrige la ruta del archivo o coloca el archivo allí. No edites todavía el contenido de la zona.
Tarea 4: Confirma que el archivo existe donde BIND lo espera
cr0x@server:~$ ls -la /etc/bind/zones/db.example.com
ls: cannot access '/etc/bind/zones/db.example.com': No such file or directory
Significado: Realmente no está allí (o estás en la raíz equivocada si hay chroot).
Decisión: localiza el archivo real, arregla el despliegue o actualiza el stanza de zona con la ruta correcta.
Tarea 5: Encuentra dónde vive el archivo de zona (común con automatización “útil”)
cr0x@server:~$ sudo find /etc/bind -maxdepth 3 -type f -name "db.example.com" -print
/etc/bind/master/db.example.com
Significado: Alguien movió o generó el archivo en un directorio diferente.
Decisión: alinea la configuración y el sistema de archivos. Es preferible hacer que la configuración apunte a la ruta gestionada en vez de duplicar archivos.
Tarea 6: Comprueba permisos y propiedad (BIND se ejecuta como un usuario por una razón)
cr0x@server:~$ namei -l /etc/bind/master/db.example.com
f: /etc/bind/master/db.example.com
drwxr-xr-x root root /
drwxr-xr-x root root etc
drwxr-xr-x root root bind
drwx------ root root master
-rw-r----- root root db.example.com
Significado: El directorio /etc/bind/master es 0700, por lo que el usuario bind no puede atravesarlo.
Decisión: arregla los permisos del directorio (o mueve el archivo). No “simplemente ejecutes named como root” salvo que disfrutes redactar informes de incidente.
Tarea 7: Corrige permisos de forma segura y recarga
cr0x@server:~$ sudo chgrp bind /etc/bind/master
cr0x@server:~$ sudo chmod 0750 /etc/bind/master
cr0x@server:~$ sudo chgrp bind /etc/bind/master/db.example.com
cr0x@server:~$ sudo chmod 0640 /etc/bind/master/db.example.com
cr0x@server:~$ sudo rndc reload example.com
server reload successful
Significado: La recarga tuvo éxito a nivel del canal de control. No garantiza que la zona se haya cargado; significa que BIND aceptó el comando.
Decisión: confirma el estado de la zona y consulta SOA/NS para asegurar que la zona esté realmente en memoria.
Tarea 8: Pregunta a BIND directamente si la zona está cargada
cr0x@server:~$ sudo rndc zonestatus example.com
name: example.com
type: master
files: /etc/bind/master/db.example.com
serial: 2025123101
nodes: 29
last loaded: Tue, 31 Dec 2025 09:22:11 GMT
secure: no
Significado: La zona está cargada, y BIND usa el archivo esperado con un serial específico.
Decisión: pasa a comprobaciones de corrección (SOA/NS, glue, respuestas) en lugar de problemas de parser.
Tarea 9: Valida un archivo de zona offline antes de tocar producción otra vez
cr0x@server:~$ sudo named-checkzone example.com /etc/bind/master/db.example.com
zone example.com/IN: loaded serial 2025123101
OK
Significado: La sintaxis y las comprobaciones semánticas básicas pasaron.
Decisión: si los clientes aún fallan, revisa delegación, views, DNSSEC o caché. Deja de culpar al parser de la zona.
Tarea 10: Captura el clásico “punto faltante” y confusión de origen con un named-checkzone fallido
cr0x@server:~$ sudo named-checkzone example.com /etc/bind/master/db.example.com
/etc/bind/master/db.example.com:18: NS 'ns1.example.com.example.com' has no address records (A or AAAA)
zone example.com/IN: loaded serial 2025123101
OK
Significado: La zona se carga, pero BIND advierte que tu nombre NS se expandió relativo al origin. Normalmente es un punto final faltante en un FQDN.
Decisión: corrige el nombre objetivo del NS (añade el punto o usa un nombre relativo intencional) y asegúrate de que existan registros A/AAAA para los servidores de nombres dentro de la zona.
Tarea 11: Consulta el servidor autoritativo localmente (elimina caché de la historia)
cr0x@server:~$ dig @127.0.0.1 example.com SOA +norecurse
; <<>> DiG 9.18.24-1-Debian <<>> @127.0.0.1 example.com SOA +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; ANSWER SECTION:
example.com. 3600 IN SOA ns1.example.com. hostmaster.example.com. 2025123101 3600 900 1209600 300
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Dec 31 09:24:20 UTC 2025
;; MSG SIZE rcvd: 98
Significado: Respuesta autoritativa (aa) y campos SOA sensatos. La zona se sirve.
Decisión: si clientes externos ven fallos, revisa firewall/ACLs, views o la delegación en la zona padre.
Tarea 12: Verifica el conjunto NS y expectativas de glue
cr0x@server:~$ dig @127.0.0.1 example.com NS +norecurse
; <<>> DiG 9.18.24-1-Debian <<>> @127.0.0.1 example.com NS +norecurse
;; Got answer:
;; ->HEADER<<- opcode: QUERY, status: NOERROR, id: 22222
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; ANSWER SECTION:
example.com. 3600 IN NS ns1.example.com.
example.com. 3600 IN NS ns2.example.com.
Significado: La zona publica dos servidores de nombres autoritativos.
Decisión: asegura que esos nombres NS resuelvan. Si están dentro de la zona, publica glue A/AAAA en la zona. Si están fuera, garantiza que los nombres externos sean resolubles.
Tarea 13: Confirma que no creaste una mezcla ilegal con CNAME
cr0x@server:~$ sudo named-checkzone example.com /etc/bind/master/db.example.com
/etc/bind/master/db.example.com:42: 'www.example.com' CNAME and other data
zone example.com/IN: loading from master file /etc/bind/master/db.example.com failed: CNAME and other data
zone example.com/IN: not loaded due to errors.
Significado: Un nombre propietario tiene un CNAME y además otro tipo de registro (A/AAAA/TXT/MX/etc.). Eso está prohibido.
Decisión: elige: CNAME o “registros reales”. Si necesitas comportamiento tipo apex, considera ALIAS en el proveedor (no es estándar DNS) o rediseña.
Tarea 14: Comprueba si las views son la verdadera culpable
cr0x@server:~$ sudo named-checkconf -p | sed -n '1,120p'
acl "internal-nets" { 10.0.0.0/8; 192.168.0.0/16; };
view "internal" {
match-clients { "internal-nets"; };
zone "example.com" { type master; file "/etc/bind/master/db.example.com.internal"; };
};
view "external" {
match-clients { any; };
zone "example.com" { type master; file "/etc/bind/master/db.example.com.external"; };
};
Significado: Dos archivos diferentes sirven la misma zona dependiendo de la fuente del cliente.
Decisión: verifica que editaste el archivo correcto para los clientes que fallan. “Funciona en mi portátil” suele ser “funciona en la view interna”.
Tarea 15: Valida archivos relacionados con DNSSEC si estás firmado
cr0x@server:~$ journalctl -u bind9 -n 30 --no-pager
Dec 31 09:30:11 server named[1321]: zone example.com/IN: loaded serial 2025123101
Dec 31 09:30:11 server named[1321]: zone example.com/IN: signing with keys in key repository
Dec 31 09:30:11 server named[1321]: zone example.com/IN: DNSKEY RRset is not signed
Dec 31 09:30:11 server named[1321]: zone example.com/IN: not loaded due to errors.
Significado: Tienes expectativas de DNSSEC (firma en línea o políticas), pero los datos/llaves de la zona no las satisfacen.
Decisión: determina si DNSSEC es obligatorio para esta zona. Si sí, arregla el material de claves/política y vuelve a firmar. Si no, desactiva las características DNSSEC para la zona para restaurar el servicio.
Tarea 16: Confirma qué ve el exterior (respuestas autoritativas, no caché)
cr0x@server:~$ dig @ns1.example.com example.com SOA +norecurse
; <<>> DiG 9.18.24 <<>> @ns1.example.com example.com SOA +norecurse
;; Got answer:
;; ->HEADER<<- opcode: QUERY, status: SERVFAIL, id: 33333
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
Significado: El servidor autoritativo devuelve SERVFAIL. Normalmente es un problema del lado del servidor (zona no cargada, rotura DNSSEC, errores en tiempo de ejecución), no un problema de caché del cliente.
Decisión: vuelve a los logs del servidor y al estado de la zona; no pierdas tiempo vaciando resolutores.
Broma #1: El DNS es el único sistema donde añadir un punto puede arreglar producción. En la mayoría de sitios, añadir puntuación solo genera drama en Slack.
Errores comunes: síntoma → causa raíz → solución
Esta sección es deliberadamente específica. Si quieres consejos vagos, ya hay muchos posts que hacen ese trabajo mal.
1) Síntoma: “zone not loaded due to errors” tras recargar
Causa raíz: Confiaste en rndc reload para decirte que la zona se cargó. Solo te dice que el comando fue aceptado.
Solución: Sigue siempre con rndc zonestatus example.com y named-checkzone. Si falla, obtendrás el error exacto de parseo y el número de línea.
2) Síntoma: “file not found” pero juras que el archivo existe
Causa raíz: Ruta errónea en el stanza de la zona, un mismatch con un archivo include, o estás ejecutando BIND chrooted y miras el filesystem del host, no la jaula.
Solución: Usa named-checkconf -z para imprimir lo que BIND intenta abrir. Si hay chroot, verifica que el archivo exista bajo el directorio chroot. Confirma con ls -la dentro de esa raíz.
3) Síntoma: “permission denied” al cargar un archivo de zona
Causa raíz: Falta de derechos de traversado en directorios (el astuto), propiedad equivocada o políticas MAC (SELinux/AppArmor).
Solución: Ejecuta namei -l /path/to/zone. Arregla los bits de modo del directorio para que el usuario BIND pueda atravesarlo. Si es SELinux, revisa las denegaciones AVC y ajusta el contexto.
4) Síntoma: “CNAME and other data”
Causa raíz: Un nombre es CNAME y además tiene otro RRset (A/AAAA/TXT/MX/NS, etc.). Común cuando se quiere que www apunte a otro sitio pero también mantener un TXT para verificación.
Solución: Elimina los registros en conflicto. Si necesitas TXT en ese nombre, no uses CNAME allí. Usa A/AAAA o mueve la verificación a otra etiqueta.
5) Síntoma: “out of zone data”
Causa raíz: Pusiste registros para otro dominio en el archivo (a menudo por puntos finales faltantes o porque pegaste algo de otra zona).
Solución: Asegura que los nombres propietarios pertenezcan al origen de la zona. Usa $ORIGIN con cuidado. Añade puntos finales a nombres absolutos.
6) Síntoma: La zona carga, pero los secundarios nunca se actualizan
Causa raíz: El serial del SOA no cambió, o retrocedió (serial basado en fecha con un error), o editaste el archivo equivocado en otra view.
Solución: Incrementa el serial hacia adelante. Usa un esquema monótono. Luego rndc notify example.com y revisa los logs de transferencia en los secundarios.
7) Síntoma: NXDOMAIN persiste después de “arreglar” el registro
Causa raíz: Caché negativa según el TTL mínimo/negativo del SOA. También posible: cambiaste la view interna pero los clientes consultan la externa.
Solución: Revisa el campo mínimo del SOA; redúcelo antes del cambio cuando planifiques migraciones. Verifica qué view responde a tu cliente de prueba consultando desde la misma ruta de red.
8) Síntoma: “bad owner name (check-names)”
Causa raíz: Caracteres ilegales en nombres propietarios (guiones bajos en hostnames, espacios, etc.) o defaults de verificación estricta.
Solución: Corrige el nombre. Los guiones bajos están permitidos en ciertos contextos (como algunas etiquetas SRV) pero no como hostnames generales. No “arregles” deshabilitando las comprobaciones globalmente a menos que te gusten los bugs sutiles.
9) Síntoma: La zona carga localmente, pero resolutores externos obtienen SERVFAIL
Causa raíz: Fallos de validación DNSSEC (firmas expiradas, DS faltante, estado NSEC/NSEC3 erróneo), delegación pésima o bloqueos de firewall hacia UDP/TCP 53.
Solución: Confirma la autoridad desde varios puntos. Verifica el estado de la cadena DNSSEC y la frescura de las firmas. Asegura que TCP 53 funcione (respuestas DNSSEC grandes suelen necesitarlo).
10) Síntoma: “unexpected end of input” / el parseo se detiene a mitad de archivo
Causa raíz: Paréntesis de cierre faltante en un SOA multilínea, comillas sin cerrar en TXT o un copy/paste que truncó la última nueva línea o paréntesis.
Solución: Ejecuta named-checkzone y ve al número de línea. Luego escanea hacia arriba por estructuras sin cerrar; el parser suele señalar dónde notó el problema, no dónde empezó.
11) Síntoma: advertencias “ignoring out-of-zone data” y registros faltantes
Causa raíz: El propietario del registro se expandió al nombre equivocado por etiquetas relativas y cambios de $ORIGIN.
Solución: Sé explícito: usa nombres completos con punto final para todo lo que no esté bajo el origen actual y evita cambiar $ORIGIN a menos que la zona sea realmente compleja.
12) Síntoma: La recarga funciona, pero las respuestas siguen siendo antiguas
Causa raíz: Editaste un archivo que BIND no está usando (view equivocada, include equivocado, archivo generado sobrescrito). O BIND rechazó la nueva versión y mantuvo la antigua en memoria.
Solución: rndc zonestatus para ver la ruta y el serial cargados actualmente. Compáralo con lo que editaste. Si hay discrepancia, arregla tu despliegue/automatización, no la sintaxis de la zona.
Tres micro-historias corporativas desde el campo
Micro-historia 1: El incidente causado por una suposición equivocada
El equipo migraba una app orientada al cliente de un balanceador a otro. El plan parecía limpio: añadir un nuevo registro A, mantener TTL bajo y volcar tráfico actualizando un solo nombre. Editaron la zona, aumentaron el serial, ejecutaron rndc reload y vieron sus checks sintéticos. Verde.
Luego comenzaron las llamadas. Usuarios externos no podían resolver el nombre; empleados internos sí. La primera suposición fue predecible: “el DNS público está cachéando la respuesta antigua”. Alguien propuso vaciar cachés (siempre entrañable), otro propuso esperar.
El problema real fue DNS de horizonte dividido. Había dos views: interna y externa. El ingeniero actualizó el archivo de la zona interno, porque eso era lo que su portátil alcanzaba por VPN. La view externa aún apuntaba al balanceador viejo, que ya estaba drenado y medio deshabilitado. En su modelo mental había “la zona”. En BIND había dos zonas con el mismo nombre.
Arreglarlo fue técnicamente trivial—actualizar el archivo correcto, subir el serial, recargar. La parte difícil fue social: explicar por qué el cambio “funcionaba en pruebas” pero rompía producción para clientes. La lección quedó: siempre prueba desde la perspectiva del cliente que te importa. En DNS eso significa consultar al servidor autoritativo desde la red adecuada y verificar en qué view estás.
Tras el incidente añadieron un paso al runbook: named-checkconf -p para imprimir la configuración activa, y un par de comandos dig ejecutados desde un host interno y un vantage point externo. Evitó el siguiente “pero a mí me funcionó”.
Micro-historia 2: La optimización que salió mal
Un grupo de plataforma decidió que los archivos de zona eran “demasiado lentos” para recargar y quiso una optimización: generarlos con cambios agresivos de $ORIGIN y omitir puntos finales “innecesarios” para reducir tamaño y limpiar plantillas. También habilitaron composición basada en includes para que varios equipos aportaran fragmentos.
El resultado fue un archivo de zona que parecía elegante para humanos que ya sabían cómo funcionaba—e incomprensible durante incidentes. Un punto faltante en un objetivo NS se expandió silenciosamente al nombre equivocado, y como no estaba en la zona no tenía registros de dirección. Algunos resolutores lo toleraban; otros no. Mientras tanto, las rutas include diferían entre entornos. Staging cargaba; producción fallaba con file-not-found porque el layout de directorios no era idéntico.
El fallo no fue dramático; fue peor. Fueron fallos intermitentes de resolución y timeouts esporádicos. Tickets rebotaron entre networking, SRE y equipos de aplicación porque nadie veía un estado “caído” claro. Los logs de BIND tenían advertencias, pero nadie las leía porque “las advertencias son normales”.
La solución fue aburrida y efectiva: dejar de ser ingeniosos. Estandarizaron FQDN explícitos con puntos finales para todo lo que no fuera obviamente relativo, minimizaron cambios de $ORIGIN y hicieron que el generador produjera un único archivo canónico por zona por view. El archivo aumentó de tamaño. El tiempo de recarga no importó. El tiempo medio para entender mejoró drásticamente.
Broma #2: Si tu zona DNS necesita un generador para ser legible, no construiste automatización—construiste un acertijo.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Una empresa regulada tenía una regla de gestión de cambios: toda edición DNS debía pasar named-checkzone y named-checkconf en CI, y el sistema de despliegue se negaba a publicar archivos que no validaran. Los ingenieros se quejaban. Por supuesto que lo hacían.
Un viernes rutinario, un cambio añadió un registro TXT para un paso de verificación de dominio. El ingeniero colocó por error el TXT en un nombre que ya tenía un CNAME (porque marketing quería “nombres bonitos”). En un ambiente más casual, la zona habría fallado al cargar y se habría llevado un montón de registros no relacionados—porque la zona es atómica desde la perspectiva de BIND.
En su lugar, CI bloqueó el commit con un claro fallo “CNAME and other data”, incluyendo el número exacto de línea. Lo arreglaron, movieron la verificación a otra etiqueta y desplegaron de forma segura. Nadie pagó. Nadie lo recordó el lunes.
La práctica era poco glamorosa: validar antes de recargar, desplegar desde una única fuente de verdad y registrar los cambios de serial. No es innovador, pero es cómo evitas explicar a la dirección por qué “un registro TXT” causó un incidente.
Listas de verificación / plan paso a paso
Checklist de incidente: la zona no carga ahora mismo
- Confirma el impacto: ¿es un nombre, una zona o todas las zonas? Consulta SOA/NS localmente y desde al menos una perspectiva externa.
- Revisa la salud de BIND: servicio en ejecución, CPU/memoria saneadas, sin bucles de caída.
- Lee las últimas 100 líneas de log: encuentra el primer error del intento de carga de la zona; no persigas ruido descendente.
- Ejecuta
named-checkconf -z: arregla includes faltantes, rutas malas, zonas duplicadas, problemas de view. - Ejecuta
named-checkzone: corrige errores de sintaxis, conflictos CNAME, formato SOA, nombres propietarios, datos fuera de zona. - Corrige acceso al sistema de archivos: permisos, propiedad, SELinux/AppArmor. Valida con
namei -l. - Recarga y verifica:
rndc reload zone, luegorndc zonestatus, luegodig @127.0.0.1SOA/NS. - Si sigue fallando externamente: revisa views, firewall, delegación o estado DNSSEC.
Checklist de cambio: editar una zona de forma segura (para no conocer el pager)
- Decide la ventana de cambio según TTL: si necesitas despliegue/rollback rápido, baja los TTL con antelación.
- Edita con guardrails: usa un linter o al menos formato consistente. El SOA multilínea está bien; solo mantén los paréntesis balanceados.
- Siempre incrementa el serial del SOA: y asegúrate de que sea monótono entre rutas de despliegue.
- Valida offline:
named-checkzonepara el archivo de zona,named-checkconfsi cambias includes/views. - Recarga dirigida:
rndc reload example.comen vez de recargar todo. - Verifica respuestas autoritativas: consulta el servidor directamente por SOA/NS y el nombre cambiado. Confirma la bandera
aa. - Verifica transferencia/propagación: si tienes secundarios, confirma que tiraron el nuevo serial.
- Anota lo que cambiaste: una línea en el ticket. El tú del futuro es un extraño con menos sueño.
Checklist de endurecimiento: hacer que fallos de carga sean raros y cortos
- Validación en CI: bloquea merges que fallen
named-checkzone/named-checkconf. - Fuente de verdad única: genera un archivo canónico por zona/view y despliega de forma atómica.
- Registra seriales: trata los cambios de serial como versiones de release.
- Separa responsabilidades: no mezcles ediciones manuales con fragmentos generados a menos que disfrutes del trabajo de detective.
- Usa secundarios: y pruébalos. Un buen secundario es red de seguridad y herramienta de monitoreo.
- Alerta sobre “zona no cargada”: raspa logs o usa comprobaciones basadas en
rndc.
Preguntas frecuentes
1) ¿Por qué rndc reload dice “successful” cuando la zona aún no está cargada?
rndc informa que BIND aceptó el comando de control, no que el parseo haya tenido éxito. Siempre comprueba rndc zonestatus y los logs.
2) ¿Cuál es la forma más rápida de encontrar la línea exacta del error de sintaxis?
Ejecuta named-checkzone example.com /path/to/zone. Imprime el archivo y número de línea, normalmente con el token fallido.
3) Arreglé un registro pero los clientes aún ven NXDOMAIN. ¿BIND está roto?
Probablemente no. NXDOMAIN está cacheado (caché negativa). Revisa el TTL mínimo/negativo del SOA y espera—o planifica de antemano bajándolo antes de cambios.
4) ¿Realmente necesito el punto final en FQDNs en archivos de zona?
Si quieres que el nombre sea absoluto, sí. Sin el punto, BIND lo trata como relativo al origin actual. Así se fabrican nombres absurdos.
5) ¿Puedo tener un CNAME y un registro TXT en el mismo nombre?
No. Un CNAME no puede coexistir con otros datos en el mismo nombre. Mueve el TXT a otra etiqueta o no uses CNAME.
6) ¿Por qué los secundarios no recogen mis cambios aunque el primario los sirva?
La razón más frecuente es que el serial del SOA no aumentó. Los secundarios comparan seriales; si no sube (o baja), mantienen la zona antigua.
7) La zona carga, pero los resolutores externos obtienen SERVFAIL. ¿Qué hago ahora?
Primero revisa DNSSEC si lo usas. También verifica accesibilidad a TCP/53 y la corrección de la delegación. SERVFAIL desde un autoritativo es una señal de alarma.
8) ¿Cómo cambian las views la resolución de problemas?
Crean múltiples versiones de la “misma” zona. Debes confirmar qué view coincide con el cliente y validar el archivo de zona correspondiente.
9) ¿Cuál es un formato de serial SOA seguro?
Un formato por fecha YYYYMMDDnn funciona si nunca retrocedes. Un entero monotónico también funciona. Elige uno y haz que las herramientas lo impongan.
10) ¿Debería desactivar check-names para deshacerme de advertencias?
Por lo general no. Corrige los nombres. Desactivar las comprobaciones cambia una advertencia obvia hoy por una falla confusa mañana.
Pasos prácticos siguientes
Cuando BIND9 no carga una zona, no “intentes un reinicio” como rasgo de personalidad. Haz lo disciplinado:
- Pregunta a BIND qué cargó:
rndc zonestatus, y consulta SOA/NS directamente. - Lee los logs como si te pagaran (porque lo están haciendo).
- Valida offline con
named-checkconfynamed-checkzoneantes de tocar producción otra vez. - Arregla lo aburrido primero: rutas, permisos y puntos finales.
- Institucionaliza la victoria: añade validación en CI y una checklist de despliegue para que esto deje de ser un evento.
Y un mantra operativo fiable, parafraseando a W. Edwards Deming: la calidad proviene de mejorar el proceso, no de culpar a individuos. A las caídas de DNS les encanta los procesos débiles.