Cloudflare DDNS: Actualizador DNS Dinámico en Rust
Cliente DDNS ligero para Cloudflare con imagen Docker de 1.1 MB y consumo de 3.5 MB RAM
Vídeo tutorial en YouTube
Mira el vídeo completo sobre cómo instalar y usar Cloudflare DDNS: Actualizador DNS Dinámico en Rust en el canal GENBYTE:
¿Qué es Cloudflare DDNS: Actualizador DNS Dinámico en Rust?
Cloudflare DDNS es un cliente de DNS dinámico escrito en Rust que permite acceder a una red doméstica mediante un nombre de dominio personalizado sin necesidad de IP estática. El proyecto mantiene actualizados los registros A y AAAA en Cloudflare, y opcionalmente listas de IP del WAF, apuntando a la IP pública actual. Se distribuye como una imagen Docker estática construida desde scratch de aproximadamente 1.1 MB que utiliza unos 3.5 MB de RAM. La configuración se realiza mediante variables de entorno y soporta IPv4 e IPv6 con proveedores de detección independientes, múltiples dominios y zonas, comodines, proxy por dominio, notificaciones y heartbeats.
Características principales
Detección IPv4 e IPv6 independiente
Soporta múltiples proveedores: Cloudflare trace (por defecto), Cloudflare DNS-over-HTTPS, ipify, tabla de enrutamiento local, interfaz de red, URL personalizada o IPs estáticas. Cada familia de direcciones puede usar un proveedor distinto.
Múltiples dominios y zonas
Gestiona muchos dominios en varias zonas de Cloudflare, incluyendo comodines (ej. *.example.com). Las zonas se descubren automáticamente a partir del nombre de dominio.
Seguridad ante fallos
Un fallo en la detección de IP nunca borra ni sobrescribe los registros existentes. Las IPs anycast de Cloudflare se rechazan automáticamente. Los rangos de Cloudflare se obtienen y cachean por 24 horas.
Listas WAF sincronizadas
Mantiene listas de IP del WAF de Cloudflare actualizadas con las direcciones detectadas. Requiere permiso Account › Account Filter Lists › Edit.
Proxy por dominio con expresiones
Controla qué dominios pasan por el proxy de Cloudflare mediante expresiones booleanas (is, sub, !, &&, ||). Ejemplo: !is(vpn.example.com) para excluir un subdominio.
Notificaciones y heartbeats
Envía notificaciones vía shoutrrr (Discord, Slack, Telegram, Gotify, Pushover, Zulip, webhooks genéricos) y heartbeats a Healthchecks.io y Uptime Kuma en cada ciclo, inicio y apagado.
Programación flexible
Cron simple (@every 5m, @once) con jitter 0-20%, ejecución inmediata al arranque (UPDATE_ON_START), limpieza opcional al parar (DELETE_ON_STOP) y modo dry-run.
Comentarios y regex en registros
Añade comentarios a los registros gestionados y usa regex (MANAGED_RECORDS_COMMENT_REGEX) para compartir una zona con otras herramientas sin conflictos.
Multi-homed y grupos de detección
En hosts con varias interfaces (dual-WAN, instancias cloud) permite grupos numerados (DOMAINS_2, IP4_PROVIDER_2, etc.) cada uno con sus propios dominios y proveedores vinculados a interfaces específicas.
Despliegue universal
Funciona en Docker (amd64, arm64, ppc64le), Kubernetes/Helm, systemd o cualquier plataforma que soporte Rust. Imagen multi-arquitectura publicada en Docker Hub y GHCR.
Requisitos del sistema
- Docker Engine o Docker Compose
- Token de API de Cloudflare con permisos: Zone › DNS › Edit, Zone › Zone › Read, y Account › Account Filter Lists › Edit si se usan listas WAF
- Dominio(s) gestionados en Cloudflare
- Conectividad a Internet para detección de IP pública y API de Cloudflare
- Para IPv6 en Docker: network_mode: host (o –network host) porque la red bridge por defecto no tiene conectividad IPv6
Instalación con Docker Compose
Ejecutar con Docker (IPv4 únicamente)
Ejecución rápida sin red host. Se desactiva IPv6 con IP6_PROVIDER=none.
–name cloudflare-ddns \
–restart unless-stopped \
-e CLOUDFLARE_API_TOKEN=tu-api-token \
-e DOMAINS=example.com,www.example.com \
-e IP6_PROVIDER=none \
timothyjmiller/cloudflare-ddns:2.3.0
Ejecutar con Docker (IPv4 + IPv6)
Requiere red host para que la detección IPv6 funcione correctamente.
–name cloudflare-ddns \
–restart unless-stopped \
–network host \
-e CLOUDFLARE_API_TOKEN=tu-api-token \
-e DOMAINS=example.com,www.example.com \
timothyjmiller/cloudflare-ddns:2.3.0
Docker Compose (IPv4 únicamente)
Archivo docker-compose.yml listo para producción con seguridad básica y healthcheck opcional.
cloudflare-ddns:
image: timothyjmiller/cloudflare-ddns:2.3.0
container_name: cloudflare-ddns
security_opt:
– no-new-privileges:true
environment:
– CLOUDFLARE_API_TOKEN=tu-api-token
– DOMAINS=example.com,www.example.com
– PROXIED=true
– IP6_PROVIDER=none
– HEALTHCHECKS=https://hc-ping.com/tu-uuid
restart: unless-stopped
Docker Compose (IPv4 + IPv6 con secretos)
Usa Docker secrets para no exponer el token en el archivo compose. Requiere network_mode: host.
cloudflare-ddns:
image: timothyjmiller/cloudflare-ddns:2.3.0
container_name: cloudflare-ddns
security_opt:
– no-new-privileges:true
network_mode: host
environment:
– CLOUDFLARE_API_TOKEN_FILE=/run/secrets/cloudflare_api_token
– DOMAINS=example.com,www.example.com
secrets:
– cloudflare_api_token
restart: unless-stopped
secrets:
cloudflare_api_token:
file: ./cloudflare_api_token.txt
Kubernetes con Helm (recomendado)
Chart publicado como artefacto OCI en GHCR. Usa values.yaml para configuración.
–namespace ddns –create-namespace \
-f values.yaml
# values.yaml ejemplo:
cloudflare:
apiToken: tu-api-token
domains: example.com,www.example.com
ip6Provider: cloudflare.trace
proxied: "true"
shoutrrr: |
discord://token@webhook-id
healthchecks: https://hc-ping.com/tu-uuid
systemd (binario nativo)
Compila desde fuente e instala unidades systemd con temporizador cada 15 minutos.
sudo install -m 755 target/release/cloudflare-ddns /usr/local/bin/cloudflare-ddns
sudo install -d -m 700 /etc/cloudflare-ddns
sudo tee /etc/cloudflare-ddns/env >/dev/null <<'EOF'
CLOUDFLARE_API_TOKEN=tu-api-token
DOMAINS=example.com,www.example.com
EOF
sudo chmod 600 /etc/cloudflare-ddns/env
sudo cp systemd/cloudflare-ddns.service systemd/cloudflare-ddns.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable –now cloudflare-ddns.timer
Acceder al proyecto
Acceso remoto vía dominio
Una vez configurado, los dominios listados en DOMAINS, IP4_DOMAINS o IP6_DOMAINS resuelven a la IP pública actual del host. Permite acceder a servicios autohospedados (VPN, NAS, Home Assistant, etc.) usando nombres como home.example.com o vpn.example.com sin IP fija.
Verificación de funcionamiento
Revisa los logs del contenedor: docker logs cloudflare-ddns. Cada ciclo muestra IPs detectadas, registros actualizados/creados, estado de listas WAF y heartbeats. En modo QUIET=true solo se muestran avisos y errores.
Casos de uso
- Acceso remoto a red doméstica sin IP estática (VPN, escritorio remoto, cámaras, NAS)
- Servicios autohospedados accesibles por dominio propio (Home Assistant, Plex, Nextcloud, Gitea)
- Actualización automática de registros DNS para instancias cloud con IP dinámica
- Sincronización de listas de IP en WAF de Cloudflare para reglas de firewall basadas en IP de origen
- Entornos multi-WAN o multi-interfaz donde cada proveedor de conectividad actualiza su propio conjunto de dominios
- Despliegues en Raspberry Pi, servidores caseros, VPS o clusters Kubernetes ligeros
Configuración avanzada
Grupos de detección multi-interfaz
Define grupos numerados (sufijo _2, _3…) para hosts con varias interfaces de red. Cada grupo tiene sus propios dominios y proveedores vinculados a interfaces específicas.
DOMAINS_2=b.example.com # grupo 2
IP4_PROVIDER_2=cloudflare.trace@ens5 # IPv4 detectado vía ens5
IP6_PROVIDER_2=local.iface:ens5 # IPv6 leído de interfaz ens5
Listas WAF de Cloudflare
Mantiene listas de IP (account-id/list-name) sincronizadas con todas las IPs detectadas (IPv4 e IPv6). La lista se crea si no existe. El nombre solo admite minúsculas, dígitos y guion bajo.
WAF_LIST_DESCRIPTION=Gestionado por cloudflare-ddns
WAF_LIST_ITEM_COMMENT=ddns-auto
MANAGED_WAF_LIST_ITEMS_COMMENT_REGEX=^ddns-auto$
Notificaciones múltiples (shoutrrr)
Una URL por línea en variable SHOUTRRR. En Docker Compose usa bloque YAML. Soporta Discord, Slack, Telegram, Gotify, Pushover, Zulip y webhooks genéricos.
SHOUTRRR: |
discord://token@webhook-id
telegram://bot-token@telegram?chats=123456789
gotify://host/app-token
generic+https://webhook.example.com/ddns?messagekey=text
Heartbeats Healthchecks.io y Uptime Kuma
Envía ping de inicio, cada ciclo (éxito/fallo) y apagado. Para Uptime Kuma usa monitor tipo Push; la URL puede incluir parámetros que se eliminan automáticamente.
UPTIMEKUMA=https://kuma.example.com/api/push/tu-token
Comentarios y regex para zonas compartidas
Etiqueta los registros gestionados con un comentario fijo y usa regex para que la herramienta solo toque sus propios registros, permitiendo convivir con otras herramientas en la misma zona.
MANAGED_RECORDS_COMMENT_REGEX=^managed by cloudflare-ddns$
Expresiones de proxy (PROXIED)
Controla proxy por dominio con expresiones booleanas. Valores: true/false, is(dominio), sub(dominio), !, &&, ||. Ejemplo: proxy todo excepto vpn.
Modo dry-run y ejecución única
Bandera –dry-run para simular cambios sin escribir en Cloudflare. UPDATE_CRON=@once ejecuta un ciclo y sale con código 1 si falla, útil para cron/systemd.
# O en compose con variable:
UPDATE_CRON=@once
UPDATE_ON_START=true
DELETE_ON_STOP=false
Gestión y mantenimiento
Actualización de imagen
Las imágenes se etiquetan con versión completa (2.3.0), menor (2.3), mayor (2) y latest. En producción fija versión exacta (2.3.0) y actualiza deliberadamente tras leer CHANGELOG.md.
docker compose up -d
Rotación de token API
Crea nuevo token en Cloudflare con mismos permisos y zonas. Actualiza el secreto (Docker secret, Kubernetes secret o archivo env) y reinicia el contenedor/servicio.
Limpieza de registros al detener
Con DELETE_ON_STOP=true, al recibir SIGTERM/SIGINT borra los registros gestionados y limpia ítems WAF. Útil en entornos efímeros. Por defecto false.
Solución de problemas IPv6 en Docker
La red bridge por defecto no tiene IPv6. Usa network_mode: host o –network host. Si no necesitas IPv6, establece IP6_PROVIDER=none.
Problemas con Cloudflare WARP/Zero Trust
Si el host usa WARP, la detección ve IPs de Cloudflare que son rechazadas. Excluye cloudflare.com y api.cloudflare.com del túnel WARP (split tunnel) o usa proveedor alternativo (ipify, url:, local.iface).
IP6_PROVIDER=ipify
Monitoreo de salud
Configura HEALTHCHECKS o UPTIMEKUMA para alertas si el contenedor deja de enviar heartbeats. Intervalo del monitor mayor que UPDATE_CRON + 20% jitter (ej. 7 min para default 5 min).
Stack técnico
- Rust (lenguaje principal)
- Docker (imagen multi-arquitectura: amd64, arm64, ppc64le)
- Docker Compose
- Kubernetes / Helm (chart OCI en GHCR)
- systemd (unidades nativas)
- API de Cloudflare (DNS, Zone, Account Filter Lists)
- shoutrrr (biblioteca de notificaciones unificada)
- UPX (compresión de binario en imagen scratch)
Referencias oficiales
- Repositorio GitHub: https://github.com/timothymiller/cloudflare-ddns
- Imagen en Docker Hub: https://hub.docker.com/r/timothyjmiller/cloudflare-ddns
- Documentación oficial del proyecto: https://timknowsbest.com/free-dynamic-dns
- Crear token API de Cloudflare: https://dash.cloudflare.com/profile/api-tokens
- Guía de tokens API Cloudflare: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
- Encontrar IDs de zona y cuenta: https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/
- Rangos IP de Cloudflare: https://www.cloudflare.com/ips/
- Changelog del proyecto: https://github.com/timothymiller/cloudflare-ddns/blob/master/CHANGELOG.md
- Licencia GPL-3.0: https://github.com/timothymiller/cloudflare-ddns/blob/master/LICENSE
Apoya el canal GENBYTE
¿Te ha sido útil este contenido?
Suscríbete a YouTube
Newsletter GENBYTE
Ko-fi
Contacto: [email protected]
