↓ Ir al contenido

Recuperación ante fallos de DNS en infraestructura doméstica con BIND9, redundancia y failover automático

Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

El problema
#

Hace unos meses mi servidor DNS se cayó sin aviso. No fue catastrófico, pero sí incómodo: durante varias horas ningún dispositivo en la red doméstica podía resolver dominios. Aprendí la lección: un DNS centralizado es un punto único de fallo que no puedo permitirme.

La solución obvia es redundancia. Necesitaba dos servidores DNS independientes con failover automático. Esto es lo que implementé.

La arquitectura
#

Configuré dos máquinas con BIND9:

  • ns1: servidor primario (maestro)
  • ns2: servidor secundario (esclavo)

Ambos resuelven consultas. Si ns1 cae, los clientes se redirigen automáticamente a ns2. En la red doméstica, los equipos apuntan a ambos servidores en su configuración de DHCP.

Instalación base
#

En ambas máquinas instalé BIND9:

sudo apt-get update
sudo apt-get install bind9 bind9-utils bind9-doc
sudo systemctl enable named

Configuración del servidor primario (ns1)
#

Edité /etc/bind/named.conf.local:

zone "ejemplo.local" {
    type master;
    file "/etc/bind/zones/db.ejemplo.local";
    allow-transfer { 192.168.1.20; };
    notify yes;
    also-notify { 192.168.1.20; };
};

Las líneas clave:

  • allow-transfer: permite que ns2 descargue la zona
  • notify: notifica automáticamente al secundario de cambios
  • also-notify: especifica la IP del secundario

Luego creé el archivo de zona /etc/bind/zones/db.ejemplo.local:

$TTL 3600
@   IN  SOA ns1.ejemplo.local. admin.ejemplo.local. (
            2026090401  ; serial
            3600        ; refresh
            1800        ; retry
            604800      ; expire
            86400 )     ; minimum
    IN  NS  ns1.ejemplo.local.
    IN  NS  ns2.ejemplo.local.

ns1 IN  A   192.168.1.10
ns2 IN  A   192.168.1.20

@   IN  A   192.168.1.10

El serial es crítico: cada cambio requiere incrementarlo. Uso YYYYMMDDNN como formato.

Configuración del servidor secundario (ns2)
#

En /etc/bind/named.conf.local del secundario:

zone "ejemplo.local" {
    type slave;
    masters { 192.168.1.10; };
    file "/etc/bind/zones/db.ejemplo.local";
};

Mucho más simple. El secundario descarga la zona completa del primario y la mantiene sincronizada.

Validación de configuración
#

Antes de reiniciar, validé la sintaxis:

sudo named-checkconf
sudo named-checkzone ejemplo.local /etc/bind/zones/db.ejemplo.local

Si hay errores, estos comandos lo dirán. Reinicié el servicio:

sudo systemctl restart named

Pruebas de failover
#

Desde otra máquina en la red probé la resolución:

nslookup ns1.ejemplo.local 192.168.1.10
nslookup ns1.ejemplo.local 192.168.1.20

Ambas responden correctamente. Luego simulé la caída del primario deteniendo BIND9:

sudo systemctl stop named

Las consultas al primario fallan, pero las al secundario funcionan sin problemas.

Configuración del cliente DHCP
#

En el servidor DHCP (o en los equipos estáticos), configuré ambos servidores DNS:

option domain-name-servers 192.168.1.10, 192.168.1.20;

Los clientes automáticamente intentan el primero y usan el segundo si falla.

Monitoreo en producción
#

Agregué un script simple que verifica el estado cada 5 minutos:

#!/bin/bash
for ns in 192.168.1.10 192.168.1.20; do
    dig @$ns ejemplo.local +short | grep -q "192.168.1" || \
    echo "ALERTA: NS $ns no responde" | mail -s "DNS FALLO" admin@ejemplo.local
done

Lo metí en crontab.

Lecciones aprendidas
#

La redundancia DNS no es complicada, pero los detalles importan. El serial en la zona debe estar correcto o no se sincroniza. Los permisos de archivos deben permitir que BIND lea las zonas. Y siempre validar configuración antes de reiniciar.

Desde que implementé esto, he podido reiniciar servidores sin perder resolución DNS. Eso es tranquilidad en infraestructura doméstica.