Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente | |||
| si:infra:acme-dns [2025/04/24 21:34] – supprimée - modification externe (Unknown date) 127.0.0.1 | si:infra:acme-dns [2025/04/24 21:34] (Version actuelle) – ↷ Page déplacée de si:acme-dns à si:infra:acme-dns vcalame | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| + | ====== Certificats Letsencrypt via DNS ====== | ||
| + | |||
| + | La création de certificats Letsencrypt se fait traditionnellement par authentification HTTP en utilisant le client [[https:// | ||
| + | Mais il est également possible de créer des certificats Letsencrypt par authentification DNS pour des cas d' | ||
| + | |||
| + | Pour les besoins du service XMPP c'est un certificat Wildcard qui a été créé en utilisant le client [[https:// | ||
| + | |||
| + | Ici j' | ||
| + | |||
| + | ===== Principe de fonctionnement ===== | ||
| + | |||
| + | Le principe du fonctionnement de la validation est similaire que l’on passe par validation DNS-01 ou validation HTTP-01 : | ||
| + | |||
| + | * votre client ACME (certbot, dehydrated, autre) contacte le serveur CA ACME | ||
| + | * le serveur ACME lui retourne une chaine de caractères générée pour l’occasion | ||
| + | * le client ACME rend alors cette chaine de caractères publique : | ||
| + | * soit à une URL http:// | ||
| + | * soit dans un enregistrement DNS de type TXT *_acme-challenge.ledomaine.net* dans le cas d’une validation par DNS-01 | ||
| + | * le client ACME prévient le serveur ACME que ça a été publié | ||
| + | * le serveur ACME est désormais sûr qu’il avait affaire à quelqu’un de légitime valide alors le requête, génère le certificat demandé initialement et le transmet au client ACME | ||
| + | |||
| + | Il faut donc pouvoir publier un enregistrement DNS de type TXT sur nos serveurs Bind (en fait sur un seul ça suffit). | ||
| + | |||
| + | ===== Configurer Bind pour les mises à jour dynamiques ===== | ||
| + | |||
| + | Techniquement il est possible de configurer directement la zone parinux.org pour accepter les changements dynamiques, avec la commande // | ||
| + | |||
| + | > Zones that are under dynamic control via nsupdate or a DHCP server should not be edited by hand. Manual edits could conflict with dynamic updates and cause data to be lost. | ||
| + | |||
| + | Donc le plus simple c'est créer une délégation DNS uniquement pour // | ||
| + | |||
| + | Donc pour cela dans le fichier de zone de // | ||
| + | |||
| + | < | ||
| + | _acme-challenge NS ns1.parinux.org. | ||
| + | </ | ||
| + | |||
| + | Créer une clef secrète qui ne sera partagée qu' | ||
| + | |||
| + | < | ||
| + | cd /tmp | ||
| + | dnssec-keygen -r / | ||
| + | </ | ||
| + | |||
| + | La clef secrète se trouve dans un fichier nommé /// | ||
| + | Ensuite, créer un fichier /// | ||
| + | |||
| + | <file / | ||
| + | key " | ||
| + | algorithm hmac-sha512; | ||
| + | secret " | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Dans le fichier /// | ||
| + | |||
| + | <file / | ||
| + | include "/ | ||
| + | zone " | ||
| + | file "/ | ||
| + | type master; | ||
| + | masterfile-format text; | ||
| + | allow-update { key " | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Il faut maintenant peupler un minimum cette zone dynamique (un SOA et un NS). Créer le fichier /// | ||
| + | |||
| + | <file / | ||
| + | _acme-challenge.parinux.org. IN SOA troll4.parinux.org. admin.parinux.org. ( | ||
| + | | ||
| + | 86400 | ||
| + | 300 | ||
| + | | ||
| + | 86400 | ||
| + | ) | ||
| + | NS | ||
| + | </ | ||
| + | |||
| + | Permettre à Bind de modifier ce fichier : | ||
| + | |||
| + | < | ||
| + | sudo chown bind: / | ||
| + | </ | ||
| + | |||
| + | Puis '' | ||
| + | |||
| + | Maintenant on peut tester la publication dynamique. On peut déjà vérifier qu'on peut manuellement ajouter/ | ||
| + | |||
| + | < | ||
| + | sudo nsupdate -k / | ||
| + | server 127.0.0.1 | ||
| + | update delete _acme-challenge.parinux.org | ||
| + | update add _acme-challenge.parinux.org 8000 IN TXT " | ||
| + | send | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | Puis | ||
| + | |||
| + | < | ||
| + | dig +short _acme-challenge.parinux.org | ||
| + | </ | ||
| + | Voilà. Ça, c'est fait. | ||
| + | |||
| + | ===== Certificat Wildcard avec dehydrated ===== | ||
| + | |||
| + | Sur la machine ayant besoin d'un certificat Wildcard (ici la machine xmpp-1 hébergeant ejabberd) créer le fichier /// | ||
| + | |||
| + | <file etc/ | ||
| + | key " | ||
| + | algorithm hmac-sha512; | ||
| + | secret " | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | |||
| + | Temporairement, | ||
| + | |||
| + | < | ||
| + | |||
| + | On configure dehydrated pour faire de la validation DNS-01 dans le fichier /// | ||
| + | |||
| + | <file / | ||
| + | CHALLENGETYPE=" | ||
| + | HOOK=/ | ||
| + | </ | ||
| + | |||
| + | On créé le script hook /// | ||
| + | |||
| + | < | ||
| + | # | ||
| + | |||
| + | set | ||
| + | set -u | ||
| + | set -o pipefail | ||
| + | |||
| + | NSUPDATE=" | ||
| + | DNSSERVER=" | ||
| + | TTL=300 | ||
| + | |||
| + | case " | ||
| + | " | ||
| + | printf " | ||
| + | ;; | ||
| + | " | ||
| + | printf " | ||
| + | ;; | ||
| + | " | ||
| + | # on concatène le certificat et la clef pour ejabberd. C'est pas obligatoire mais c'est plus simple. | ||
| + | cat / | ||
| + | sudo -u ejabberd ejabberdctl reload_config | ||
| + | |||
| + | ;; | ||
| + | " | ||
| + | # do nothing for now | ||
| + | ;; | ||
| + | " | ||
| + | # do nothing for now | ||
| + | ;; | ||
| + | " | ||
| + | # do nothing for now | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | exit 0 | ||
| + | </ | ||
| + | |||
| + | Il faut rendre ce script exécutable : | ||
| + | |||
| + | < | ||
| + | |||
| + | On indique le ou les domaines qu’on souhaite dans /// | ||
| + | |||
| + | <file / | ||
| + | parinux.org *.parinux.org | ||
| + | </ | ||
| + | |||
| + | La première fois : | ||
| + | |||
| + | <code bash> | ||
| + | |||
| + | Puis on génère ou régénère les certificats : | ||
| + | |||
| + | <code bash> | ||
| + | |||
| + | Si tout s'est bien passé, alors pour peut générer un vrai certificat cette fois en supprimant le fichier /// | ||
| + | |||
| + | < | ||
| + | rm / | ||
| + | dehydrated --register --accept-terms | ||
| + | dehydrated -c --force # --force pour écraser le précédent certificat staging | ||
| + | </ | ||
| + | |||
| + | Il faut maintenant créer une tâche cron pour renouveler le certificat automatiquement. | ||
| + | On créé le fichier /// | ||
| + | |||
| + | <file / | ||
| + | #! /bin/bash | ||
| + | / | ||
| + | </ | ||
| + | |||
| + | Et on le rend exécutable : | ||
| + | |||
| + | < | ||
| + | |||
| + | ===== Créer le certificat avec Certbot ===== | ||
| + | |||
| + | Cette méthode nécessite le plugin [[https:// | ||
| + | |||
| + | Installer les paquets nécessaires : | ||
| + | |||
| + | < | ||
| + | sudo apt install certbot python3-certbot-dns-rfc2136 | ||
| + | </ | ||
| + | |||
| + | Définir les variables qui seront utilisées par la suite : | ||
| + | |||
| + | < | ||
| + | export DOMAIN=mondomaine.net | ||
| + | export DNSSERVER=x.x.x.x | ||
| + | </ | ||
| + | |||
| + | Créer le fichier /// | ||
| + | |||
| + | < | ||
| + | cat << EOF | sudo tee / | ||
| + | dns_rfc2136_server = ${DNSSERVER} | ||
| + | dns_rfc2136_port = 53 | ||
| + | dns_rfc2136_name = rndc-acme-challenge.${DOMAIN}-key | ||
| + | dns_rfc2136_secret = xxxxxxxxxxxxxxxx | ||
| + | dns_rfc2136_algorithm = HMAC-SHA256 | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | Avec des permissions restreintes : | ||
| + | |||
| + | < | ||
| + | |||
| + | Créer le script hook a exécuter après chaque renouvellement de certificat : | ||
| + | |||
| + | < | ||
| + | cat << EOF | sudo tee / | ||
| + | #! /bin/sh | ||
| + | systemctl reload nginx | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | Et le rendre exécutable : | ||
| + | |||
| + | < | ||
| + | |||
| + | Puis lancer certbot certonly : | ||
| + | |||
| + | < | ||
| + | certbot certonly \ | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | -d " | ||
| + | | ||
| + | </ | ||