La conmutación por error de DNS (DNS failover) hace que el nombre de tu servicio apunte automáticamente a un servidor de respaldo cuando el principal deja de responder. Es una forma sencilla de tener alta disponibilidad entre dos centros de datos sin balanceadores compartidos. En esta guía configurarás PowerDNS Authoritative en Ubuntu 24.04 con registros LUA, que comprueban la salud de cada servidor web y devuelven la IP del principal mientras funciona y la del respaldo cuando cae.

Cómo funciona y qué limitaciones tiene

Un servidor DNS autoritativo con comprobaciones de salud consulta periódicamente tus servidores web. Cuando un resolutor pregunta por el dominio, responde solo con las IP que están sanas. Hay varias estrategias habituales:

EstrategiaComprueba la saludUso típico
Round robin (varios registros A)NoRepartir carga; si un servidor cae, parte de los clientes falla
Activo-activo con comprobaciónSíDevolver todas las IP sanas
Activo-pasivo con comprobaciónSíPrincipal mientras funcione, respaldo solo si cae

Esta guía implementa el modelo activo-pasivo. Antes de empezar, ten en cuenta sus límites:

  • El cambio no es instantáneo: los resolutores guardan la respuesta durante el TTL del registro. Con un TTL de 60 segundos, la mayoría de clientes cambian en uno o dos minutos, pero algunos resolutores y aplicaciones ignoran TTL tan bajos.
  • Los datos deben estar en ambos servidores: el DNS solo cambia a dónde van los clientes. El servidor de respaldo necesita una copia actualizada de la aplicación y de la base de datos, por ejemplo mediante replicación.
  • Las conexiones abiertas no se migran: los clientes conectados al servidor caído reintentarán y resolverán de nuevo.

Requisitos previos

  • Dos servidores con Ubuntu 24.04 LTS para DNS (ns1 y ns2), preferiblemente en ubicaciones distintas, por ejemplo dos VPS de CubePath en centros de datos diferentes. Los recursos necesarios son mínimos (1 vCPU y 1 GB de RAM bastan).
  • Dos servidores web con el mismo contenido: el principal (203.0.113.10 en los ejemplos) y el de respaldo (198.51.100.20), ambos con HTTPS válido para el dominio.
  • Un dominio (example.com en los ejemplos) cuyo registrador permita cambiar los servidores de nombres y crear registros glue.
  • Un usuario no root con privilegios sudo en los servidores DNS.

Sustituye example.com, las IP de ejemplo, ns1_ip y ns2_ip por tus valores reales en todos los archivos.

Paso 1: Instalar PowerDNS Authoritative

Ejecuta los pasos 1 a 5 en ns1; en el paso 6 replicarás la configuración en ns2.

Instala el servidor y el backend BIND, que lee las zonas desde archivos de texto con el formato clásico de BIND:

sudo apt update
sudo apt install pdns-server pdns-backend-bind

El paquete del backend crea /etc/powerdns/pdns.d/bind.conf, que activa el backend y le indica que lea las zonas declaradas en /etc/powerdns/named.conf.

Es posible que el servicio no arranque tras la instalación: en Ubuntu, systemd-resolved ya ocupa el puerto 53 en 127.0.0.53, y PowerDNS intenta escuchar en todas las direcciones. Lo resolverás en el siguiente paso indicándole que escuche solo en la IP pública.

Paso 2: Activar los registros LUA

Los registros LUA son un tipo de registro propio de PowerDNS: en lugar de una IP fija contienen una pequeña expresión que se evalúa en cada consulta. Vienen desactivados por defecto.

Crea un archivo de configuración propio:

sudo nano /etc/powerdns/pdns.d/failover.conf
local-address=ns1_ip
enable-lua-records=yes

local-address limita PowerDNS a la IP pública del servidor, evitando el conflicto con systemd-resolved. Si el servidor tiene IPv6, añádela separada por una coma.

Paso 3: Crear la zona con un registro de conmutación

Crea el directorio de zonas y el archivo de zona:

sudo mkdir -p /etc/powerdns/zones
sudo nano /etc/powerdns/zones/example.com.zone
$ORIGIN example.com.
$TTL 3600
@   IN SOA ns1.example.com. hostmaster.example.com. (
        2026092501 ; serial
        3600       ; refresh
        600        ; retry
        1209600    ; expire
        300 )      ; negative TTL

    IN NS ns1.example.com.
    IN NS ns2.example.com.

ns1 IN A ns1_ip
ns2 IN A ns2_ip

@   60 IN LUA A "ifurlup('https://example.com/', {{'203.0.113.10'}, {'198.51.100.20'}})"
www 60 IN CNAME example.com.

El registro clave es el LUA A del dominio raíz:

  • ifurlup hace una petición HTTPS a https://example.com/ contra cada IP de la lista y considera sana la que responde con un código 200.
  • Las IP están en dos grupos: {'203.0.113.10'} y {'198.51.100.20'}. PowerDNS devuelve el primer grupo que tenga alguna IP sana. Mientras el principal responda, solo se devuelve 203.0.113.10; si falla, se devuelve el respaldo. Si ninguno responde, PowerDNS sigue devolviendo alguna dirección en lugar de una respuesta vacía.
  • 60 es el TTL del registro: cuanto más bajo, antes cambian los clientes, a costa de más consultas a tus servidores DNS.

Si pones las dos IP en un mismo grupo, {'203.0.113.10', '198.51.100.20'}, obtienes el modelo activo-activo: se devuelven todas las IP sanas.

Para una comprobación más fiable que el código HTTP, apunta a una ruta de salud de tu aplicación y exige un texto concreto en la respuesta con la opción stringmatch:

@   60 IN LUA A "ifurlup('https://example.com/health', {{'203.0.113.10'}, {'198.51.100.20'}}, {stringmatch='OK'})"

Si prefieres comprobar solo que un puerto acepta conexiones, sin HTTP, usa ifportup(443, {'203.0.113.10', '198.51.100.20'}), que devuelve todas las IP con el puerto abierto.

Paso 4: Declarar la zona y arrancar PowerDNS

Añade la zona al final de /etc/powerdns/named.conf:

sudo nano /etc/powerdns/named.conf
zone "example.com" {
    type master;
    file "/etc/powerdns/zones/example.com.zone";
};

Comprueba que la zona no tiene errores:

sudo pdnsutil check-zone example.com
Checked 7 records of 'example.com', 0 errors, 0 warnings.

Reinicia PowerDNS y verifica que está en marcha:

sudo systemctl restart pdns
sudo systemctl status pdns --no-pager
● pdns.service - PowerDNS Authoritative Server
     Loaded: loaded (/usr/lib/systemd/system/pdns.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-25 10:02:11 UTC; 4s ago

Abre el puerto 53 en UFW, tanto UDP como TCP:

sudo ufw allow 53

Paso 5: Comprobar la respuesta y probar la conmutación

Consulta el servidor directamente. La primera consulta pone en marcha las comprobaciones de salud, así que repítela pasados unos segundos:

dig @ns1_ip example.com A +noall +answer
example.com.		60	IN	A	203.0.113.10

Simula una caída del principal. En el servidor web principal, detén Nginx:

sudo systemctl stop nginx

Espera unos segundos (PowerDNS repite las comprobaciones cada 5 segundos por defecto) y vuelve a consultar:

dig @ns1_ip example.com A +noall +answer
example.com.		60	IN	A	198.51.100.20

Arranca de nuevo Nginx en el principal y comprueba que la respuesta vuelve a 203.0.113.10:

sudo systemctl start nginx

Si algo no cuadra, el registro de PowerDNS muestra el resultado de las comprobaciones y los errores de los registros LUA:

sudo journalctl -u pdns -n 50 --no-pager

Paso 6: Configurar el segundo servidor DNS

Todo dominio necesita al menos dos servidores de nombres. En este diseño, ns2 es una copia idéntica de ns1 y hace sus propias comprobaciones de salud, de modo que sigue respondiendo correctamente aunque ns1 caiga. No uses transferencias de zona a un servidor secundario que no sea PowerDNS: no sabría interpretar los registros LUA.

En ns2, repite los pasos 1, 2 y 4, con local-address=ns2_ip en failover.conf. Copia el archivo de zona desde ns1:

scp your_user@ns1_ip:/etc/powerdns/zones/example.com.zone ~/
sudo mkdir -p /etc/powerdns/zones
sudo mv ~/example.com.zone /etc/powerdns/zones/

Comprueba que ns2 responde igual:

dig @ns2_ip example.com A +noall +answer

Cada vez que modifiques la zona, incrementa el número de serie del SOA, copia el archivo a ambos servidores y recarga la zona en cada uno:

sudo pdns_control bind-reload-now example.com

Si gestionas varias zonas, automatiza esta copia con Ansible o con un repositorio Git que ambos servidores sincronicen, en lugar de hacerlo a mano.

Paso 7: Delegar el dominio en tus servidores

Hasta ahora solo tú preguntas a ns1 y ns2 directamente. Para que el resto de Internet los use, en el panel de tu registrador:

  1. Crea los registros glue (a veces llamados "host records" o "servidores de nombres personalizados"): ns1.example.com con ns1_ip y ns2.example.com con ns2_ip.
  2. Cambia los servidores de nombres del dominio a ns1.example.com y ns2.example.com.

La delegación puede tardar algunas horas en propagarse, según el TTL de los registros NS de la zona padre. Compruébala siguiendo la cadena de delegación desde los servidores raíz:

dig +trace example.com A

La última sección de la salida debe mostrar la respuesta de ns1.example.com o ns2.example.com. Después consulta un resolutor público:

dig @1.1.1.1 example.com A +short
203.0.113.10

Solución de problemas

  • Unable to bind UDP socket to '0.0.0.0:53': Address already in use: PowerDNS intenta escuchar en todas las direcciones y choca con systemd-resolved. Revisa que local-address está en /etc/powerdns/pdns.d/failover.conf con la IP pública del servidor.
  • El registro LUA devuelve SERVFAIL: los registros LUA no están activados o la expresión tiene un error de sintaxis. Comprueba enable-lua-records=yes y revisa journalctl -u pdns; las comillas simples dentro de la expresión deben ir dentro de las comillas dobles del registro.
  • Siempre se devuelve el respaldo aunque el principal funciona: la comprobación HTTPS falla desde el servidor DNS. Pruébala desde ns1 con curl -sI --resolve example.com:443:203.0.113.10 https://example.com/. Un certificado no válido para el dominio o un cortafuegos que bloquea a ns1 hacen que el principal se marque como caído.
  • Los clientes tardan mucho en cambiar: revisa el TTL que llega a los resolutores con dig @1.1.1.1 example.com A. Si ves un valor alto, puede que el cambio de TTL aún no se haya propagado o que el resolutor imponga un mínimo propio.

Conclusión

Tienes dos servidores PowerDNS autoritativos que comprueban la salud de tus servidores web y apuntan el dominio al respaldo cuando el principal cae, y de vuelta al principal cuando se recupera. Recuerda que el DNS solo dirige el tráfico: el servidor de respaldo debe tener los datos al día. Como siguientes pasos, configura replicación de la base de datos entre los dos centros de datos, crea una ruta /health en tu aplicación que compruebe también sus dependencias y añade alertas de monitorización para saber cuándo se ha producido una conmutación.