BIND9 es el servidor DNS de referencia en Linux y sirve tanto para resolver nombres (resolver recursivo) como para publicar las zonas de tus dominios (servidor autoritativo). En este tutorial configurarás BIND9 en Ubuntu 24.04 como servidor autoritativo para tu dominio, con un servidor primario y uno secundario sincronizados por transferencia de zona, firma DNSSEC automática y limitación de respuestas contra ataques de amplificación.
Requisitos previos
Para seguir esta guía necesitas:
- Dos servidores con Ubuntu 24.04 LTS e IP pública, por ejemplo dos VPS de CubePath, idealmente en ubicaciones distintas. Uno será el primario (
ns1) y otro el secundario (ns2). Puedes seguir la guía con un solo servidor y añadir el secundario más adelante, aunque los registradores suelen exigir al menos dos servidores de nombres. - Un usuario no root con privilegios
sudoen ambos, con UFW activo y SSH permitido. - Un dominio registrado (
your_domain) y acceso al panel del registrador para cambiar sus servidores de nombres y crear registros glue.
En los ejemplos se usan estos valores, que debes sustituir por los tuyos:
| Valor | Ejemplo |
|---|---|
| Dominio | your_domain |
IP de ns1 (primario) | 203.0.113.10 |
IP de ns2 (secundario) | 203.0.113.20 |
| IP del servidor web | 203.0.113.30 |
Notaun servidor autoritativo no debe resolver consultas recursivas para Internet. Un resolver abierto se usa para ataques de amplificación. Por eso esta configuración desactiva la recursión.
Paso 1: Instalar BIND9 en ambos servidores
Ejecuta en ns1 y en ns2:
sudo apt update
sudo apt install bind9 bind9-utils bind9-dnsutils
bind9-utils incluye las herramientas de validación (named-checkconf, named-checkzone) y bind9-dnsutils incluye dig. Comprueba la versión y el servicio, que en Ubuntu 24.04 se llama named:
named -v
systemctl status named --no-pager
BIND 9.18.30-0ubuntu0.24.04.2-Ubuntu (Extended Support Version) <id:>
● named.service - BIND Domain Name Server
Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-25 13:00:21 UTC; 15s ago
Paso 2: Configurar las opciones globales
La configuración de BIND en Ubuntu está repartida en /etc/bind: named.conf.options contiene las opciones globales y named.conf.local tus zonas. Haz una copia de las opciones y edítalas en ambos servidores:
sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.orig
sudo nano /etc/bind/named.conf.options
Sustituye el contenido por:
options {
directory "/var/cache/bind";
// Solo autoritativo: sin recursión ni caché para terceros
recursion no;
allow-query { any; };
allow-transfer { none; };
listen-on { any; };
listen-on-v6 { any; };
dnssec-validation auto;
// No revelar la versión de BIND
version "not disclosed";
// Limitar respuestas idénticas por cliente para frenar ataques de amplificación
rate-limit {
responses-per-second 10;
};
};
recursion nohace que el servidor solo responda a las zonas que aloja.allow-transfer { none; }bloquea las transferencias de zona por defecto; en el paso 5 las permitirás solo hacia el secundario.rate-limit(Response Rate Limiting) limita a 10 por segundo las respuestas idénticas hacia una misma red, lo que inutiliza el servidor como amplificador sin afectar a los resolvers legítimos.
Valida la sintaxis:
sudo named-checkconf
El comando no muestra nada si la configuración es correcta.
Paso 3: Crear el archivo de zona en el primario
En ns1, crea el archivo de zona en /var/lib/bind, el directorio donde BIND puede escribir. Será necesario para DNSSEC en el paso 7:
sudo nano /var/lib/bind/db.your_domain
$TTL 3600
@ IN SOA ns1.your_domain. hostmaster.your_domain. (
2026092501 ; serial (AAAAMMDDNN)
3600 ; refresh
900 ; retry
1209600 ; expire
300 ) ; TTL negativo
; Servidores de nombres
@ IN NS ns1.your_domain.
@ IN NS ns2.your_domain.
ns1 IN A 203.0.113.10
ns2 IN A 203.0.113.20
; Web
@ IN A 203.0.113.30
www IN CNAME your_domain.
; Correo
@ IN MX 10 mail.your_domain.
mail IN A 203.0.113.30
@ IN TXT "v=spf1 mx -all"
Algunos detalles importantes:
- Los nombres completos terminan en punto (
ns1.your_domain.). Sin el punto, BIND les añade el dominio y obtendríasns1.your_domain.your_domain. @representa el propio dominio.- El segundo campo del SOA es el correo del responsable con el
@sustituido por un punto:hostmaster.your_domain.equivale ahostmaster@your_domain. - El serial debe aumentar cada vez que modificas la zona; es lo que indica al secundario que hay cambios. El formato
AAAAMMDDNN(fecha más un contador) es el más práctico.
Ajusta el propietario para que BIND pueda leer y, más adelante, escribir el archivo:
sudo chown bind:bind /var/lib/bind/db.your_domain
Valida la zona:
sudo named-checkzone your_domain /var/lib/bind/db.your_domain
zone your_domain/IN: loaded serial 2026092501
OK
Paso 4: Declarar la zona en el primario
Añade la zona a /etc/bind/named.conf.local en ns1:
sudo nano /etc/bind/named.conf.local
zone "your_domain" {
type primary;
file "/var/lib/bind/db.your_domain";
allow-transfer { 203.0.113.20; };
also-notify { 203.0.113.20; };
};
allow-transfer permite que solo ns2 descargue la zona completa, y also-notify avisa a ns2 en cuanto la zona cambia, sin esperar al intervalo de refresh. Valida y recarga:
sudo named-checkconf
sudo rndc reload
server reload successful
Comprueba que ns1 responde con autoridad para la zona:
dig @127.0.0.1 your_domain A +norec
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
your_domain. 3600 IN A 203.0.113.30
El flag aa (authoritative answer) confirma que el servidor es autoritativo para el dominio.
Paso 5: Configurar el servidor secundario
En ns2, con las opciones del paso 2 ya aplicadas, declara la zona como secundaria en /etc/bind/named.conf.local:
sudo nano /etc/bind/named.conf.local
zone "your_domain" {
type secondary;
file "/var/lib/bind/db.your_domain";
primaries { 203.0.113.10; };
};
El secundario descarga la zona del primario y la guarda en /var/lib/bind. Valida y recarga:
sudo named-checkconf
sudo rndc reload
Comprueba en el log que la transferencia se ha completado:
sudo journalctl -u named -n 20 --no-pager | grep -i transfer
... transfer of 'your_domain/IN' from 203.0.113.10#53: Transfer completed: 1 messages, 11 records, 318 bytes, 0.012 secs
Verifica que ambos servidores devuelven el mismo serial:
dig @203.0.113.10 your_domain SOA +short
dig @203.0.113.20 your_domain SOA +short
ns1.your_domain. hostmaster.your_domain. 2026092501 3600 900 1209600 300
ns1.your_domain. hostmaster.your_domain. 2026092501 3600 900 1209600 300
Paso 6: Abrir el firewall y delegar el dominio
DNS usa el puerto 53 en UDP para la mayoría de consultas y en TCP para respuestas grandes y transferencias de zona. Ábrelo en ambos servidores:
sudo ufw allow 53
Comprueba desde tu equipo que los dos servidores responden por Internet:
dig @203.0.113.10 www.your_domain +short
dig @203.0.113.20 www.your_domain +short
your_domain.
203.0.113.30
Ya puedes delegar el dominio. En el panel de tu registrador:
- Crea los registros glue (a veces llamados "host records" o "servidores de nombres propios"):
ns1.your_domaincon203.0.113.10yns2.your_domaincon203.0.113.20. Son necesarios porque los servidores de nombres están dentro del propio dominio. - Cambia los servidores de nombres del dominio a
ns1.your_domainyns2.your_domain.
La delegación puede tardar unas horas en propagarse, según el TTL de los registros NS del TLD. Para comprobarla, sigue la cadena desde los servidores raíz:
dig your_domain NS +trace
Las últimas líneas deben mostrar los registros NS servidos por ns1 o ns2.
Paso 7: Firmar la zona con DNSSEC
DNSSEC firma las respuestas para que los resolvers puedan comprobar que no han sido alteradas. BIND 9.18 gestiona las claves, las firmas y su rotación de forma automática con dnssec-policy. En ns1, edita la zona:
sudo nano /etc/bind/named.conf.local
zone "your_domain" {
type primary;
file "/var/lib/bind/db.your_domain";
allow-transfer { 203.0.113.20; };
also-notify { 203.0.113.20; };
dnssec-policy default;
inline-signing yes;
};
Con inline-signing yes, BIND mantiene tu archivo de zona sin cambios y genera a su lado una versión firmada (db.your_domain.signed), por eso la zona debe estar en un directorio donde bind pueda escribir. La política default usa una única clave ECDSAP256SHA256 y renueva las firmas automáticamente. Aplica el cambio:
sudo named-checkconf
sudo rndc reconfig
Comprueba que la zona ya devuelve firmas (registros RRSIG):
dig @127.0.0.1 your_domain A +dnssec +norec
;; ANSWER SECTION:
your_domain. 3600 IN A 203.0.113.30
your_domain. 3600 IN RRSIG A 13 2 3600 20261009130512 20260925120512 41522 your_domain. kW9...Zg==
El secundario recibe la zona ya firmada por transferencia, así que no necesita ningún cambio.
Para cerrar la cadena de confianza, debes publicar un registro DS en el registrador. Obtén los datos a partir de la clave pública (KSK) que BIND ha creado:
dig @127.0.0.1 your_domain DNSKEY +norec +noall +answer | dnssec-dsfromkey -f - your_domain
your_domain. IN DS 41522 13 2 4A1B...9F3C
Introduce en el registrador el key tag (41522), el algoritmo (13), el tipo de digest (2, SHA-256) y el digest. Algunos registradores piden directamente la clave pública (DNSKEY); en ese caso copia el registro DNSKEY con flags 257.
Cuando el DS esté publicado, comprueba el estado de la clave:
sudo rndc dnssec -status your_domain
Y verifica la validación con un resolver público: el flag ad (authenticated data) indica que la firma se ha validado.
dig @1.1.1.1 your_domain A +dnssec | grep flags
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
Paso 8: Modificar la zona
Cada cambio en la zona sigue el mismo proceso en ns1: editar el archivo, aumentar el serial, validar y recargar solo esa zona:
sudo nano /var/lib/bind/db.your_domain
sudo named-checkzone your_domain /var/lib/bind/db.your_domain
sudo rndc reload your_domain
zone reload queued
Gracias a also-notify, ns2 recibe el cambio en segundos. Confírmalo comparando el serial en ambos servidores como en el paso 5.
Solución de problemas
named no arranca o rndc reload falla. Ejecuta sudo named-checkconf y sudo named-checkzone para localizar el error, y revisa sudo journalctl -u named -n 50. Los fallos más comunes son un punto y coma olvidado en named.conf.* o un nombre sin el punto final en la zona.
El secundario no actualiza la zona. Casi siempre es porque el serial no ha aumentado. También puede ser que allow-transfer en el primario no incluya la IP del secundario o que el puerto 53/TCP esté bloqueado. El log de ns2 muestra el motivo, por ejemplo Transfer status: REFUSED.
dig devuelve status: REFUSED para otros dominios. Es el comportamiento esperado: con recursion no, el servidor solo responde a sus propias zonas.
Los resolvers devuelven SERVFAIL tras activar DNSSEC. El DS del registrador no coincide con la clave publicada, por ejemplo tras reinstalar el servidor y generar claves nuevas. Compara la salida de dnssec-dsfromkey con el DS publicado (dig your_domain DS +short) y corrígelo en el registrador.
Conclusión
Tienes un servicio DNS autoritativo con BIND9 en Ubuntu 24.04: un primario con tu zona, un secundario sincronizado mediante transferencias y notificaciones, recursión desactivada, limitación de respuestas y DNSSEC con gestión automática de claves.
Como siguientes pasos, puedes proteger las transferencias de zona con claves TSIG en lugar de filtrar solo por IP, añadir una zona inversa para tus direcciones IP si tu proveedor te delega el PTR, o monitorizar ambos servidores con consultas dig periódicas desde un sistema externo.
