Créer ou renouveler un certificat Let’s Encrypt avec la méthode DNS challenge

Certbot (Let’s Encrypt) a révolutionné et démocratisé l’utilisation du protocole HTTPS avec ses certificats gratuits. J’en avais déjà parlé notament dans l’article Renouveler un certificat SSL Let’s encrypt avec le plugin Webroot. La méthode utilisée dans l’article possède au moins un inconvénient en ce qui me concerne, si un des domaines ou sous-domaines n’a pas de document root – par exemple c’est un domaine redirigé – alors il n’est pas possible de renouveler le certificat car Certbot doit écrire à la racine de l’hébergement du domaine dans un répertoire .well-known, qui n’existe pas pour ce genre de cas.

La méthode DNS challenge

Pour palier à cela, je me suis penché sur la vérification par DNS que propose Certbot. Voici la syntaxe que j’utilise avec quelques options bien utiles :

certbot \
     --text \
     --agree-tos \
     --email postmaster@domaine.net \
     -d domaine.net \
     -d www.domaine.net \
     -d admin.domaine.net \
     -d outils.domaine.net \
     --manual \
     --preferred-challenges dns \
     --expand \
     --renew-by-default \
     --manual-public-ip-logging-ok \
     certonly

La première fois, Certbot va vous demander d’ajouter un ou plusieurs nouveaux enregistrements DNS de type TXT avec des messages de la sorte :

Please deploy a DNS TXT record under the name
_acme-challenge.www.domaine.net with the following value:

01q03R1jl4gen_8souu4Ki1kbnfEaJJ7JIjP_eG12nU

Before continuing, verify the record is deployed.

Lorsque c’est fait, il suffit d’appuyer sur entrée pour continuer et le renouvellement du certificat va se poursuivre.


Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/www.domaine.net/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/www.domaine.net/privkey.pem
   Your cert will expire on 2018-01-01. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Erreur urn:acme:error:connection lors du renouvellement d’un certificat Certbot

Vous avez un certificat Certbot (Let’s Encrypt) que vous renouvelez toujours sans problème tous les 90 jours, et récemment une erreur du type de celle ci-dessous survient alors que votre serveur fonctionne normalement.

Failed authorization procedure. mon.domaine.net (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Could not connect to mon-domaine.net

Il y a des dizaines et des dizaines de publications sur ce message d’erreur, qui logiquement renvoient vers des problèmes d’accessibilité au serveur (DNS) ou aux fichiers de celui-ci (permissions). D’ailleurs Certbot vous donne des indices dans ce sens :

To fix these errors, please make sure that your domain name was
 entered correctly and the DNS A record(s) for that domain
 contain(s) the right IP address. Additionally, please check that
 your computer has a publicly routable IP address and that no
 firewalls are preventing the server from communicating with the
 client. If you're using the webroot plugin, you should also verify
 that you are serving files from the webroot path you provided.

Mais comme dans mon cas, tout était fonctionnel.

IPv4 et IPv6

Après des heures à chercher et trifouiller ma configuration, je me suis rendu compte qu’un telnet mon.domaine.net 80 faisait déjà une résolution sur l’IPv6 de mon domaine avant de passer en IPv4. J’ai donc cherché dans ce sens et découvert que depuis peu Certbot privilégie IPv6 si un enregistrement DNS de type AAAA existe pour le domaine, ce qui était mon cas.

J’ai supprimé l’enregistrement AAAA (ce n’est peut-être pas le plus préférable, mais pour l’instant je m’en contente), et le renouvellement s’est bien déroulé avec succès.

Renouveler un certificat SSL Let’s encrypt avec le plugin Webroot

Installation d’un certificat SSL Let’s encrypt avec la méthode Webroot avec un serveur web Nginx

Il y a quelques semaines j’avais mis en place un certificat Let’s encrypt pour feub.net pour Nginx. A ce moment j’avais utilisé la méthode Standalone verification de Let’s encrypt qui est automatique mais qui a le désavantage d’utiliser le port 80, donc il faut stopper le serveur web pendant la génération du certificat, occasionnant un petit downtime du ou des site(s).

Ce petit inconvénient peut-être supprimé en utilisant la méthode Webroot proposée par Let’s encrypt, c’est celle-ci que je vais décrire ici et que j’ai utilisé pour renouveler le certificat pour feub.net.

Utilisation du plugin Webroot

Le plugin Webroot fonctionne de la sorte, un fichier est créé dans le répertoire .well-known  à la racine du serveur web (pour le ou les domaines en question), puis le serveur de validation de Let’s encrypt va faire des requêtes HTTP pour chaque domaine afin de confirmer que les DNS résolvent bien vers le serveur exécutant Let’s encrypt.

Pour l’installation de Let’s encrypt, se référer à la première partie de l’article Installer un certificat Let’s encrypt pour Nginx et servir WordPress en https.

Ensuite, pour générer le certificat avec la méthode Webroot, il suffit d’ajouter l’option –webroot  et de préciser le chemin vers la racine du site web avec l’option -w /chemin/vers/racine/web . Voici comment générer le certificat pour le domaine feub.net et son sous-domaine www.feub.net :

sudo letsencrypt certonly \
    --webroot -w /var/www/html/ \
    -d www.feub.net \
    -d feub.net

Après quelques secondes, si tout se passe bien, un message de succès apparait :

- Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.feub.net/fullchain.pem. Your cert will
   expire on 2016-07-25. 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

Le certificat est prêt. Il suffit alors de se référer toujours à l’article Installer un certificat Let’s encrypt pour Nginx et servir WordPress en https, chapitre Configurer Nginx avec SSL pour l’installer avec Nginx.

Installer un certificat Let’s encrypt pour Nginx et servir WordPress en https

Dans ce billet, voyons comment créer un certificat ssl avec Let’s encrypt et configurer le serveur web Nginx en HTTPS pour l’admin de Wordpress.

La folie Let’s encrypt fait des ravages, tout le monde y passe (même la Freebox!), en même temps c’est tout à fait naturel, pouvoir obtenir un vrai certificat SSL gratuit pour son site web, reconnu par les navigateurs sans message de sécurité, c’est plutôt sympa.

Je n’avais pas vraiment prêté attention à ce buzz au début, mais j’ai franchi le pas, d’ailleurs cet article vous présente un pas-à-pas de l’installation d’un certificat Let’s encrypt pour un serveur Nginx. Et spécialement pour les utilisateurs de WordPress, nous allons sécuriser la partie administration du CMS afin de laisser le site non crypté, car c’est toujours mieux pour les moteurs de recherche et la SEO.

Let’s encrypt

L’installation sous Fedora et consorts se fait très simplement avec dnf :

$ sudo dnf install letsencrypt

 

Lorsque l’installation est terminée, il y a plusieurs moyens de prouver la propriété d’un domaine et ainsi générer un certificat, dans notre cas nous utiliserons la méthode standalone qui a juste un petit point négatif, le serveur web (tout de moins le serveur tournant sur le port 80, dans mon cas c’est plutôt Varnish) doit être stoppé, car le script Let’s encrypt va démarrer son propre serveur web sur ce port (et le 443) afin de se répondre à lui-même et ainsi prouver la propriété du domaine.

Pour stopper Nginx sous Fedora 23 :

$ sudo systemctl nginx stop

 

On peut maintenant lancer le script Let’s encrypt pour vérifier le domaine. Il est possible de spécifier plusieurs domaines en les séparant par des virgules, par exemple pour le domaine nu et sa version avec www :

$ sudo letsencrypt --text --email fabien@feub.net \
--domains www.feub.net,feub.net \
--agree-tos --renew-by-default \
--standalone --standalone-supported-challenges \
http-01 certonly

 

Lorsque le script a terminé son exécution, il donne quelques informations sur le certificat créé, en particulier sur sa date d’expiration :

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/www.feub.net/fullchain.pem. Your cert will
expire on 2016-05-10. To obtain a new version of the certificate in
the future, simply run Let's Encrypt again.

 

Configurer Nginx avec SSL

Le certificat étant créé, on peut configurer le serveur web Nginx. Pour le tutoriel je suppose que votre configuration se situe sous /etc/nginx/nginx.conf.
Comme expliqué en introduction, le but ici est de n’avoir que l’admin de WordPress en HTTPS, c’est-à-dire uniquement https://feub.net/wp-admin (et https://feub.net/wp-login). Pour ceci, on va définir deux server blocks pour le même domaine, un qui servira les pages sur le port 80 et un pour les pages sur le port 443 (HTTPS) et sur le site normal on redirigera vers HTTPS tout ce qui arrive sur /wp-admin.

server {
        listen          80;

        server_name     feub.net;

        root            /var/www/html;
        index           index.php index.html index.htm;

        # Redirection de l'admin WordPress en HTTPS
        location ~ /wp-(?:admin|login) {
                return 301 https://$host$request_uri;
        }

        location / {
                try_files $uri $uri/ /index.php?$args;
        }

        # La configuration PHP
        include global/php.conf;
        include global/wordpress.conf;
        include global/things_not_logged.conf;
}

server {
        listen          443 ssl;

        server_name     feub.net;

        ssl_certificate     /etc/letsencrypt/live/www.feub.net/fullchain.pem;
        ssl_certificate_key    /etc/letsencrypt/live/www.feub.net/privkey.pem;

        root            /var/www/html;
        index           index.php index.html index.htm;

        # Redirect all other requests to HTTP.
        location / {
                return 301 http://$host$request_uri;
        }

        # Redirection de l'admin WordPress en HTTPS
        location ~ /wp-(admin|login) {
                # La configuration PHP
                include global/php.conf;

                try_files $uri $uri/ \1/index.php?$args;
        }
}

 

 

Vérification de la configuration Nginx et si tout est ok redémarrage du serveur web :

$ sudo nginx -t
$ sudo systemctl nginx start

 

WordPress

Pour terminer nous allons dire à WordPress d’utiliser HTTPS pour l’admin en ajoutant cette ligne dans le fichier de configuration wp-config.php :

define( 'FORCE_SSL_ADMIN', true );

On vérifie que l’accès au site se fait bien normalement en se rendant sur le site, puis on essaie l’admin de WordPress, on voit que l’on est redirigé sur https://feub.net/wp-login. Cela fonctionne.

Admin WordPress en https
Admin WordPress en https

 

 

 

 

 

 

 

Les certificats Let’s encrypt expirent après 90 jours, il faut donc penser à le renouveler avant la date indiquée lors de sa création.