Table des matières

Let’s Encrypt, Certbot et SSL sur Debian

Pour ceux qui ne connaissent pas, Let's Encrypt fourni, gratuitement, des certificats SSL reconnus par les navigateurs (une petite révolution).

Le SSL, qu'est-ce que c'est ? C'est un protocole permettant de sécuriser les échanges sur internet, que ce soit via les protocoles http, ftp ou encore pop (pour les e-mails). Ce protocole ne se nomme plus SSL (Secure Sockets Layer) mais TLS (Transport Layer Security) depuis 1999 (merci wikipedia ^^). Le protocole TLS est le successeur du protocole SSL (ce dernier n'étant plus utilisé) mais le terme SSL est resté.

Pour expliquer rapidement comment ça fonctionne, le SSL utilise une paire de clé (publique et privée) et une autorité de confiance :

  1. Le navigateur se connecte au serveur et demande une connexion SSL
  2. Le serveur envoi un certificat SSL, contenant sa clé publique et sa signature numérique chiffrée, au navigateur
  3. Le navigateur essaye de déchiffrer la signature avec les clés publiques des autorités de confiance intégrés au navigateur (VeriSign, Visa, etc)
  4. S'il y arrive, ça prouve que le certificat a été émis par une autorité de confiance, tout va bien. S'il n'y arrive pas il va déchiffrer la signature avec la clé publique fournie avec le certificat et va alerter l'utilisateur que ce certificat n'a pas été émis par une autorité de confiance et n'est donc pas sûr (on parle de certficat auto-émis).
  5. Une fois le certificat validé, le navigateur va échanger des données chiffrées avec le serveur en utilisant des suites cryptographiques (voir plus de détails ici).

La révolution amenée par Let's Encrypt est qu'il a été reconnu comme une autorité de confiance et que, contrairement aux autres autorités de confiance, il propose des certificats gratuitement.

Toutes les commandes indiquées doivent être lancées avec l'utilisateur root (ou avec sudo)

Activez le support SSL

Tout d'abord on va activer le support ssl ainsi que le mode headers dont aura besoin.

a2enmod ssl headers

Maintenant que ça c'est fait, on va installer le client Certbot qui est utilisé pour générer les certificats SSL Let's Encrypt.

Installation de Certbot

Il va nous falloir installer la version présente dans les dépôts backports de Debian. Pour ajouter ces dépôts, ouvrez le fichier

/etc/apt/sources.list

Ajoutez la ligne suivante au fichier

deb http://ftp.debian.org/debian bullseye-backports main

Mettez à jour les dépôts

aptitude update

On va maintenant pouvoir installer Certbot

aptitude install certbot -t bullseye-backports

Maintenant que nous avons tout ce qu’il nous faut, passons à la création.

Création du certificat SSL sans wildcard

Si vous avez besoin de créer un certificat wildcard (c’est-à-dire valide pour tous les sous-domaines également), passez au chapitre suivant.

Commencez par créer un fichier lets_encrypt.ini (vous pouvez le nommer comme vous voulez) et mettez-y les lignes suivantes dedans :

authenticator = standalone
renew-by-default = True
agree-tos=true
email = postmaster@votredomaine.fr
domains=www.domaine.fr,domaine.fr
rsa-key-size = 4096

Ceci va être le fichier de config du client Certbot que l’on va lancer pour générer nos certificats SSL. Si vous vous demandez à quoi correspondent ces lignes :

Le client Certbot a besoin d'utiliser le port 80. Il vous faudra donc arrêter Apache le temps de l'opération.

On va donc commencer par couper Apache

systemctl stop apache2.service

Il ne reste plus qu’à générer notre certificat. Pensez à modifier l’emplacement du fichier ini si vous ne l’avez pas mis dans le home de l’utilisateur root

certbot certonly --config /root/lets_encrypt.ini

Les certificats vont être créés dans le répertoire

/etc/letsencrypt/live/domaine.fr/

Si tout c'est bien passé, vous devriez avoir le message suivant

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.domaine.fr/fullchain.pem. Your cert
   will expire on 2016-05-15. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:
 
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Si vous allez dans le répertoire /etc/letsencrypt/live/domaine.fr/, vous trouverez 4 fichiers :

Création d’un certificat wildcard

Let’s Encrypt permet également de générer des certificats wildcard. Les wildcard sont des certificats qui sont valables pour l’ensemble des sous-domaines.

Avec la méthode du chapitre précédent, il faut lister tous les sous-domaines lors de la création du certificat SSL. Du coup si on crée un nouveau sous-domaine 3 jours après avoir généré le certificat SSL il faut le regénérer en incluant le nouveau sous-domaine. Avec les certificats wildcard, plus besoin.

Pour vérifier que le nom de domaine pour lequel vous souhaitez générer un certificat vous appartient, Let’s Encrypt propose 2 types de challenges :

Dans le chapitre précédent, on a utilisé le challenge http-01, le plus simple à mettre en place. Mais pour les certificats wildcard, seul le challenge dns-01 est accepté. Je ne traiterai dans ce chapitre que le cas du serveur DNS auto-hébergé, dans mon cas Bind. Certbot possède d’autres plugins permettant de compléter le challenge dns-01 dans le cas où votre dns est géré par ovh, ghandi, etc, mais je ne les ai jamais testés.

Il faut donc impérativement que vous ayez suivi la page IP dynamique et DNS sur la mise en place de dns dynamique. Seuls les chapitres 1 et 2 de cet article, qui traitent de la création de la clé et de la configuration de Bind, sont indispensables. L’autre partie traite de la mise à jour de l’adresse ip, qui n’est pas utile pour les wildcard. Par contre, il ne vous faudra pas utiliser “update-policy”comme indiqué au début du chapitre 2, mais “allow-update” comme indiqué à la fin du chapitre 2 (que vous utilisiez ISPConfig ou non).

Il va également nous falloir installer un plugin pour mettre à jour notre zone DNS

aptitude install python3-certbot-dns-rfc2136

Créez un fichier ini, lets_encrypt.ini par exemple (vous pouvez l’appeler comme vous voulez). Voici ce qu’il doit y avoir dedans :

authenticator = dns-rfc2136
renew-by-default = True
agree-tos=true
email = toto@domaine.fr
domains=domaine.fr,*.domaine.fr
rsa-key-size = 4096
server = https://acme-v02.api.letsencrypt.org/directory
dns-rfc2136-credentials = /root/dns.ini

Expliquons toutes ces lignes :

Et voici ce que doit contenir le fichier dns.ini (pareil, vous pouvez l’appeler comme vous voulez) :

# Target DNS server
dns_rfc2136_server = IP du serveur DNS
# Target DNS port
dns_rfc2136_port = 53
# TSIG key name
dns_rfc2136_name = nom de la clé
# TSIG key secret
dns_rfc2136_secret = contenu de la clé
# TSIG key algorithm
dns_rfc2136_algorithm = HMAC-SHA512

Si votre serveur DNS et votre serveur web (Apache ou Nginx) sont sur le même serveur, il vous faudra mettre 127.0.0.1 pour l’IP. Le nom de clé correspond au nom que vous avez donné à la clé dans le fichier named.conf.keys. Le contenu correspond au code secret de la clé. Si vous avez utilisé un algorithme autre que le HMAC-SHA512, pensez à modifier cette partie.

Comme ce fichier ini contient le code secret de la clé, chose assez sensible, on va modifier les droits de ce fichier

chmod 600 dns.ini

Comme j’ai mis la clé dans le home de l’utilisateur root, lui seul pourra lire ce fichier.

Il ne reste plus qu’à générer notre certificat. Pensez à modifier l’emplacement du fichier ini si vous ne l’avez pas mis dans le home de l’utilisateur root

certbot certonly --config /root/lets_encrypt.ini

Les certificats vont être créés dans le répertoire

/etc/letsencrypt/live/nomdedomaine/

Une chose à savoir, les certificats créés par certbot ne sont accessibles qu'à l'utilisateur root. Les programmes comme Apache2, Postfix, PureFTP, etc sont exécutés par l'utilisateur root et auront donc accès à ces certificats mais il y peut y avoir d'autres programmes exécuté par un autre utilisateur ayant besoin de ces certificats (Collabora Online par exemple). Le meilleur moyen de donner accès à ces programmes aux certficats est d'utiliser https://fr.wikipedia.org/wiki/Access_Control_List. Commencez par installer le paquet acl :

sudo aptitude install acl

Ensuite tapez les commandes suivantes (remplacez utilisateur par votre utilisateur devant accéder aux certificats et nomdedomaine.fr par votre nom de domaine) :

sudo setfacl -m u:utilisateur:rX /etc/letsencrypt/{live,archive}
sudo setfacl -R -m u:utilisateur:rX /etc/letsencrypt/{live,archive}/nomdedomaine.fr

La première commande donne accès à l'utilisateur “utilisateur” aux répertoires /etc/letsencrypt/live/ et /etc/letsencrypt/archive mais pas à leurs sous-dossiers. La seconde commande donne accès à l'utilisateur “utilisateur” aux fichiers se trouvant dans les répertoire /etc/letsencrypt/live/nomdedomaine.fr et /etc/letsencrypt/archive/nomdedomaine.fr.

L'attribution des droits se fait en 2 fois car vous pouvez avoir les certificats de plusieurs noms de domaine dans vos dossiers live et archive mais ne vouloir donner l'accès qu'à un en particulier. Cette modification des droits est perdue après un redémarrage, donc pensez à ajouter un cron pour relancer ces commandes à chaque démarrage.

Configuration d’Apache

Maintenant, il nous faut modifier les fichiers de config d'Apache pour intégrer le certificat SSL qui se trouve dans le répertoire /etc/letsencrypt/live/www.domaine.fr/.

Dans votre fichier de configuration Apache pour votre nom de domaine, ajoutez les lignes suivantes :

<VirtualHost *:443>
    ServerName domaine.fr
    ServerAlias www.domaine.fr
 
    DocumentRoot /var/www/domaine.fr
 
    ErrorLog /var/log/apache2/error.example.com.log
    CustomLog /var/log/apache2/access.example.com.log combined
 
    <Directory /var/www/domaine.fr>
	Options -Indexes +FollowSymLinks +MultiViews
	AllowOverride none
	Require all granted
    </Directory>
 
    SSLEngine on
    SSLCertificateFile    /etc/letsencrypt/live/www.domaine.fr/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/www.domaine.fr/privkey.pem
 
    Header always set Strict-Transport-Security "max-age=15768000"
 
 
</VirtualHost>
 
# intermediate configuration
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder     off
SSLSessionTickets       off
 
SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

Petite explication rapide de ces lignes :

Il faut également que toutes les connexions http (port 80) soient redirigées vers https (port 443) car le HSTS ne fonctionne pas sur tous les navigateurs.

Dans votre fichier de configuration Apache2 il faut rajouter ces lignes après <VirtualHost *:80> :

Redirect / https://domaine.fr/

Redémarrez Apache et c'est tout bon.

Si jamais vous utilisez plusieurs fichiers de configurations, c'est mon cas vu que j'ai pas mal de sous-domaines, il peut être plus simple de rentrer les paramètres SSL dans le fichier de configuration SSL d'Apache2. Ça permet d'appliquer ces options à tous les fichiers de configuration ayant le SSL d'activé.

Ouvrez le fichier de configuration SSL :

sudo nano /etc/apache2/mods-enabled/ssl.conf

Les configurations indiquées dans ce fichier seront appliquées à tous les vhosts. Avant la balise “IfModule”, ajoutez les lignes suivantes :

# intermediate configuration
        SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        SSLHonorCipherOrder     off
        SSLSessionTickets       off
 
        SSLUseStapling On
        SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
 
        # HTTP Strict Transport Security (mod_headers is required) (63072000 seconds)
        Header always set Strict-Transport-Security "max-age=63072000"

On redémarre Apache :

sudo systemctl restart apache2

Il existe un site qui teste et note les connexions SSL. C'est https://www.ssllabs.com/ssltest/index.html. Avec ce qu'on a modifié, vous devriez avoir A+ en note.

Automatisation du renouvellement des certificats Let’s Encrypt

Les certificats Let’s Encrypt étant valable 3 mois, c’est vite chiant de devoir les renouveler à la main tous les 3 mois. On va donc voir comment automatiser tout ça.

Créez un fichier script_letsencrypt.sh (vous pouvez le nommer comme vous voulez).

Si vous utilisez un certificat standard (pas de wildcard), collez les lignes suivantes dedans (pensez à modifier le chemin des différents fichiers)

#!/bin/sh
 
#Vérification de l'expiration du certificat SSL de domaine.fr"
 
if ! openssl x509 -checkend 86400 -in /etc/letsencrypt/live/www.domaine.fr/fullchain.pem; #Si le certificat expire d'ici 24h (86400 secondes)
then
systemctl stop apache2.service
certbot certonly --config /root/lets_encrypt.ini
systemctl start apache2.service
fi

Si vous utilisez un certificat wildcard, collez les lignes suivantes (pensez à modifier le chemin des différents fichiers)

#!/bin/sh
 
#Vérification de l'expiration du certificat SSL de domaine.fr"
 
if ! openssl x509 -checkend 86400 -in /etc/letsencrypt/live/www.domaine.fr/fullchain.pem; #Si le certificat expire d'ici 24h (86400 secondes)
then
certbot certonly --config /root/lets_encrypt.ini
systemctl restart apache2.service
rm /etc/bind/pri.domaine.fr*jnl
systemctl restart bind9
fi

Petite explication sur ce script :

Pensez à rendre ce fichier exécutable

chmod +x /root/script_letsencrypt.sh

Il ne nous reste plus qu’à lancer ce script tous les jours via le crontab de l’utilisateur root.

Editez le crontab du root

crontab -e

Ajoutez la ligne suivante

 00 01 * * * /root/script_letsencrypt.sh >> /var/log/lets-encrypt.log

Il vous faudra là aussi modifier le répertoire d’accès au script.

Le script sera lancé tous les jours à 1h du matin par l’utilisateur root et votre certificat sera renouvelé automatiquement 24h avant son expiration. Les sorties seront stockées dans le fichier /var/log/lets-encrypt.sh, ce qui vous permettra de voir si des erreurs surviennent.