L’objectif est de générer automatiquement ses certificats Let’s Encrypt avec Certbot. Le scénario est le suivant :
-
Certbot initie une demande
-
Let’s Encrypt initie le Request Challenge
-
Certbot met à jour la zone DNS pour répondre au défi
-
Certbot signale à Let’s Encrypt que l’enregistrement est en place
-
Let’s Encrypt vérifie l’enregistrement DNS
-
Let’s Encrypt délivre les nouveaux certificats
Prérequis
-
Avoir installé certbot
-
Avoir un serveur bind fonctionnel, le service est exécuté de préférence par un utilisateur spécifique, ex « bind ».
Un seul nom de clé pour commencer
Tester avec une seule clé nommée « tsig-key ».
Préparer le serveur DNS
Mise en place
Générer les clés et on s’assure que les fichiers sont lisibles par l’utilisateur bind.
tsig-keygen -a hmac-sha512 tsig-key > /etc/bind/tsig.key
tsig-keygen -a hmac-sha512 tsig-key > /etc/bind/rndc.key
chown bind: /etc/bind/tsig.key
chown bind: /etc/bind/rndc.key
Les clés générées sont au format suivant :
key "tsig-key" {
algorithm hmac-sha512;
secret "secret==";
};
Partie à ajouter dans named.conf.local :
include "/etc/bind/tsig.key";
zone "jbsky.fr" IN {
update-policy {
grant tsig-key name _acme-challenge.www.jbsky.fr. TXT;
grant tsig-key name _acme-challenge.mail.jbsky.fr. TXT;
};
type master;
file "/etc/bind/db.jbsky.fr";
};
Vérifier que la mise à jour fonctionne
On test la commande suivante en local afin de vérifier si la mise à jour fonctionne.
KEYFILE=/etc/bind/tsig.key
nsupdate -d -k $KEYFILE <<EOT
server ns1.jbsky.fr
zone jbsky.fr.
update add _acme-challenge.mail.jbsky.fr. 10 txt yellow
send
EOT
dig TXT _acme-challenge.mail.jbsky.fr.
Brancher les scripts de défi
En suivant cette page https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks, il va nous falloir 2 scripts (auth et clean) afin que certbot met à jour par les « hooks » de son script les infos DNS demandées.
Les variables sont passées à chacun des 2 scripts par certbot:
CERTBOT_DOMAIN: The domain being authenticated
CERTBOT_VALIDATION: The validation string
/usr/local/bin/auth.sh
#!/bin/sh
keyfile=/etc/bind/tsig.key
server=127.0.0.1
domain=$(expr match "_acme-challenge.$CERTBOT_DOMAIN" '.*.(.*..*)')
echo "domain: $domain"
echo "trying : update add _acme-challenge.$CERTBOT_DOMAIN 60 txt $CERTBOT_VALIDATION"
nsupdate -d -k $keyfile <<EOT
server $server
zone $domain
update add _acme-challenge.$CERTBOT_DOMAIN 60 txt $CERTBOT_VALIDATION
send
EOT
Mise en place
/usr/local/bin/clean.sh
#!/bin/sh
keyfile=/etc/bind/tsig.key
server=127.0.0.1
domain=$(expr match "_acme-challenge.$CERTBOT_DOMAIN" '.*.(.*..*)')
echo "domain: $domain"
echo "trying : update del _acme-challenge.$CERTBOT_DOMAIN 60 txt"
nsupdate -d -k $keyfile <<EOT
server $server
zone $domain
update del _acme-challenge.$CERTBOT_DOMAIN 60 txt
send
EOT
Vérifier avant de publier
Passer la commande suivant en adaptant la valeur après le drapeau -d. –dry-run permet de faire un essai à sec –manual-public-ip-logging-ok permet de passer la question si vous souhaitez être loggué
certbot certonly --preferred-challenges=dns --manual-auth-hook /usr/local/bin/auth --dry-run --manual-cleanup-hook /usr/local/bin/cleanup -d mail.jbsky.fr -d www.jbsky.fr --manual --manual-public-ip-logging-ok
[...]
IMPORTANT NOTES:
- The dry run was successful.
Si tout se passe bien « The dry run was successful », on peut enlever le l’option –dry-run et vérifier les certificats dans le répertoire /etc/letsencrypt/live.
Planifier le renouvellement
Commande suivante pour ouvrir crontab en mode édition
crontab -e
L essai a sec conditionne l emission reelle : si le premier echoue, le second ne part pas. C est ce qui evite de consommer un quota d emission sur une configuration cassee.
# Renouvellement quotidien des certificats deja emis
47 6 * * * root /usr/bin/certbot renew --quiet
# Deux fois par mois : essai a sec, puis emission reelle seulement s il reussit
0 0 8,22 * * root /usr/bin/certbot certonly --manual --preferred-challenges=dns \
--manual-auth-hook /usr/local/bin/auth \
--manual-cleanup-hook /usr/local/bin/cleanup \
-d www.exemple.fr -d mail.exemple.fr --dry-run > /dev/null 2>&1 \
&& /usr/bin/certbot certonly --manual --preferred-challenges=dns \
--manual-auth-hook /usr/local/bin/auth \
--manual-cleanup-hook /usr/local/bin/cleanup \
-d www.exemple.fr -d mail.exemple.fr > /dev/null 2>&1
Deux erreurs qui coûtent du temps
Mauvais format de clé
Attention, générer la clé avec la commande suivante ramène l’erreur « TSIG error with server: tsig indicates error » ou encore dans le syslog « tsig verify failure (BADKEY) »
dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST _acme-challenge.mail.jbsky.fr
En effet, en testant avec la commande suivante, le serveur ne traite pas avec ce type de clé. Il semblerait que cela soit « deprecated ».
KEYFILE=/dnskey/K_acme-challenge.mail.jbsky.fr.+157+20343.
nsupdate -d -k $KEYFILE <<EOT
server ns1.jbsky.fr
zone jbsky.fr.
update add _acme-challenge.mail.jbsky.fr. 10 txt yellow
send
EOT
Pas de droit d’écriture
Côté serveur Bind, s’assurer que l’utilisateur bind peut écrire dans son répertoire /etc/bind/
chown bind: /etc/bind