La sécurisation des échanges de données est aujourd’hui quelque chose de primordial. Une majorité de sites proposent maintenant une connexion HTTPS. Pour pousser à une plus grande sécurité sur le web, Google prend cela en compte dans son référencement des sites ; ils vont même jusqu’à interdire l’utilisation du HTTP non sécurisé sur les noms de domaines gérés par Google (.dev, .app).
Let’s Encrypt est l’une des initiatives qui a largement aidé à aller en ce sens. C’est un fournisseur de certificats SSL gratuits.
Il y a 8 ans, j’avais écrit un article sur la génération de certificats SSL, en utilisant à l’époque l’autorité de certification StartSSL. C’était à l’époque un bon service, qui reposait sur un système intelligent (la vérification d’identité était payante car manuelle, l’émission de certificats était ensuite gratuite car automatisée). Malheureusement, l’entreprise a été rachetée « en secret » par une autre société, qui a utilisé son infrastructure pour émettre de faux certificats, afin de berner des utilisateurs de services tels que GitHub (cf. article Wikipedia).
A priori, Let’s Encrypt devrait être à l’abri de ce genre de malversations, ses créateurs étant l’Eletronic Frontier Foundation, la fondation Mozilla et l’université du Michigan.
Pour créer un certificat avec Let’s Encrypt, il faut prouver que l’on possède le nom de domaine en question. Il existe plusieurs méthodes pour cela ; la première qui a été proposée reposait sur le fait que le serveur qui fait la demande de certificat est capable de répondre aux requêtes faites pour ce domaine. Mais cette technique a des limites : cela ne fonctionne pas bien si vous avez plusieurs serveurs frontaux (vous pouvez demander le certificat sur un serveur, et c’est un autre qui reçoit la requête de validation) ; et ça ne peut pas fonctionner du tout si vous demandez un certificat wildcard.
Heureusement, une autre technique existe, qui se base sur une information à enregistrer dans le DNS du domaine. Toutefois, il faut savoir que les certificats Let’s Encrypt ont une durée de vie de seulement 3 mois. Cela veut dire qu’il faut mettre à jour les DNS tous les 3 mois pour renouveler les certificats, ce qui est assez pénible. Mais nous avons la chance qu’un plugin pour Let’s Encrypt se charge de mettre automatiquement à jour les DNS pour les domaines gérés chez OVH (qui est l’un des sponsors de Let’s Encrypt).
Installation
Les commandes d’installation sont données ici pour une distribution Ubuntu récente (j’ai testé sur une 18.04, une 19.04 et une 19.10).
Installons Let’s Encrypt et son plugin :
sudo apt install letsencrypt python3-certbot-dns-ovh
(Le programme client a changé de nom, passant de « letsencrypt » à « certbot ». Je pense que bientôt, le paquet « letsencrypt » n’existera plus, et il faudra installer le paquet « certbot ».)
Configuration OVH
Vous devez créer une clé d’API chez OVH, pour que le client Let’s Encrypt soit capable de modifier vos DNS automatiquement.
Pour cela, il faut aller sur la page de création de clé d’API.
Pour la durée de validité, choisissez « Unlimited ».
Il faut ajouter 4 droits :
GET /domain/zone/*
PUT /domain/zone/*
POST /domain/zone/*
DELETE /domain/zone/*
Vous pouvez éventuellement restreindre les adresses IP qui auront le droit d’utiliser la clé.
Vous obtiendrez 3 clés : la clé d’application, la clé secrète, et une « consumer key ».
On va les stocker dans un fichier « /root/.ovh-credentials
» :
# OVH credentials for Let's Encrypt plugin
dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = XXXXXXX
dns_ovh_application_secret = YYYYYYY
dns_ovh_consumer_key = ZZZZZZZ
(En remplaçant les chaînes XXXXXXX, YYYYYYY et ZZZZZZZ par les clés correspondantes.)
Utilisation de Let’s Encrypt
Pour commencer, on va s’enregistrer, en utilisant la commande suivante :
certbot register --email [email protected]
(En remplaçant évidemment l’adresse email par la votre.)
Imaginons que l’on souhaite créer un certificat pour le domaine toto.com
. On aura au minimum besoin de gérer les noms toto.com
et www.toto.com
. Pour le plaisir, on va y ajouter data.toto.com
.
Dans le shell, on exécutera la commande suivante en tant que root :
letsencrypt certonly --email [email protected] \
--dns-ovh --dns-ovh-credentials /root/.ovh-credentials \
--dns-ovh-propagation-seconds 60 --preferred-challenges dns \
--register -d toto.com -d www.toto.com -d data.toto.com
Vous pouvez tester la commande en y ajoutant l’option --dry-run
. Si vous ne rencontrez pas d’erreur, vous pouvez ensuite la lancer normalement.
Si tout se passe bien, vous trouverez un répertoire /etc/letsencrypt/live/toto.com
contenant les certificats générés (en fait des liens symboliques mais ce n’est pas important).
Configuration Apache
Pour prendre désormais en compte les certificats générés, il faut adapter la configuration de vos virtual hosts Apache.
Voici un exemple de configuration, que vous pouvez adapter à vos besoins :
# en HTTP, les noms "toto.com" et "www.toto.com" font une redirection 301 # (redirection définitive) vers "www.toto.com" en HTTPS <VirtualHost *:80> ServerName toto.com ServerAlias www.toto.com Redirect 301 / https://www.toto.com/ </VirtualHost> # en HTTPS, le nom "toto.com" fait une redirection 301 (définitive) # vers "www.toto.com" en HTTPS <VirtualHost *:443> ServerName toto.com Redirect 301 / https://www.toto.com/ # configuration SSL SSLEngine on SSLOptions +StrictRequire SSLProtocol all SSLCipherSuite HIGH # certificats SSLCertificateFile /etc/letsencrypt/live/toto.com/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/toto.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/toto.com/chain.pem </VirtualHost> # domaine principal "www.toto.com" en HTTPS <VirtualHost *:443> ServerName www.toto.com DocumentRoot /chemin/vers/toto.com/www # HTTP Strict Transport Security Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" # configuration SSL SSLEngine on SSLOptions +StrictRequire SSLProtocol all SSLCipherSuite HIGH # certificats SSLCertificateFile /etc/letsencrypt/live/toto.com/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/toto.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/toto.com/chain.pem # log LogLevel warn ErrorLog /var/log/apache2/www.toto.com-error.log CustomLog /var/log/apache2/www.toto.com-access.log combined </VirtualHost>
Vérifiez la configuration avec la commande apache2ctl -t
avant de redémarrer Apache.
Au passage, vous pouvez voir que cette configuration ajoute un en-tête HTTP Strict Transport Policy, pour forcer l’utilisation du protocole HTTPS.
Renouvellement du certificat
Comme je l’ai dit plus haut, les certificats générés par Let’s Encrypt sont valables pendant 3 mois seulement. Il faut donc les renouveler régulièrement. La bonne nouvelle, c’est que Let’s Encrypt fait ça pour nous automatiquement.
Vous devriez voir un fichier /etc/cron.d/certbot
. Il fait en sorte que Let’s Encrypt soit exécuté chaque nuit ; il regarde alors les certificats qui arrivent à expiration dans moins d’un mois et procède à leur renouvellement.
Normalement, vous n’avez rien à faire. Vous pouvez toutefois lancer le renouvellement à la main :
letsencrypt renew
(Là encore, vous pouvez tester la commande « pour de faux » avec l’option --dry-run
, avant de l’exécuter réellement.)