« Sécuriser ses sites avec letsencrypt et acme-tiny » : différence entre les versions
Ligne 116 : | Ligne 116 : | ||
#! /bin/bash | #! /bin/bash | ||
umask 022 | umask 022 | ||
python /home/acme/acme-tiny/acme_tiny.py --account-key /home/acme/secrets/ | python /home/acme/acme-tiny/acme_tiny.py --account-key /home/acme/secrets/account.key --csr /home/acme/work/networklab.fr/networklab.fr.csr --acme-dir /home/networklab.fr/www/challenges/ > /home/acme/work/networklab.fr/networklab.fr.crt | ||
umask 027 | umask 027 | ||
wget -O /home/acme/work/networklab.fr/intermediate.pem.new https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem | wget -O /home/acme/work/networklab.fr/intermediate.pem.new https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem |
Version du 22 janvier 2017 à 19:49
Les tutos Installation et configuration d'un serveur http apache 2.2 ainsi que Installation et configuration de OpenSSL vous expliquent comment générer des certificats auto-signés et configurer vos vhosts Apache.
Ceci dit les certificats auto-signés présentent un inconvénient majeur : ils génèrent des alertes de sécurité dans les navigateurs.
Ils conviennent donc tout à fait pour sécuriser une interface d'admin, mais dès lors où votre site est ouvert au "public" ils ne sont plus utilisables, les messages d'alertes dans les navigateurs étant plus que dissuasifs.
Depuis peu une nouvelle autorité de certification a vu le jour : https://letsencrypt.org/
Cette autorité vise à fournir gratuitement des certificats de sécurité reconnus dans les navigateurs (grâce dès aujourd'hui à une signature croisée avec une autre autorité)
Il n'y a donc plus d'excuses pour ne pas proposer de HTTPS sur vos sites !
Pourquoi acme-tiny ?
Letsencrypt propose un client officiel qui se charge de presque tout pour vous mais qui a plusieurs défauts, entre autre le fait que vous n'avez pas vraiment la main sur son fonctionnement, qu'il nécessite pas mal de dépendances, doit tourner en root, etc.
Letsencrypt étant un projet OpenSource, il existe de nombreux autres scripts proposant plus ou moins de fonctionnalités, acme-tiny en fait parti : https://github.com/diafygi/acme-tiny
Ce script vous permet de générer le certificat en passant par letsencrypt tout en gardant la main sur votre config Apache, la façon dont vous gérez les certificats, etc.
Pré-configuration (pour la première utilisation)
Avant de générer les certificats, commencez par créer un utilisateur dédié qui se chargera de faire tourner le script. Nous partirons sur un utilisateur nommé acme, avec un home dans /home/acme.
Avec cet utilisateur (su - acme) :
cd /home/acme mkdir work secrets chmod 750 work chmod 700 secrets git clone https://github.com/diafygi/acme-tiny.git chmod +x acme-tiny/acme_tiny.py
Le répertoire secrets servira à héberger les clés (fichiers .key), le work hébergera les différents fichiers des certifiats (crt, csr, pem).
On restreint les droits sur les dossiers et enfin on récupère le script et on le rend exécutable.
Génération des clés
Afin de communiquer avec letsencrypt il vous faut un fichier de clé qui vous authentifie auprès d'eux. Ce fichier est extrêmement important (pensez à bien le sauvegarder) et bien sûr totalement privé.
Si vous n'en avez pas encore vous pouvez le générer de la façon suivante :
openssl genrsa 4096 > /home/acme/secrets/account.key chmod 600 /home/acme/secrets/account.key
Ce fichier de clé est réutilisable sur tous vos domaines.
Ensuite il vous faudra un fichier de clé par domaine que vous voulez sécuriser, même principe :
openssl genrsa 4096 > /home/acme/secrets/networklab.fr.key chmod 600 /home/acme/secrets/networklab.fr.key mkdir /home/acme/work/networklab.fr chmod -R 750 /home/acme/work/ chmod -x /home/acme/work/*/*
Ici pour le domaine networklab.fr, à adapter dans votre cas. On créé également un répertoire dédié au domaine dans work.
Configuration pour la demande du certificat
Afin de demander votre certificat il est nécessaire de générer une demande de certificat. Si vous n'avez qu'une adresse qui sera derrière votre certificat :
openssl req -new -sha256 -key /home/acme/secrets/networklab.fr.key -subj "/CN=networklab.fr" -out /home/acme/work/networklab.fr/networklab.fr.csr
Mais plus généralement vous en aurez au moins deux (une avec et une sans le www) :
openssl req -new -sha256 -key /home/acme/secrets/networklab.fr.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:networklab.fr,DNS:www.networklab.fr")) -out /home/acme/work/networklab.fr/networklab.fr.csr
Vous pouvez vérifier les différentes informations entrés dans le CSR avec la commande suivante :
openssl req -in /home/acme/work/networklab.fr/networklab.fr.csr -noout -text
Avant de générer votre certificat, letsencrypt vient vérifier que votre site vous appartient bien. Pour cela le script va déposer un fichier de "challenge" à l'endroit que vous lui définissez et qui doit être accessible à l'adresse /.well-known/acme-challenge/.
Pour cela il faut donc que votre utilisateur acme puisse écrire dans un dossier de votre site.
Ici nous partons du principe que vous avez un couple d'utilisateur/groupe par site que vous hébergez. Si vous avez une configuration d'Apache avec un seul utilisateur ça n'en sera que plus simple.
En root :
usermod -a -G networklab.fr acme
On ajoute le groupe networklab.fr en groupe secondaire de l'utilisateur acme.
Avec l'utilisateur correspondant à votre site (pour nous networklab.fr) :
cd /home/networklab.fr/www/ mkdir challenges chmod g+w challenges/
Le dossier challenges hébergera le fichier de challenge que letsencrypt va vérifier. On donne le droit d'écriture au groupe pour que l'utilisateur acme puisse y écrire.
Enfin en root dans la configuration Apache de votre site il faudra ajouter :
<Directory "/home/networklab.fr/www/challenges"> AllowOverride None Require all granted Order allow,deny Allow from all DirectoryIndex disabled </Directory> Alias /.well-known/acme-challenge "/home/networklab.fr/www/challenges"
Pensez à bien reload Apache après cette modification.
Attention : letsencrypt viendra chercher le fichier de challenge en HTTP et non en HTTPS. Si vous redirigez automatiquement en HTTPS pensez à mettre une exception sur cette adresse.
De même si vous sécurisez un domaine "d'administration" avec ne protection par .htpasswd pensez également à mettre une exception.
Pour cela ajoutez dans le .htaccess :
SetEnvIf Request_URI "(challenges/)$" allow SetEnvIf Request_URI "(\.well-known/acme-challenge/)$" allow
Génération du certificat
De retour en utilisateur acme, voici le script vous permettant de générer votre certificat :
#! /bin/bash umask 022 python /home/acme/acme-tiny/acme_tiny.py --account-key /home/acme/secrets/account.key --csr /home/acme/work/networklab.fr/networklab.fr.csr --acme-dir /home/networklab.fr/www/challenges/ > /home/acme/work/networklab.fr/networklab.fr.crt umask 027 wget -O /home/acme/work/networklab.fr/intermediate.pem.new https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem openssl x509 -in /home/acme/work/networklab.fr/networklab.fr.crt -text -noout &> /dev/null error=$? if [ ! $error == 0 ] ; then echo "ERROR: ACME output is not a valid x509 certificate" exit 1 fi openssl x509 -in /home/acme/work/networklab.fr/intermediate.pem.new -text -noout &> /dev/null error=$? if [ ! $error == 0 ] ; then echo "ERROR: intermediate.pem is not a valid x509 certificate" exit 1 fi #only done if no error mv /home/acme/work/networklab.fr/intermediate.pem.new /home/acme/work/networklab.fr/intermediate.pem cp /home/acme/work/networklab.fr/networklab.fr.crt /home/acme/work/networklab.fr/networklab.fr.pem
Le changement d'umask permet d'écrire le fichier de challenges avec des droits permettant à Apache de servir le fichier (le fichier étant créé en acme:acme, l'umask 027 ne le permet pas). On lance ensuite le script acme-tiny qui prend en paramètres :
- la clé de votre compte
- le csr (demande de certificat)
- l'emplacement où il doit écrire le fichier de challenge
Et en sortie on récupère le certificat.
On repasse ensuite en umask 027, on récupère le certificat intermédiaire de letsencrypt.
Enfin on combine notre certificat au certificat intermédiaire.
Le script est exactement le même pour un renouvellement de certificat. Vous pouvez donc l'enregistrer (dans notre cas /home/acme/networklab.fr.sh).
Configurez ensuite une tâche cron pour renouveler régulièrement votre certificat.
Actuellement les certificats letsencrypt sont valables 90 jours.
Vous pouvez par exemple partir sur une génération mensuelle :
0 4 21 * * /home/acme/networklab.fr.sh
Tous les 21 du mois à 4H00.
Configuration de la vhost et reload d'Apache
Dernière étape en root, il est nécessaire de configurer votre vhost en HTTPS. Si vous n'aviez que du HTTP vous pouvez rajouter :
<VirtualHost *:443> SSLEngine on SSLCertificateChainFile /home/acme/work/networklab.fr/intermediate.pem SSLCertificateFile /home/acme/work/networklab.fr/networklab.fr.pem SSLCertificateKeyFile /home/acme/secrets/networklab.fr.key SSLProtocol all -SSLv2 -SSLv3 -TLSv1 SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK SSLHonorCipherOrder on Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" Header always set X-Frame-Options DENY ServerName networklab.fr ServerAlias www.networklab.fr Include /etc/apache2/sites-config/networklab.fr.conf </VirtualHost>
On retrouve la configuration du certificat intermédiaire, du certificat de notre domaine et de la clé. Ensuite différentes configurations SSL, à adapter selon la date à laquelle vous lirez ce tuto.
Dernière étape, configurer un reload d'Apache juste après la date prévue pour le renouvellement de vos certificats. Vous pouvez au choix :
- donner le droit à l'utilisateur acme de reload Apache et le rajouter à votre script
- faire un cron en root à une date/heure définie juste après tous vos scripts de renouvellement
Ici nous utiliserons le cron en root :
5 4 21 * * /etc/init.d/apache2 reload
Tous les 21 du mois à 4H05.
Et voilà, vous aurez dorénavant un site en HTTPS avec renouvellement automatique du certificat. Vous pouvez facilement reproduire la chose pour d'autres domaines en refaisant les étapes 3 à 6. Pensez à surveiller que vos certificats se renouvellent bien (idéalement avec du monitoring qui vous alertera en cas de soucis !)