[howto] Mise en place de Dehydrated
Le but de ce howto et de:
Installer et configurer Dehydrated
Utiliser les certificats auto-générés par Dehydrated dans Apache
Disclamer: Cette procédure est faite en avril 2018. Il est nécessaire de vérifier les bonnes pratiques avant toute chose ! Les normes concernant SSL changent constamment, à cause de nouveaux périphériques, de mises à jour logicielles, ou encore de failles comblées.
Disclamer 2: Ce howto n'est pas ideal car les validation par Dehydrated seront effectuées en root, ce qui pose un problème de sécurité. (Il est relativement facile de le faire fonctionner avec l'utilisateur de Apache2 mais je ne voulais pas alourdir la procédure...)
Installation du client
Sur des distributions basées sur Debian (>9):
$ sudo apt-get install dehydrated
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les NOUVEAUX paquets suivants seront installés :
dehydrated
0 mis à jour, 1 nouvellement installés, 0 à enlever et 0 non mis à jour.
Il est nécessaire de prendre 71,9 ko dans les archives.
Après cette opération, 119 ko d'espace disque supplémentaires seront utilisés.
Réception de : 1 http://ftp.fr.debian.org/debian/ jessie-backports/main dehydrated all 0.3.1-3+deb9u2~bpo8+1 [71,9 kB]
71,9 ko réceptionnés en 0s (75,3 ko/s)
Sélection du paquet dehydrated précédemment désélectionné.
(Lecture de la base de données... 56415 fichiers et répertoires déjà installés.)
Préparation du dépaquetage de .../dehydrated_0.3.1-3+deb9u2~bpo8+1_all.deb ...
Dépaquetage de dehydrated (0.3.1-3+deb9u2~bpo8+1) ...
Traitement des actions différées (« triggers ») pour man-db (2.7.0.2-5) ...
Paramétrage de dehydrated (0.3.1-3+deb9u2~bpo8+1) ...
Pour les autres distributions, une recherche internet devrait répondre rapidement à la question ;)
De même pour Debian Jessie (dans les backports)
Configuration de Dehydrated
Le fichier de configuration fourni avec le paquet contient des informations essentielles. Pour la suite de l'article, le chemin contenant les certificats BASEDIR sera déplacé pour être sur un disque chiffré.
$ cat /etc/dehydrated/config
CONFIG_D=/etc/dehydrated/conf.d
BASEDIR=/media/datas/dehydrated
WELLKNOWN="${BASEDIR}/acme-challenges"
DOMAINS_TXT="${BASEDIR}/domains.txt"
- CONFIG_D = peut contenir des fichiers de configuration supplémentaires. Il ne sera pas utilisé ici. Il est nécessaire de laisser l'entrée.
- BASEDIR = Dossier de 'travail' de Dehydrated. Contient, entre autre, les certificats et clef privées
- WELLKNOWN = le chemin relatif, sur chaque domaine, sur lequel Let's Encrypt attends la réponse du serveur oueb
- DOMAINS_TXT = liste des certificats à générer
Le fichier domains.txt
Le fichier domains.txt contient la liste des certificats a générer, un certificat par ligne. Il est possible de demander des alternatives names à Let's Encrypt. Dans tous les cas, tous les domaines doivent être accessible pour réaliser l'échange avec LE.
Exemple:
$ cat /media/datas/dehydrated/domains.txt
releases.nailyk.fr gerrit.nailyk.fr
Un seul certificat sera créé, concernant les deux domaines releases.nailyk.fr et gerrit.nailyk.fr:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:0c:97:02:1d:5f:84:57:4b:58:60:ba:ac:c6:40:10:96:01
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
Validity
Not Before: Feb 16 02:40:21 2018 GMT
Not After : May 17 02:40:21 2018 GMT
Subject: CN=releases.nailyk.fr
Subject Public Key Info:
[...]
X509v3 Subject Alternative Name:
DNS:gerrit.nailyk.fr, DNS:releases.nailyk.fr
Avec les comptes 'perso' il n'est pas possible de demander plus de cinq certificats (5 lignes dans domains.txt).
En théorie, pour que le serveur réponde à LE, la connexion doit se faire en plain et non en ssl. Il est donc important de vérifier que le WELLKNOWN de chaque domaine pourra répondre en http et non en https:
$ ls -al /etc/apache2/conf-enabled/dehydrated.conf
Le lien symbolique vers la configuration acme existe bien, le fichier est présent, et crée bien l'alias:
[...]
<IfModule alias_module>
# Serve ACME challenge responses
Alias /.well-known/acme-challenge/ /media/datas/dehydrated/acme-challenges/
</IfModule>
Si ce n'est pas le cas, installer le paquet dehydrated-apache2 si il ne l'a pas été automatiquement.
Mise en place de la CA de test
A partir d'ici, Dehydrated devrait être en mesure de répondre à LE. Pour la mise en place ainsi que les tests, il est fortement recommandé d'utiliser une chaîne de validation de tests. Pour se faire, il suffit d'ajouter cette ligne dans le fichier /etc/dehydrated/config:
CA="https://acme-staging.api.letsencrypt.org/directory"
Demander les certificats
Il est maintenant possible de demander a Dehydrated de négocier les échanges avec LE et de nous créer les certificats:
# dehydrated -c
l'argument -c indique à Dehydrated de traiter tous les domaines de domains.txt
# INFO: Using main config file /etc/dehydrated/config
Processing releases.nailyk.fr with alternative names: gerrit.nailyk.fr
+ Checking domain name(s) of existing cert... unchanged.
+ Checking expire date of existing cert...
+ Valid till May 17 02:40:21 2018 GMT (Less than 30 days). Renewing!
+ Signing domains...
+ Generating private key...
+ Generating signing request...
+ Requesting authorization for releases.nailyk.fr...
+ Requesting authorization for gerrit.nailyk.fr...
+ 2 pending challenge(s)
+ Deploying challenge tokens...
+ Responding to challenge for releases.nailyk.fr authorization...
+ Challenge is valid!
+ Responding to challenge for gerrit.nailyk.fr authorization...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Done!
+ Creating fullchain.pem...
+ Walking chain...
+ Done!
Noter le message Less than 30 days
Le nom du dossier correspond à celui qui est (en premier) dans domains.txt (le CN du certificat en fait).
A cette étape, plusieurs fichiers sont générés:
# ls -al /media/datas/dehydrated/certs/releases.nailyk.fr/*.pem
-rw------- 1 root root 2492 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/cert-1524153089.pem
lrwxrwxrwx 1 root root 19 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/cert.pem -> cert-1524153089.pem
-rw------- 1 root root 1720 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/chain-1524153089.pem
lrwxrwxrwx 1 root root 20 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/chain.pem -> chain-1524153089.pem
-rw------- 1 root root 4212 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/fullchain-1524153089.pem
lrwxrwxrwx 1 root root 24 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/fullchain.pem -> fullchain-1524153089.pem
-rw------- 1 root root 3243 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/privkey-1524153089.pem
lrwxrwxrwx 1 root root 22 Apr 19 17:51 /media/datas/dehydrated/certs/releases.nailyk.fr/privkey.pem -> privkey-1524153089.pem
On note que les liens symboliques pointent vers les certificats et clefs, les plus récemment générés.
Les fichiers
cert.pem --> Contient le certificat généré par LE (valable maximum 30 jours!)
chain.pem --> Contient le certificat de LE
fullchain.pem --> Contient le certificat généré par LE, ainsi que celui de leur CA
privkey.pem --> Contient la clef privée
Le certificat généré par LE:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
fa:d1:a2:c9:c3:67:29:a4:df:d2:a6:89:14:d0:53:6d:7d:a4
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Fake LE Intermediate X1
Validity
Not Before: Apr 19 14:51:37 2018 GMT
Not After : Jul 18 14:51:37 2018 GMT
Subject: CN=releases.nailyk.fr
[...]
X509v3 Subject Alternative Name:
DNS:gerrit.nailyk.fr, DNS:releases.nailyk.fr
Pour le moment la CA est Fake LE Intermediate X1 étant donné la configuration de dehydrated.
On constate que le champ alternative name est bien rempli, avec tous les noms alternatifs de la ligne du fichier domains.txt.
Mise en place des certificats dans Apache
Le but de cet article n'est pas de détailler la configuration d'un VHost Apache, juste d'ajouter le SSL...
Pour ce faire, rajouter les entrées suivantes dans le vhost:
<VirtualHost *:443>
ServerName gerrit.nailyk.fr
SSLEngine on
SSLCertificateFile /media/datas/dehydrated/certs/releases.nailyk.fr/cert.pem
SSLCertificateKeyFile /media/datas/dehydrated/certs/releases.nailyk.fr/privkey.pem
SSLCertificateChainFile /media/datas/dehydrated/certs/releases.nailyk.fr/chain.pem
[...]
</VirtualHost *:443>
Le vhost va donc écouter sur le port 443. Il est maintenant possible de vérifier qu'il n'y a pas de fautes de frappes dans le fichier
# apache2ctl configtest
Syntax OK
Attention: la commande ne vérifie pas que les fichiers de certificats existent et sont cohérents, mais uniquement la syntaxe de la configuration!
Lorsque la configuration est ok, demander de prendre en compte les modifications au démon:
# apache2ctl graceful
La commande ne retourne rien quand tout va bien. Le retour se fait dans les logs apache
# tail /var/log/apache2/error.log
[Tue Apr 24 11:06:34.056138 2018] [mpm_prefork:notice] [pid 21061] AH00171: Graceful restart requested, doing restart
[Tue Apr 24 11:06:34.276288 2018] [mpm_prefork:notice] [pid 21061] AH00163: Apache/2.4.10 (Debian) OpenSSL/1.0.1t configured -- resuming normal operations
[Tue Apr 24 11:06:34.276315 2018] [core:notice] [pid 21061] AH00094: Command line: '/usr/sbin/apache2'
En cas de problèmes:
Quelques petits rappels évidents, comme lire les logs.
Erreur de clef privée/clefs publique ne correspondant pas:
nailyk@hostname :) % sudo apache2ctl configtest
Syntax OK
nailyk@hostname :) % sudo apache2ctl graceful
httpd not running, trying to start
Action 'graceful' failed.
The Apache error log may have more information.
nailyk@hostname 1 :( % sudo tail /var/log/apache2/error.log
[snip]
AH00016: Configuration Failed
L'erreur détaillée est dans le fichier de log dédié au vhost.
Un ls -alrt peut donner des indices sur quel vhost à crashé.
-rw-r----- 1 root adm 4386 Apr 24 11:21 gerrit.nailyk.fr_access.log
-rw-r----- 1 root adm 161 Apr 24 11:23 releases.nailyk.fr_error.log
-rw-r----- 1 root adm 12352 Apr 24 11:24 other_vhosts_access.log
-rw-r----- 1 root adm 271881 Apr 24 11:24 releases.nailyk.fr_access.log
-rw-r----- 1 root adm 1080 Apr 24 11:27 gerrit.nailyk.fr_error.log
-rw-r----- 1 root adm 1082 Apr 24 11:27 error.log
# tail /var/log/apache2/gerrit.nailyk.fr_error.log
[Tue Apr 24 11:27:22.447167 2018] [ssl:emerg] [pid 15383] AH02565: Certificate and private key gerrit.nailyk.fr:443:0 from /media/datas/dehydrated/certs/releases.nailyk.fr/cert-1488276399.pem and /media/datas/dehydrated/certs/releases.nailyk.fr/privkey.pem do not match
Fichier inexistant:
nailyk@hostname :) % sudo apache2ctl configtest
AH00526: Syntax error on line 10 of /etc/apache2/sites-enabled/gerrit.nailyk.fr.conf:
SSLCertificateFile: file '/media/datas/dehydrated/certs/releases.nailyk.fr/certdekikinatorleroidescastors.pem' does not exist or is empty
Action 'configtest' failed.
The Apache error log may have more information.
Pour le reste..... Pas de panique, quelqu'un s'est sûrement déjà posé la même question, une petite recherche sur les zinternets devrait donner une réponse :)
Mise en place de la tache planifiée
Les certificats fournis par Lets Encrypt, ont une durée maximum de 90 jours (30 pour la CA de test), ce qui ne fait pas exactement trois mois.
Les scripts de Dehydrated ne renouvelleront pas les certificats, si ils sont encore valables plus de 30 jours. Il faut donc bien réfléchir aux dates d'execution de la tâche plannifée, pour ne pas se retrouver avec un certificat expiré.
Il est bien entendu possible de faire plusieurs exécutions.
Mon choix s'est posé sur le 16 de chaque mois.
De cette façon, peut importe le nombre de jours du mois, le certificat sera toujours renouvelé pour le mois suivant, si il doit expirer (lorsqu'un mois fera 31 jours, le 15 du mois suivant est à plus de 30 jours du 16 du mois en cours, de même que pour les mois de 30 jours, car sur une période de trois mois, il y a forcement eu un mois de 31 jours. Le certificat sera donc renouvelé. Comment ça c'est pas clair? )
40 4 16 * * /usr/bin/dehydrated -c && /usr/sbin/apache2ctl configtest && /usr/sbin/apache2ctl graceful
Disclamer: C'est ici que la configuration n'est pas idéale, car le cron va tourner en root, lançant ainsi les scripts de Dehydrated avec tous les privilèges, ce qui présente un risque de sécurité.
Mise en production
Enlever la CA spécifiée dans la configuration de Dehydrated. (voir plus haut) Demander le renouvellement avec dehydrated -c -x (l'option -x permet de forcer la demande de renouvellement, car, ici, elle est récente, mais n'a pas été générée avec la bonne CA.
# INFO: Using main config file /etc/dehydrated/config
Processing releases.nailyk.fr with alternative names: gerrit.nailyk.fr
+ Checking domain name(s) of existing cert... unchanged.
+ Checking expire date of existing cert...
+ Valid till Jul 18 14:51:37 2018 GMT (Longer than 30 days). Ignoring because renew was forced!
+ Signing domains...
+ Generating private key...
+ Generating signing request...
+ Requesting new certificate order from CA...
+ Received 2 authorizations URLs from the CA
+ Handling authorization for gerrit.nailyk.fr
+ Handling authorization for releases.nailyk.fr
+ 2 pending challenge(s)
+ Deploying challenge tokens...
+ Responding to challenge for gerrit.nailyk.fr authorization...
+ Challenge is valid!
+ Responding to challenge for releases.nailyk.fr authorization...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Done!
+ Creating fullchain.pem...
+ Using cached chain!
+ Done!
Il n'y a plus qu'a recharger Apache pour prendre en compte les nouveaux certificats:
# apache2ctl graceful
Test du certificat:
A faire depuis une autre machine, de préférence:
$ openssl s_client -showcerts -servername gerrit.nailyk.fr -connect gerrit.nailyk.fr:443 </dev/null
Server certificate
subject=/CN=releases.nailyk.fr
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3