DNS dinámico · 8 min read · Oct 02, 2025

Cómo implementar un servidor DNS dinámico con Docker en Debian 10

El DNS dinámico es un servicio de red para mapear nombres de dominio a direcciones IP dinámicas (temporales, que cambian con frecuencia). Se utiliza para acceder a computadoras que no tienen una dirección IP estática, como las que se encuentran en redes SOHO (Pequeña Oficina/Oficina en Casa), y a menudo se utiliza en combinación con el reenvío de puertos para acceder a sistemas que están detrás de cortafuegos NAT. Este artículo te guiará a través de la configuración completa de un servidor DNS dinámico en un contenedor Docker en un sistema Debian 10, incluyendo la configuración de los registros DNS requeridos, colocando la API de gestión detrás de un proxy inverso HTTPS de Nginx y automatizando las actualizaciones de registros DNS del lado del cliente.

Requisitos

  • Un solo servidor Debian 10, opcionalmente con conectividad IPv6. (192.0.2.2 y 2001:0db8::0db9 se utilizarán como marcadores de posición para la IPv4 y la IPv6 del servidor, respectivamente.)
  • Acceso al usuario root, o un usuario con privilegios sudo.
  • Los puertos tcp/53 y udp/53 deben estar disponibles en el host.
  • Un nombre de dominio registrado y acceso a sus servidores de nombres/archivo de zona. Crea registros DNS para este dominio como se muestra en la siguiente sección.
  • La variable de entorno $EDITOR debe estar configurada.
  • Opcionalmente, cualquier sistema cliente Linux/Unix para configurar actualizaciones automáticas de registros DNS.

Creando registros DNS.

Necesitarás crear al menos 2 registros DNS para que tu servidor DNS dinámico funcione. Primero, elige un subdominio como ns1.tu_dominio que apuntará a la dirección IPv4 de tu servidor. En segundo lugar, elige un subdominio como ddns.tu_dominio que será delegado a ns1.tu_dominio.

Tu servidor DNS dinámico manejará todos los registros bajo ddns.tu_dominio. El tercer registro, de tipo AAAA, es opcional. Los registros correspondientes se ven como los siguientes:

ns1.tu_dominio A 192.0.2.2
ddns.tu_dominio NS ns1.tu_dominio
ns1.tu_dominio AAAA 2001:0db8::0db9 (opcional)

Ejemplo de registros DNS

Deberías crear estos registros en el panel de control de tu registrador de dominios. Ten en cuenta que puede tardar hasta 24 horas en propagarse bien, pero generalmente toma minutos.

Instalación

Si no estás utilizando el usuario root, te recomendamos que inicies un shell root temporal, ya que la mayoría de los comandos mostrados en esta guía requieren privilegios elevados. Para lanzar un shell root, utiliza uno de los siguientes comandos:

sudo su - root
sudo -s

Paso 1: Actualizando e instalando dependencias.

Siempre es una buena práctica actualizar tu sistema primero:

apt update
apt upgrade -y
reboot

Después del reinicio, instala los paquetes de software requeridos para esta configuración:

  • certbot se utilizará para obtener certificados SSL/TLS.
  • make es necesario para construir la imagen de docker en la que se ejecutará el servidor DDNS.
  • apt-transport-https, ca-certificates, curl, gnupg2 y software-properties-common son necesarios para instalar el repositorio de Docker y su correspondiente clave GPG.
  • dnsutils proporciona dig, que se utilizará para pruebas.
apt install -y certbot make apt-transport-https curl ca-certificates software-properties-common gnupg2 dnsutils

Paso 2: Instalar Docker CE.

Agrega la clave GPG de Docker:

curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -

Instala el repositorio de docker:

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable"

Actualiza la caché del repositorio de Debian y luego instala docker y sus dependencias:

apt update
apt install -y docker-ce docker-ce-cli containerd.io

Una vez que la instalación esté completa, asegúrate de que el servicio de docker esté habilitado y en ejecución de la siguiente manera:

systemctl enable --now docker.service

Paso 3: Descargar y construir docker-ddns

Nuestro servidor DNS dinámico será impulsado por un contenedor docker que utiliza Bind como servidor DNS y una API de gestión escrita en Go. Primero, clona el repositorio de Github y construye la imagen del contenedor con los siguientes comandos:

git clone https://github.com/dprandzioch/docker-ddns.git
cd docker-ddns
make image

Espera a que el proceso termine, lo que puede tardar un tiempo, luego abre el archivo envfile con un editor de texto:

$EDITOR envfile

Y escribe lo siguiente:

SHARED_SECRET=tu_secreto   
ZONE=ddns.tu_dominio   
RECORD_TTL=60

El secreto compartido es una contraseña que se utilizará para autenticar con la API de gestión. ZONE indica qué zona DNS será responsable tu servidor, y el TTL del registro especifica cuánto tiempo se pueden almacenar en caché los registros DNS. Se recomienda un TTL de 60 segundos para IPs dinámicas que cambian con frecuencia.

Si es necesario, puedes generar una cadena aleatoria de 40 caracteres para el secreto utilizando el siguiente comando:

cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 40 | head -1

Ahora podemos crear el contenedor:

docker create -it -p 127.0.0.1:8080:8080 -p 53:53 -p 53:53/udp --env-file envfile -v /mnt/ddns-data:/var/cache/bind --name ddns-server davd/docker-ddns

Este comando creará un contenedor llamado ddns-server a partir de la imagen que construimos anteriormente, y mapeará los puertos 8080/tcp, 53/tcp y 53/udp desde el host al contenedor. También montará el directorio /mnt/ddns-data desde el host, en /var/cache/bind en el sistema de archivos del contenedor. Esto se utiliza para persistir datos DNS a través de la recreación del contenedor.

Verifica que el contenedor fue creado con el comando:

docker container ls -a

Una única entrada debería ser salida con el nombre ddns-server.

Paso 4: Servicio systemd (opcional)

Este paso es para una gestión más sencilla pero no es estrictamente necesario. Si decides no usar un servicio systemd, tendrás que gestionar el contenedor manualmente o usar otra solución de gestión. Ten en cuenta que para implementaciones de contenedores más grandes y complejas, se recomienda una solución de orquestación como Kubernetes o Docker Swarm. En este caso, un servicio systemd es perfectamente adecuado, ya que solo estamos ejecutando un único contenedor.

Para poder gestionar este contenedor como un servicio del sistema, lo envolveremos en una unidad systemd. Crea el archivo /etc/systemd/system/ddns-server-ct.service con tu editor de texto:

$EDITOR /etc/systemd/system/ddns-server-ct.service

Y agrega lo siguiente:

[Unit]  
Description=Contenedor Docker del Servidor DDNS  
After=docker.service  
Requires=docker.service  
Requires=network.target  
[Service]  
Type=oneshot  
TimeoutStartSec=240  
Restart=no  
RemainAfterExit=yes  
ExecStart=/usr/bin/docker start ddns-server  
ExecStop=/usr/bin/docker stop ddns-server  
[Install]  
WantedBy=multi-user.target

Guarda y sal, luego establece los permisos correctos en este archivo de unidad:

chmod 664 /etc/systemd/system/ddns-server-ct.service

Carga el nuevo archivo de servicio con el siguiente comando:

systemctl daemon-reload

Ahora deberías poder iniciar y detener este contenedor usando systemctl como cualquier otro servicio del sistema.

Si deseas que el servidor DDNS se inicie automáticamente al arrancar el sistema, ejecuta lo siguiente:

systemctl enable ddns-server-ct.service

Paso 5: Probando tu servidor

Antes de continuar con la configuración, probaremos la API de gestión localmente. Inicia el contenedor:

systemctl start ddns-server-ct.service

Envía una solicitud GET a la API para crear un nuevo registro:

NOTA: La API actualmente solo es accesible localmente (es decir, desde localhost).

curl "http://127.0.0.1:8080/update?secret=tu_secreto&domain=test1&addr=1.1.1.1"

Curl debería devolver la siguiente respuesta:

{"Success":true,"Message":"Registro A actualizado para test1 a la dirección IP 1.1.1.1","Domain":"test1","Domains":["test1"],"Address":"1.1.1.1","AddrType":"A"}

NOTA: El dominio test1 se refiere a test1.ddns.tu_dominio. ya que el servidor está manejando la zona ddns.tu_dominio.

Realiza una búsqueda DNS para verificar que el registro fue efectivamente creado y para probar la resolución DNS:

dig +short -t A test1.ddns.tu_dominio @127.0.0.1

La salida debería ser 1.1.1.1.

Paso 6: Proxy inverso

Dado que la API funciona sobre HTTP, tu secreto de autenticación puede ser potencialmente espiado cada vez que envías una solicitud a través de la red. Un atacante podría manipular tus registros DNS utilizando tu secreto. Configuraremos un proxy inverso utilizando Nginx y lo aseguraremos utilizando HTTPS. Primero, obtén un certificado SSL de Let’s Encrypt utilizando certbot:

certbot certonly --standalone --agree-tos -m [email protected] -d ns1.tu_dominio

La propiedad de tu dominio será verificada y se emitirá un certificado. A continuación, instala Nginx y asegúrate de que esté habilitado y en ejecución:

apt install -y nginx systemctl enable --now nginx.service

Luego desactiva el archivo de bloque de servidor predeterminado, ya que no es necesario:

unlink /etc/nginx/sites-enabled/default

Ahora crearemos un nuevo archivo de configuración para el proxy inverso, por ejemplo:

$EDITOR /etc/nginx/sites-available/ddns-api-proxy.conf

Y pega lo siguiente, asegurándote de reemplazar las direcciones IP y los nombres de dominio con los tuyos:

server {  
listen 192.0.2.2:8080;  
server_name ns1.tu_dominio;  
ssl on;  
ssl_certificate /etc/letsencrypt/live/ns1.tu_dominio/fullchain.pem;  
ssl_certificate_key /etc/letsencrypt/live/ns1.tu_dominio/privkey.pem;  
  
location /update {  
proxy_pass http://127.0.0.1:8080;  
}  
location / {  
return 404;  
}  
access_log /var/log/nginx/ddns-api-access.log;  
error_log /var/log/nginx/ddns-api-error.log;  
}

Opcional: Si deseas que la API sea accesible a través de IPv6, agrega la siguiente línea después de la directiva listen existente:

listen [2001:0db8::0db9]:8080;

Habilita esta configuración y aplica los cambios recargando Nginx:

ln -s /etc/nginx/sites-available/ddns-api-proxy.conf /etc/nginx/sites-enabled/
systemctl reload nginx.service

La API ahora debería ser accesible a través de Internet y solo aceptará conexiones HTTPS. Para probarlo, emite el comando:

curl "https://ns1.tu_dominio:8080/update?secret=tu_secreto&domain=test2&addr=1.1.1.2"

Debería devolver lo siguiente:

{"Success":true,"Message":"Registro A actualizado para test2 a la dirección IP 1.1.1.2","Domain":"test2","Domains":["test2"],"Address":"1.1.1.2","AddrType":"A"}

Paso 7: Configuración del cliente

Puedes configurar actualizaciones automáticas de registros en cualquier enrutador que soporte proveedores de DNS dinámico personalizados, como Pfsense. También puedes configurarlos en la mayoría de los otros dispositivos en tu red de oficina o hogar. Para actualizar o crear un registro, se debe enviar una solicitud GET al siguiente endpoint:

https://ns1.tu_dominio:8080/update?secret=tu_secreto&domain=tu_subdominio&addr=tu_direccion_ip

También puedes actualizar los registros de múltiples subdominios con una sola solicitud. Por ejemplo, para crear/actualizar registros para sub1.ddns.tu_dominio y sub2.ddns.tu_dominio con la dirección IP 198.51.100.100, enviarías una solicitud GET a esta URL:

https://ns1.tu_dominio:8080/update?secret=tu_secreto&domain=sub1,sub2&addr=198.51.100.100

El parámetro addr también puede contener una dirección IPv6 para crear/actualizar registros DNS AAAA, por ejemplo:

https://ns1.tu_dominio:8080/update?secret=tu_secreto&domain=queso&addr=2001:0db8:aaaa::

Para automatizar estas actualizaciones en un cliente Linux, guarda el siguiente script bash como /opt/ddns-update.sh:

#!/bin/bash  
  
while [ -z $CURRENTIP ]
do  
CURRENTIP=`dig -r +short myip.opendns.com @resolver1.opendns.com 2>/dev/null`  
sleep 1  
done  
curl -s "https://ns1.tu_dominio:8080/update?secret=tu_secreto&domain=tu_subdominio&addr=${CURRENTIP}"

Este script emplea un bucle while que envuelve un comando dig que obtiene la dirección IP pública del cliente y la almacena en una variable. El bucle asegura que la IP pública se obtenga correctamente. Luego, se utiliza cURL para enviar una solicitud API para actualizar el registro DNS con esta IP recién obtenida. Asegúrate de reemplazar los valores de tu_secreto y tu_subdominio.

A continuación, haz que este script sea ejecutable:

chmod +x /opt/ddns-update.sh

Luego lanza el editor de crontab:

crontab -e

Agrega la siguiente línea al final de tu crontab:

*/2 * * * * /opt/ddns-update.sh

Guarda y sal. El script ahora se ejecutará cada dos minutos, manteniendo tu registro DNS dinámico actualizado con la última dirección IP pública del cliente.

Lectura adicional

  • Artículo de Wikipedia sobre DNS dinámico
  • docker-ddns en Github
Share: X/Twitter LinkedIn

Recibe nuevas publicaciones en tu bandeja de entrada.

No spam. Cancela la suscripción en cualquier momento.