Panoramica
Il protocollo ACME (utilizzato da Let's Encrypt e altre autorità di certificazione) supporta la challenge DNS-01 per la validazione del dominio. DNS-01 è l’unico tipo di challenge che supporta i certificati wildcard (*.example.com) e non richiede un server HTTP sulla macchina di destinazione.
NexDNS offre integrazioni native con i client ACME più diffusi, oltre a un hook CLI generico per qualsiasi client che supporti hook DNS manuali.
Tutte le integrazioni ACME richiedono un token API, disponibile dal piano Pro in su. Ogni client cerca la zona prima di scrivere la challenge, quindi il token deve avere
zones.readoltre arecords.readerecords.write. Ne crei uno su nexdns.tech/settings/api-keys.
Come viene validato un certificato wildcard
La challenge è un record TXT su _acme-challenge sotto il nome in fase di validazione. Un certificato che copre sia example.com sia *.example.com genera due valori di challenge diversi sullo stesso nome ed entrambi devono essere presenti contemporaneamente. Tutte le integrazioni descritte sotto gestiscono questo caso: per questo il set di record non va mai eliminato tra le due validazioni.
Tenere conto della propagazione
Un record di challenge impiega circa 30 secondi per raggiungere i name server, quindi un’attesa di 30 secondi non lascia alcun margine - ne abbiamo visto uno fallire con NXDOMAIN. Concedi all’autorità di certificazione almeno 60 secondi: il plugin certbot e lego attendono 60 per impostazione predefinita, mentre per acme.sh e l’hook CLI l’attesa la imposti tu.
acme.sh
acme.sh è un client ACME scritto interamente in shell. Il nostro hook DNS non fa ancora parte di una release di acme.sh, quindi mettilo in ~/.acme.sh/dnsapi/ prima della prima esecuzione: curl -fsSL https://get.nexdns.tech/acme/dns_nexdns.sh -o ~/.acme.sh/dnsapi/dns_nexdns.sh. Lo stesso file si trova nel repository della CLI se preferisci leggerlo prima.
Emissione di un certificato
export NEXDNS_Token="nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
acme.sh --issue --server letsencrypt --dns dns_nexdns \
--dnssleep 60 \
-d example.com -d '*.example.com'
Il token viene salvato in ~/.acme.sh/account.conf dopo la prima esecuzione, quindi non è necessario esportarlo nuovamente per i rinnovi.
Rinnovo
I rinnovi avvengono automaticamente tramite cron. Per forzare un rinnovo manuale:
acme.sh --renew -d example.com
lego / Traefik
lego è un client ACME scritto in Go, alla base anche della gestione automatica dei certificati di Traefik. Il provider è incluso in lego dalla versione 5.4.0.
Utilizzo autonomo
NEXDNS_API_TOKEN=nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
NEXDNS_PROPAGATION_TIMEOUT=300 \
lego --dns nexdns \
--domains example.com \
--domains '*.example.com' \
--email admin@example.com \
--accept-tos \
run
lego legge i timeout come un semplice numero di secondi: NEXDNS_PROPAGATION_TIMEOUT=300 funziona, mentre 300s non viene interpretato e viene sostituito silenziosamente dal valore predefinito di 60 secondi.
Configurazione Traefik
Traefik incorpora la tabella dei provider di lego in fase di build e usa ancora una versione precedente, quindi qui serve un Traefik compilato con lego 5.4.0. Aggiungi il resolver di challenge DNS di NexDNS alla configurazione di Traefik: il seguente docker-compose.yml mostra una configurazione tipica:
services:
traefik:
image: traefik:v3 # lego >= v5.4.0
command:
- "--certificatesresolvers.nexdns.acme.dnschallenge=true"
- "--certificatesresolvers.nexdns.acme.dnschallenge.provider=nexdns"
- "--certificatesresolvers.nexdns.acme.email=admin@example.com"
- "--certificatesresolvers.nexdns.acme.storage=/letsencrypt/acme.json"
environment:
NEXDNS_API_TOKEN: "nxd_xxxxxxxxxxxxxxxxxxxx"
volumes:
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "443:443"
volumes:
letsencrypt:
Quindi utilizzare il resolver nelle etichette del servizio:
labels:
- "traefik.http.routers.myapp.tls.certresolver=nexdns"
- "traefik.http.routers.myapp.tls.domains[0].main=example.com"
- "traefik.http.routers.myapp.tls.domains[0].sans=*.example.com"
certbot
certbot è il client ufficiale di Let's Encrypt. Utilizzare il plugin di autenticazione DNS NexDNS per la validazione automatica DNS-01.
Installazione del plugin
Installa il plugin da PyPI oppure usa l’immagine Docker qui sotto, che lo include già.
pip install certbot-dns-nexdns
Creazione del file delle credenziali
Creare ~/.nexdns/certbot-credentials.ini con il token API:
dns_nexdns_token = nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Limitare i permessi del file:
chmod 600 ~/.nexdns/certbot-credentials.ini
Emissione di un certificato
certbot certonly \
--authenticator dns-nexdns \
--dns-nexdns-credentials ~/.nexdns/certbot-credentials.ini \
-d example.com \
-d '*.example.com'
Utilizzo con Docker
docker run --rm \
-v /etc/letsencrypt:/etc/letsencrypt \
-v ~/.nexdns/certbot-credentials.ini:/credentials.ini:ro \
nexdns/certbot certonly \
--non-interactive --agree-tos --email admin@example.com \
--authenticator dns-nexdns \
--dns-nexdns-credentials /credentials.ini \
-d example.com \
-d '*.example.com'
Hook CLI
Se il client ACME supporta hook DNS manuali, è possibile utilizzare la CLI NexDNS come script di hook. Funziona con qualsiasi client che fornisce le opzioni --manual-auth-hook e --manual-cleanup-hook (es. certbot in modalità manuale).
certbot con hook CLI
certbot certonly --manual --preferred-challenges dns \
--manual-auth-hook "nexdns acme hook --action create && sleep 60" \
--manual-cleanup-hook "nexdns acme hook --action delete" \
-d example.com \
-d '*.example.com'
L’hook legge le variabili d’ambiente CERTBOT_DOMAIN e CERTBOT_VALIDATION impostate da certbot e crea o rimuove automaticamente il record TXT _acme-challenge.
La CLI deve essere autenticata prima di utilizzare gli hook. Eseguire
nexdns auth token nxd_xxxo impostare la variabile d’ambienteNEXDNS_TOKEN.