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.2ddns.tu_dominio NS ns1.tu_dominions1.tu_dominio AAAA 2001:0db8::0db9 (opcional)
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 - rootsudo -sPaso 1: Actualizando e instalando dependencias.
Siempre es una buena práctica actualizar tu sistema primero:
apt updateapt upgrade -yrebootDespué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 dnsutilsPaso 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 updateapt install -y docker-ce docker-ce-cli containerd.ioUna 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.servicePaso 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.gitcd docker-ddnsmake imageEspera a que el proceso termine, lo que puede tardar un tiempo, luego abre el archivo envfile con un editor de texto:
$EDITOR envfileY escribe lo siguiente:
SHARED_SECRET=tu_secreto
ZONE=ddns.tu_dominio
RECORD_TTL=60El 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 -1Ahora 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-ddnsEste 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.targetGuarda y sal, luego establece los permisos correctos en este archivo de unidad:
chmod 664 /etc/systemd/system/ddns-server-ct.serviceCarga el nuevo archivo de servicio con el siguiente comando:
systemctl daemon-reloadAhora 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.servicePaso 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.serviceEnví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.1La 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_dominioLa 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.serviceLuego desactiva el archivo de bloque de servidor predeterminado, ya que no es necesario:
unlink /etc/nginx/sites-enabled/defaultAhora crearemos un nuevo archivo de configuración para el proxy inverso, por ejemplo:
$EDITOR /etc/nginx/sites-available/ddns-api-proxy.confY 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.serviceLa 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_ipTambié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.shLuego lanza el editor de crontab:
crontab -eAgrega la siguiente línea al final de tu crontab:
*/2 * * * * /opt/ddns-update.shGuarda 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
Recibe nuevas publicaciones en tu bandeja de entrada.
No spam. Cancela la suscripción en cualquier momento.