--- title: "Conmutación por error de DNS con PowerDNS y registros LUA" description: "Configura PowerDNS en Ubuntu 24.04 con registros LUA que comprueban tus servidores web y responden con la IP de respaldo cuando cae el servidor principal." category: "Migración y Recuperación ante Desastres" language: es source: https://cubepath.com/es/docs/migración-y-recuperación-ante-desastres/configuracion-de-conmutacion-por-error-de-dns updated: 2026-09-25 --- # Conmutación por error de DNS con PowerDNS y registros LUA 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: | Estrategia | Comprueba la salud | Uso típico | |---|---|---| | Round robin (varios registros `A`) | No | Repartir carga; si un servidor cae, parte de los clientes falla | | Activo-activo con comprobación | Sí | Devolver todas las IP sanas | | Activo-pasivo con comprobación | Sí | 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: ```bash 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: ```bash sudo nano /etc/powerdns/pdns.d/failover.conf ``` ```ini 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: ```bash sudo mkdir -p /etc/powerdns/zones sudo nano /etc/powerdns/zones/example.com.zone ``` ```text $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`: ```text @ 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`: ```bash sudo nano /etc/powerdns/named.conf ``` ```text zone "example.com" { type master; file "/etc/powerdns/zones/example.com.zone"; }; ``` Comprueba que la zona no tiene errores: ```bash sudo pdnsutil check-zone example.com ``` ```output Checked 7 records of 'example.com', 0 errors, 0 warnings. ``` Reinicia PowerDNS y verifica que está en marcha: ```bash sudo systemctl restart pdns sudo systemctl status pdns --no-pager ``` ```output ● 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: ```bash 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: ```bash dig @ns1_ip example.com A +noall +answer ``` ```output example.com. 60 IN A 203.0.113.10 ``` Simula una caída del principal. En el **servidor web principal**, detén Nginx: ```bash sudo systemctl stop nginx ``` Espera unos segundos (PowerDNS repite las comprobaciones cada 5 segundos por defecto) y vuelve a consultar: ```bash dig @ns1_ip example.com A +noall +answer ``` ```output 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`: ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash dig @1.1.1.1 example.com A +short ``` ```output 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.