Instalación y Configuración de PowerDNS

PowerDNS es un servidor DNS autoritativo de alto rendimiento y código abierto que soporta múltiples backends de base de datos (MySQL, PostgreSQL, SQLite) para almacenar zonas y registros, lo que permite su gestión mediante API REST y herramientas externas. Con soporte completo para DNSSEC y una API moderna, es la elección preferida en entornos de hosting y proveedores DNS. Esta guía cubre la instalación de PowerDNS con backend MySQL, gestión de zonas y configuración DNSSEC.

Requisitos Previos

  • Ubuntu 22.04/Debian 12 o CentOS 9/Rocky Linux 9
  • MySQL 8.0 o MariaDB 10.6+ (o PostgreSQL 14+)
  • Mínimo 1 GB de RAM
  • Puerto 53 TCP/UDP disponible
  • Acceso root al servidor

Instalación de PowerDNS

# Ubuntu/Debian: usar el repositorio oficial de PowerDNS
# (los paquetes de distribución suelen ir atrasados)
curl -fsSL https://repo.powerdns.com/FD380FBB-pub.asc | \
  gpg --dearmor -o /usr/share/keyrings/powerdns-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/powerdns-archive-keyring.gpg] \
  https://repo.powerdns.com/ubuntu $(lsb_release -cs)-auth-master main" | \
  tee /etc/apt/sources.list.d/pdns.list

# Dar prioridad al repositorio de PowerDNS sobre los de Ubuntu
cat > /etc/apt/preferences.d/pdns << 'EOF'
Package: pdns-*
Pin: origin repo.powerdns.com
Pin-Priority: 600
EOF

apt-get update
apt-get install -y pdns-server pdns-backend-mysql

# CentOS/Rocky Linux
dnf install -y epel-release
dnf install -y pdns pdns-backend-mysql

# Verificar la instalación
pdns_server --version

Configuración del Backend MySQL

# Instalar MySQL si no está disponible
apt-get install -y mysql-server  # Ubuntu/Debian
# dnf install -y mysql-server && systemctl enable --now mysqld  # CentOS

# Crear la base de datos y usuario para PowerDNS
mysql -u root << 'EOF'
CREATE DATABASE pdns CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'pdns'@'localhost' IDENTIFIED BY 'password_seguro_pdns';
GRANT ALL PRIVILEGES ON pdns.* TO 'pdns'@'localhost';
FLUSH PRIVILEGES;
EOF

# Importar el esquema de base de datos de PowerDNS
mysql -u pdns -p pdns < /usr/share/doc/pdns-backend-mysql/schema.mysql.sql

# Verificar que las tablas se crearon correctamente
mysql -u pdns -ppassword_seguro_pdns pdns -e "SHOW TABLES;"
# Debe mostrar: comments, cryptokeys, domainmetadata, domains, records, supermasters, tsigkeys

Configuración del Servidor

# Hacer copia de seguridad de la configuración por defecto
cp /etc/powerdns/pdns.conf /etc/powerdns/pdns.conf.original

# Configuración principal de PowerDNS
cat > /etc/powerdns/pdns.conf << 'EOF'
# Backend de base de datos
launch=gmysql

# Configuración del backend MySQL
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=password_seguro_pdns
gmysql-dnssec=yes  # Habilitar soporte DNSSEC en la base de datos

# Configuración de red
local-address=0.0.0.0
local-port=53
allow-axfr-ips=127.0.0.1,10.0.1.0/24  # IPs permitidas para transferencias de zona

# API REST (necesaria para gestión programática)
api=yes
api-key=tu_api_key_seguro_aqui
webserver=yes
webserver-address=127.0.0.1
webserver-port=8081
webserver-allow-from=127.0.0.1,10.0.0.0/8

# Rendimiento
max-tcp-connections=20
cache-ttl=20
negquery-cache-ttl=60
query-cache-ttl=20

# Logging (reducir en producción)
loglevel=4
log-dns-queries=no

# Seguridad
setuid=pdns
setgid=pdns
EOF

# Iniciar y habilitar PowerDNS
systemctl enable --now pdns

# Verificar que el servicio arrancó correctamente
systemctl status pdns

Gestión de Zonas y Registros

Gestiona zonas mediante la herramienta de línea de comandos pdnsutil:

# Crear una zona nueva
pdnsutil create-zone empresa.com

# Añadir registros a la zona
pdnsutil add-record empresa.com @ SOA "ns1.empresa.com. admin.empresa.com. 1 3600 900 604800 300"
pdnsutil add-record empresa.com @ NS ns1.empresa.com
pdnsutil add-record empresa.com @ NS ns2.empresa.com
pdnsutil add-record empresa.com @ A 93.184.216.34
pdnsutil add-record empresa.com www A 93.184.216.34
pdnsutil add-record empresa.com mail MX "10 mail.empresa.com"
pdnsutil add-record empresa.com mail A 93.184.216.50
pdnsutil add-record empresa.com @ TXT "v=spf1 mx -all"

# Verificar los registros de la zona
pdnsutil list-zone empresa.com

# Verificar la consistencia de la zona
pdnsutil check-zone empresa.com

# Incrementar el número de serie (SOA serial)
pdnsutil increase-serial empresa.com

# Gestión directa con MySQL (alternativa)
mysql -u pdns -ppassword_seguro_pdns pdns << 'EOF'
-- Insertar zona
INSERT INTO domains (name, type) VALUES ('empresa.com', 'NATIVE');

-- Obtener el ID de la zona
SELECT id FROM domains WHERE name='empresa.com';

-- Insertar registros (usar el ID obtenido)
INSERT INTO records (domain_id, name, type, content, ttl)
VALUES 
  (1, 'empresa.com', 'A', '93.184.216.34', 300),
  (1, 'www.empresa.com', 'CNAME', 'empresa.com', 300);
EOF

API REST

PowerDNS expone una API REST completa para automatización:

# Variable para la API key
API_KEY="tu_api_key_seguro_aqui"
API_URL="http://localhost:8081/api/v1"

# Listar todas las zonas
curl -H "X-API-Key: $API_KEY" "$API_URL/servers/localhost/zones" | python3 -m json.tool

# Crear una zona nueva via API
curl -X POST -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  "$API_URL/servers/localhost/zones" \
  -d '{
    "name": "nuevazona.com.",
    "kind": "Native",
    "nameservers": ["ns1.empresa.com.", "ns2.empresa.com."]
  }'

# Añadir registros a una zona via API
curl -X PATCH -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  "$API_URL/servers/localhost/zones/nuevazona.com." \
  -d '{
    "rrsets": [{
      "name": "www.nuevazona.com.",
      "type": "A",
      "ttl": 300,
      "changetype": "REPLACE",
      "records": [{"content": "93.184.216.34", "disabled": false}]
    }]
  }'

# Obtener detalles de una zona
curl -H "X-API-Key: $API_KEY" \
  "$API_URL/servers/localhost/zones/empresa.com." | python3 -m json.tool

# Eliminar un registro
curl -X PATCH -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  "$API_URL/servers/localhost/zones/empresa.com." \
  -d '{
    "rrsets": [{
      "name": "old.empresa.com.",
      "type": "A",
      "changetype": "DELETE"
    }]
  }'

Configuración DNSSEC

# Activar DNSSEC para una zona
pdnsutil secure-zone empresa.com

# Verificar las claves DNSSEC generadas
pdnsutil show-zone empresa.com

# Obtener los registros DS para enviar al registrar del dominio
pdnsutil export-zone-ds empresa.com
# Los DS records deben configurarse en el panel del registrar del dominio

# Rectificar la zona (necesario tras cambios con DNSSEC activo)
pdnsutil rectify-zone empresa.com

# Verificar la firma DNSSEC
pdnsutil check-zone empresa.com

# Probar la resolución con DNSSEC
dig +dnssec empresa.com @localhost
dig +dnssec empresa.com DS @8.8.8.8  # Verificar el DS en el padre

# Rotación de claves (KSK - Key Signing Key)
pdnsutil generate-zone-key empresa.com ksk 257 13  # Algoritmo ECDSA P-256
pdnsutil activate-zone-key empresa.com <key-id>
pdnsutil deactivate-zone-key empresa.com <old-key-id>

Ajuste de Rendimiento

# Parámetros de rendimiento en pdns.conf
# cache-ttl=20           - TTL de la caché interna en segundos
# max-queue-length=5000  - Máxima longitud de la cola de consultas
# receiver-threads=4     - Hilos receptores (ajustar según CPUs)
# distributor-threads=3  - Hilos distribuidores de consultas

# Optimización de MySQL para PowerDNS
mysql -u root << 'EOF'
-- Índices adicionales para mejorar el rendimiento de consultas frecuentes
ALTER TABLE records ADD INDEX rec_name_index (name, type);
ALTER TABLE records ADD INDEX domain_id (domain_id);
EOF

# Verificar estadísticas de PowerDNS
pdns_control show '*'
pdns_control show cache-hits
pdns_control show cache-misses
pdns_control show queries

# Limpiar la caché de PowerDNS
pdns_control purge
pdns_control purge empresa.com  # Solo para un dominio específico

Solución de Problemas

# Ver logs en tiempo real
journalctl -u pdns -f

# Verificar que PowerDNS responde consultas
dig @localhost empresa.com SOA
dig @localhost www.empresa.com A

# Verificar la conectividad a la base de datos
pdns_server --daemon=no --log-dns-queries=yes --loglevel=7 2>&1 | head -50

# Comprobar la configuración sin iniciar el servicio
pdns_server --config

# Verificar que el backend está respondiendo
pdnsutil check-all-zones

# Problema: "Unable to determine backend" - verificar gmysql-* en pdns.conf
# Problema: "Operationally down" - verificar que MySQL está activo
systemctl status mysql
mysql -u pdns -ppassword_seguro_pdns pdns -e "SELECT COUNT(*) FROM domains;"

Conclusión

PowerDNS con backend MySQL ofrece una plataforma DNS autoritativa robusta y gestionable programáticamente, ideal para proveedores de hosting y entornos donde los registros DNS cambian frecuentemente. La API REST y el soporte completo de DNSSEC, combinados con su alto rendimiento demostrado en producción, hacen de PowerDNS la opción más completa para gestión DNS empresarial a escala.