From edb3a22ec0bc2a33f397e3ba447519f6ecfc4055 Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 25 Nov 2025 19:30:40 -0300 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20renovaci=C3=B3n=20autom=C3=A1tica?= =?UTF-8?q?=20de=20certificados=20SSL=20con=20dns-standalone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Activada renovación automática cada 4 y 18 de mes - Usa dns-standalone sin conflictos con dnsmasq (IPs diferentes) - Documentación completa de arquitectura DNS y validación ACME --- DNS_ARCHITECTURE.md | 162 +++++++++++++++++++++++++++++++++++ roles/certbot/tasks/main.yml | 15 ++-- 2 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 DNS_ARCHITECTURE.md diff --git a/DNS_ARCHITECTURE.md b/DNS_ARCHITECTURE.md new file mode 100644 index 0000000..9123cde --- /dev/null +++ b/DNS_ARCHITECTURE.md @@ -0,0 +1,162 @@ +# Arquitectura DNS y Validación ACME + +Este documento explica cómo funciona el sistema DNS distribuido y la validación de certificados SSL para dominios FQDN. + +## Componentes DNS + +### 1. Servidores Knot (Autoritativos Remotos) + +**Ubicación:** `anarres.sutty.nl`, `athshe.sutty.nl`, `gethen.sutty.nl`, `ganam.sutty.nl` + +**Función:** DNS autoritativo real para: +- Zona `abyaya.la` +- Zonas FQDN (ej: `latina.red`, `example.com.ar`) + +**Actualización:** Via `knsupdate` ejecutado desde el proxy + +### 2. Proxy (Hetzner: 5.161.236.18) + +**Servicios DNS en diferentes IPs:** + +| Servicio | IP | Puerto | Función | +|----------|-------|--------|---------| +| **dnsmasq** | `10.13.12.1` + `127.0.0.1` | 53 | DNS cache/resolver para VPN interna | +| **certbot dns-standalone** | `5.161.236.18` | 53 | DNS temporal para validación ACME | + +**No hay conflicto de puertos** porque usan IPs diferentes en la misma máquina. + +## Flujo de Validación ACME para Dominios FQDN + +### Ejemplo: Certificado para `kipu.latina.red` + +#### Paso 1: knsupdate configura delegación en Knot + +Cuando se despliega un servicio con FQDN, `knsupdate` crea estos registros en los servidores Knot: + +```dns +; En zona latina.red +kipu.latina.red IN A 5.161.236.18 +*.kipu.latina.red IN A 5.161.236.18 +_acme-challenge.kipu.latina.red IN CNAME abyaya.la. +_acme-challenge.kipu.latina.red IN NS _acme-challenge.abyaya.la. + +; En zona abyaya.la +_acme-challenge.abyaya.la IN A 5.161.236.18 +_acme-challenge IN NS _acme-challenge.abyaya.la. +``` + +**Propósito de la delegación:** +- El CNAME redirige la validación a `abyaya.la` +- El NS delega la autoridad a `_acme-challenge.abyaya.la` +- Que apunta al proxy donde certbot corre + +#### Paso 2: Certbot obtiene/renueva certificado + +```bash +docker run --rm \ + -v abyayala_certs_data:/etc/letsencrypt \ + --network host \ + numericalatina/certbot-wildcard \ + certonly --dns-standalone-address=5.161.236.18 --dns-standalone-port=53 \ + -d kipu.latina.red -d *.kipu.latina.red +``` + +**Certbot:** +1. Levanta un servidor DNS temporal en `5.161.236.18:53` +2. Crea el registro TXT con el token de validación +3. Notifica a Let's Encrypt que está listo + +#### Paso 3: Let's Encrypt valida + +``` +Let's Encrypt consulta: _acme-challenge.kipu.latina.red + ↓ Consulta a nameservers de latina.red (Knot) + ↓ Knot responde con CNAME + +Redirigido a: _acme-challenge.abyaya.la + ↓ Consulta delegación NS + ↓ Knot indica: usar nameserver _acme-challenge.abyaya.la + +Consulta directa a: 5.161.236.18:53 + ↓ certbot dns-standalone responde + ↓ Proporciona el token TXT + +✓ Validación exitosa +``` + +## Configuración Requerida en DNS Externo + +Para que un dominio FQDN externo (no `.abyaya.la`) pueda delegar la validación ACME al proxy, es necesario agregar estos registros en el DNS del dominio: + +```dns +_acme-challenge IN CNAME abyaya.la. +_acme-challenge IN NS _acme-challenge.abyaya.la. +``` + +**Ejemplo para `kipu.latina.red`:** +```dns +; En el DNS de latina.red +_acme-challenge.kipu IN CNAME abyaya.la. +_acme-challenge.kipu IN NS _acme-challenge.abyaya.la. +``` + +Esto se hace **una sola vez por dominio** y permite que todos los subdominios deleguen automáticamente. + +## Renovación Automática + +La renovación de certificados funciona automáticamente porque: + +1. ✅ **Delegación persistente**: Los registros `_acme-challenge` ya están en Knot +2. ✅ **Cron configurado**: Se ejecuta los días 4 y 18 de cada mes +3. ✅ **Sin conflictos**: dnsmasq y certbot usan IPs diferentes +4. ✅ **Mismo método**: `certbot renew` usa dns-standalone automáticamente + +```yaml +# Configurado en roles/certbot/tasks/main.yml +- name: automatic letsencrypt certs renewal + cron: + name: certificate renewal + day: 4,18 + hour: 0 + minute: 0 + job: "docker run --rm -v abyayala_certs_data:/etc/letsencrypt --network host numericalatina/certbot-wildcard renew --dns-standalone-address=5.161.236.18 --dns-standalone-port=53 >> /var/log/renewal.log 2>&1" +``` + +## Ventajas de esta Arquitectura + +1. **Centralizada**: Un solo proxy maneja validación ACME para todos los dominios +2. **Segura**: No requiere credenciales API de proveedores DNS externos +3. **Flexible**: Soporta dominios `.abyaya.la` y FQDN externos +4. **Automatizada**: Renovación sin intervención manual +5. **Escalable**: Agregar nuevos dominios solo requiere actualizar `abyayala.yml` + +## Troubleshooting + +### Verificar delegación DNS + +```bash +# Verificar CNAME +dig _acme-challenge.kipu.latina.red CNAME + +# Verificar NS delegation +dig _acme-challenge.kipu.latina.red NS + +# Probar resolución completa +dig @5.161.236.18 _acme-challenge.kipu.latina.red TXT +``` + +### Ver logs de renovación + +```bash +tail -f /var/log/renewal.log +``` + +### Probar renovación manualmente + +```bash +docker run --rm \ + -v abyayala_certs_data:/etc/letsencrypt \ + --network host \ + numericalatina/certbot-wildcard \ + renew --dns-standalone-address=5.161.236.18 --dns-standalone-port=53 --dry-run +``` diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml index 2ebffae..3b8fec3 100644 --- a/roles/certbot/tasks/main.yml +++ b/roles/certbot/tasks/main.yml @@ -30,14 +30,13 @@ env: yes value: /bin/bash -# TODO -# - name: automatic letsencrypt certs renewal -# cron: -# name: certificate renewal -# day: 4,18 -# hour: 0 -# minute: 0 -# job: "docker run --rm -v {{ althost }}_certs_data:/etc/letsencrypt -v {{ althost }}_certs_www:/var/www/letsencrypt certbot/certbot renew >> /var/log/renewal.log 2>&1" + - name: automatic letsencrypt certs renewal + cron: + name: certificate renewal + day: 4,18 + hour: 0 + minute: 0 + job: "docker run --rm -v {{ althost }}_certs_data:/etc/letsencrypt --network host {{ CERTBOT_image }} renew --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 >> /var/log/renewal.log 2>&1" - name: proxy update, after certs renewal cron: -- 2.49.0 From 127504cb625b412cca7bc02e62f1d7dfff830551 Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 2 Dec 2025 17:37:18 -0300 Subject: [PATCH 2/2] fix logs del certbot --- roles/certbot/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml index 3b8fec3..9757a2c 100644 --- a/roles/certbot/tasks/main.yml +++ b/roles/certbot/tasks/main.yml @@ -36,7 +36,7 @@ day: 4,18 hour: 0 minute: 0 - job: "docker run --rm -v {{ althost }}_certs_data:/etc/letsencrypt --network host {{ CERTBOT_image }} renew --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 >> /var/log/renewal.log 2>&1" + job: "docker run --rm -v {{ althost }}_certs_data:/etc/letsencrypt --network host {{ CERTBOT_image }} renew --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --log-driver=journald" - name: proxy update, after certs renewal cron: -- 2.49.0