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..9757a2c 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 --log-driver=journald" - name: proxy update, after certs renewal cron: