Ci-dessous, les différences entre deux révisions de la page.
Both sides previous revision Révision précédente Prochaine révision | Révision précédente | ||
si:acme-dns [2018/12/25 17:21] pitchum |
si:acme-dns [2022/02/13 19:32] (Version actuelle) pitchum |
||
---|---|---|---|
Ligne 24: | Ligne 24: | ||
===== Configurer Bind pour les mises à jour dynamiques ===== | ===== 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 //nsupdate// par exemple. Mais quand on active cette option alors Bind réorganise complètement le fichier zone à sa façon illisible. Et ça c'est pénible pour les adminsys. Et puis en plus ce fichier zone ne doit plus être éditer manuellement comme l'indique la page //man nsupdate// : | + | Techniquement il est possible de configurer directement la zone parinux.org pour accepter les changements dynamiques, avec la commande //nsupdate// par exemple. Mais quand on active cette option alors Bind réorganise complètement le fichier zone à sa façon illisible. Et ça c'est pénible pour les adminsys. Et puis en plus ce fichier zone ne doit plus être édité manuellement comme l'indique la page //man nsupdate// : |
> 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. | > 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. | ||
Ligne 55: | Ligne 55: | ||
Dans le fichier ///etc/bind/named.conf.local// déclarer cette nouvelle zone et inclure le fichier de la clef secrète : | Dans le fichier ///etc/bind/named.conf.local// déclarer cette nouvelle zone et inclure le fichier de la clef secrète : | ||
- | <code> | + | <file /etc/bind/named.conf.local.sample> |
include "/etc/bind/rndc-acme.key"; | include "/etc/bind/rndc-acme.key"; | ||
zone "_acme-challenge.parinux.org" { | zone "_acme-challenge.parinux.org" { | ||
Ligne 63: | Ligne 63: | ||
allow-update { key "rndc-acme"; }; | allow-update { key "rndc-acme"; }; | ||
}; | }; | ||
- | </code> | + | </file> |
Il faut maintenant peupler un minimum cette zone dynamique (un SOA et un NS). Créer le fichier ///var/cache/bind/_acme-challenge.parinux.org.zone// comme ceci : | Il faut maintenant peupler un minimum cette zone dynamique (un SOA et un NS). Créer le fichier ///var/cache/bind/_acme-challenge.parinux.org.zone// comme ceci : | ||
- | <code> | + | <file /var/cache/bind/_acme-challenge.parinux.org.zone> |
_acme-challenge.parinux.org. IN SOA troll4.parinux.org. admin.parinux.org. ( | _acme-challenge.parinux.org. IN SOA troll4.parinux.org. admin.parinux.org. ( | ||
2018112200 | 2018112200 | ||
Ligne 76: | Ligne 76: | ||
) | ) | ||
NS troll4.parinux.org. | NS troll4.parinux.org. | ||
- | </code> | + | </file> |
Permettre à Bind de modifier ce fichier : | Permettre à Bind de modifier ce fichier : | ||
Ligne 86: | Ligne 86: | ||
Puis ''%%sudo systemctl restart bind9%%''. | Puis ''%%sudo systemctl restart bind9%%''. | ||
- | Maintenant on peut tester la publication dynamique. On peut déjà vérifier qu'on peut manuellement ajouter/modifier/supprimer l'enregistrement DNS. | + | Maintenant on peut tester la publication dynamique. On peut déjà vérifier qu'on peut manuellement ajouter/modifier/supprimer l'enregistrement DNS depuis troll4 elle-même (par la suite il faudra pouvoir faire le même chose depuis un autre machine ayant la clef secrète). |
<code> | <code> | ||
sudo nsupdate -k /etc/bind/rndc.key <<EOF | sudo nsupdate -k /etc/bind/rndc.key <<EOF | ||
server 127.0.0.1 | server 127.0.0.1 | ||
- | delete _acme-challenge.parinux.org | + | update delete _acme-challenge.parinux.org |
update add _acme-challenge.parinux.org 8000 IN TXT "coucou tout va bieng ?" | update add _acme-challenge.parinux.org 8000 IN TXT "coucou tout va bieng ?" | ||
send | send | ||
EOF | EOF | ||
</code> | </code> | ||
+ | |||
Puis | Puis | ||
Ligne 103: | Ligne 104: | ||
Voilà. Ça, c'est fait. | 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 ///etc/parinux/rndc-acme.key// contenant la même clef secrète que sur le serveur Bind : | ||
+ | |||
+ | <file etc/parinux/rndc-acme.key> | ||
+ | key "rndc-acme" { | ||
+ | algorithm hmac-sha512; | ||
+ | secret "cZh3zV8Uf7aIOxjv8ZA8iA=="; | ||
+ | }; | ||
+ | </file> | ||
+ | |||
+ | <code>sudo apt install dehydrated dnsutils ntp</code> | ||
+ | |||
+ | Temporairement, le temps de tester la configuration on va utiliser le serveur ACME de staging. | ||
+ | |||
+ | <code>echo 'CA="https://acme-staging-v02.api.letsencrypt.org/directory"' | sudo tee /etc/dehydrated/conf.d/staging.sh</code> | ||
+ | |||
+ | On configure dehydrated pour faire de la validation DNS-01 dans le fichier ///etc/dehydrated/conf.d/auth-dns.sh// : | ||
+ | |||
+ | <file /etc/dehydrated/conf.d/auth-dns.sh> | ||
+ | CHALLENGETYPE="dns-01" | ||
+ | HOOK=/etc/dehydrated/hook-custom.sh | ||
+ | </file> | ||
+ | |||
+ | On créé le script hook ///etc/dehydrated/hook-custom.sh// : | ||
+ | |||
+ | <file> | ||
+ | #!/usr/bin/env bash | ||
+ | |||
+ | set | ||
+ | set -u | ||
+ | set -o pipefail | ||
+ | |||
+ | NSUPDATE="nsupdate -k /etc/parinux/rndc-acme.key" | ||
+ | DNSSERVER="192.168.2.55" # l'IP de troll4, le serveur DNS master | ||
+ | TTL=300 | ||
+ | |||
+ | case "$1" in | ||
+ | "deploy_challenge") | ||
+ | printf "server %s\nupdate add _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${TTL}" "${4}" | $NSUPDATE | ||
+ | ;; | ||
+ | "clean_challenge") | ||
+ | printf "server %s\nupdate delete _acme-challenge.%s. %d in TXT \"%s\"\nsend\n" "${DNSSERVER}" "${2}" "${TTL}" "${4}" | $NSUPDATE | ||
+ | ;; | ||
+ | "deploy_cert") | ||
+ | # on concatène le certificat et la clef pour ejabberd. C'est pas obligatoire mais c'est plus simple. | ||
+ | cat /var/lib/dehydrated/certs/parinux.org/fullchain.pem /var/lib/dehydrated/certs/parinux.org/privkey.pem > /etc/ejabberd/parinux.org.ejabberd.pem | ||
+ | sudo -u ejabberd ejabberdctl reload_config | ||
+ | |||
+ | ;; | ||
+ | "unchanged_cert") | ||
+ | # do nothing for now | ||
+ | ;; | ||
+ | "startup_hook") | ||
+ | # do nothing for now | ||
+ | ;; | ||
+ | "exit_hook") | ||
+ | # do nothing for now | ||
+ | ;; | ||
+ | esac | ||
+ | |||
+ | exit 0 | ||
+ | </file> | ||
+ | |||
+ | Il faut rendre ce script exécutable : | ||
+ | |||
+ | <code>sudo chmod +x /etc/dehydrated/hook-custom.sh</code> | ||
+ | |||
+ | On indique le ou les domaines qu’on souhaite dans ///etc/dehydrated/domains.txt// : | ||
+ | |||
+ | <file /etc/dehydrated/domains.txt> | ||
+ | parinux.org *.parinux.org | ||
+ | </file> | ||
+ | |||
+ | La première fois : | ||
+ | |||
+ | <code bash>dehydrated --register --accept-terms</code> | ||
+ | |||
+ | Puis on génère ou régénère les certificats : | ||
+ | |||
+ | <code bash>dehydrated -c</code> | ||
+ | |||
+ | Si tout s'est bien passé, alors pour peut générer un vrai certificat cette fois en supprimant le fichier ///etc/dehydrated/conf.d/staging.sh// : | ||
+ | |||
+ | <code> | ||
+ | rm /etc/dehydrated/conf.d/staging.sh | ||
+ | dehydrated --register --accept-terms | ||
+ | dehydrated -c --force # --force pour écraser le précédent certificat staging | ||
+ | </code> | ||
+ | |||
+ | Il faut maintenant créer une tâche cron pour renouveler le certificat automatiquement. | ||
+ | On créé le fichier ///etc/cron.weekly/acme-renew// suivant : | ||
+ | |||
+ | <file /etc/cron.weekly/acme-renew> | ||
+ | #! /bin/bash | ||
+ | /usr/bin/dehydrated -c | ||
+ | </file> | ||
+ | |||
+ | Et on le rend exécutable : | ||
+ | |||
+ | <code>chmod +x /etc/cron.weekly/acme-renew</code> | ||
+ | |||
+ | ===== Créer le certificat avec Certbot ===== | ||
+ | |||
+ | Cette méthode nécessite le plugin [[https://certbot-dns-rfc2136.readthedocs.io/en/stable/|certbot-dns-rfc2136]]. | ||
+ | |||
+ | Installer les paquets nécessaires : | ||
+ | |||
+ | <code> | ||
+ | sudo apt install certbot python3-certbot-dns-rfc2136 | ||
+ | </code> | ||
+ | |||
+ | Définir les variables qui seront utilisées par la suite : | ||
+ | |||
+ | <code> | ||
+ | export DOMAIN=mondomaine.net | ||
+ | export DNSSERVER=x.x.x.x | ||
+ | </code> | ||
+ | |||
+ | Créer le fichier ///etc/letsencrypt/nsupdate-credentials-${DOMAIN}.ini// : | ||
+ | |||
+ | <code> | ||
+ | cat << EOF | sudo tee /etc/letsencrypt/nsupdate-credentials-${DOMAIN}.ini | ||
+ | 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 | ||
+ | </code> | ||
+ | |||
+ | Avec des permissions restreintes : | ||
+ | |||
+ | <code>sudo chmod 600 /etc/letsencrypt/nsupdate-credentials-${DOMAIN}.ini</code> | ||
+ | |||
+ | Créer le script hook a exécuter après chaque renouvellement de certificat : | ||
+ | |||
+ | <code> | ||
+ | cat << EOF | sudo tee /etc/letsencrypt/renewal-hooks/post/reload-services.sh | ||
+ | #! /bin/sh | ||
+ | systemctl reload nginx | ||
+ | EOF | ||
+ | </code> | ||
+ | |||
+ | Et le rendre exécutable : | ||
+ | |||
+ | <code>sudo chmod u+x /etc/letsencrypt/renewal-hooks/post/reload-services.sh</code> | ||
+ | |||
+ | Puis lancer certbot certonly : | ||
+ | |||
+ | <code> | ||
+ | certbot certonly \ | ||
+ | --expand --non-interactive --agree-tos --email root@${DOMAIN} \ | ||
+ | --dns-rfc2136 \ | ||
+ | --dns-rfc2136-propagation-seconds 3 \ | ||
+ | --dns-rfc2136-credentials /etc/letsencrypt/nsupdate-credentials-${DOMAIN}.ini \ | ||
+ | -d "*.${DOMAIN}" -d ${DOMAIN} \ | ||
+ | --post-hook /etc/letsencrypt/renewal-hooks/post/reload-services.sh | ||
+ | </code> | ||