Configurer HTTPS sur NGINX… correctement !

Configurer HTTPS sur NGINX

Salut à tous, dernier TP de la série qui fait suite à la réinstallation du serveur. On va voir comment configurer HTTPS sur NGINX… correctement. Car la crypto c’est pas une affaire de néophytes et on tombe facilement sur des sites plus ou moins connus ou officiels qui ont une configuration SSL à la rue. Par exemple vous regardez si votre banque, de votre boîte, association suit les bonnes pratiques pour assurer la confidentialité de vos communications ? Ça se voit de moins en moins sur des gros sites mais au détour d’une session web on tombe parfois sur une erreur comme celles qui sont très bien mises en exemple sur badssl.com. Si vous voulez vraiment du sang des exemples : il suffit de jeter un oeil à la « Recent Worst List » chez SSLLabs-Server Test.

Bref, on va voir comment configurer HTTPS avec NGINX à l’aide de Certbot pour le certificat (Let’s Encrypt) sur une Debian 8 et ajuster la configuration de NGINX pour être bibiche sur le test de SSLLabs.

Certbot, Le nouveau Let’s Encrypt.

Alors j’ai déjà parlé de Let’s Encrypt avec le serveur précédent donc on va pas revenir dessus, par contre vous noterez que certbot a bien évolué et se pare désormais d’un générateur automatique de documentation. Donc plutôt que de suivre bêtement ce que je vais vous dire la dessus, je vous invite à suivre la doc officielle pour votre distribution et serveur web.

Pour bien commencer, Certbot n’est pas présent dans les dépôts par défaut de Debian 8 donc il faut rajouter dans votre fichier /etc/apt/sources.list la paire de dépôt ci dessous :

deb http://ftp.debian.org/debian jessie-backports main
deb-src http://ftp.debian.org/debian jessie-backports main

Et suivre avec l’habituel :logo de Let's Encrypt

apt-get update && apt-get upgrade

Enfin on installe certbot

apt-get install certbot -t jessie-backports

Certbot délivre des certificats HTTPS issu de l’autorité de Let’s Encrypt et reconnus par la majorité des navigateurs aujourd’hui. Pour s’assurer qu’il délivre au bon détenteur du site il vérifie la correspondance avec le DNS associé à votre site et pour lequel le certificat est délivré. Du coup, si vous venez de changer ou de monter votre serveur, de vous devrez attendre que vos enregistrement DNS soient propagés correctement.

Déployer le certificat

Il n’existe pas (encore) de module Certbot qui fait tout pour vous avec NGINX (contrairement à Apache). Vous avez deux options, le mode certonly ou le mode webroot. Dans le mode certonly, Certbot va monter un mini-serveur web temporaire y déposer un fichier que le serveur de Let’s Encrypt ira vérifier, prouvant ainsi la bonne détention du DNS pour ce serveur et autorisant la délivrance du certificat. Seul défaut, si vous avez déjà votre site qui occupe le port 80 : certbot plantera car il ne peut pas monter son serveur sur ce port. Il faudra donc stopper le serveur web, exécuter Certbot et re-lancer votre serveur web ensuite. Ce n’est  pas envisageable sur un site en production donc, par contre l’avantage c’est que ça fonctionne même si vous n’avez pas un site publique ou que vous utilisez un serveur web exotique.

Cerbot mode Webroot

Nous, on va se concentrer sur la solution webroot qui permet d’enrôler et renouveler le certificat sans downtime de votre site web. Pour commencer, il faut créer un espace sur lequel certbot pourra agir de façon à rendre accessible le challenge attendu par le serveur. Pour ça on va ajouter le bloc suivant dans le fichier de config /etc/nginx/sites-available/wordpress de votre site

 # certbot webroot : .well-known doit rester accessible pour tous, pour que le serveur cerbot puisse y accéder
 location ~ /\.well-known/acme-challenge {
   allow all;
 }

Ensuite on demande le certificat et on indique à certbot avec la commande suivante  :

  • la racine de notre serveur web ; et
  • les noms de domaines auxquels il doit répondre :
certbot certonly --webroot -w /var/www/wordpress/ -d geekeries.org -d www.geekeries.org

Si se passe bien vous devriez avoir un message du genre :

# IMPORTANT NOTES:
 # - Congratulations! Your certificate and chain have been saved at
 # /etc/letsencrypt/live/<dns.tdl>/fullchain.pem. Your cert will
 # expire on 2017-01-06. 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 lose your account credentials, you can recover through
 # e-mails sent to <votreadresse@email.tld>
 # - Your account credentials have been saved in your Certbot
 # configuration directory at /etc/letsencrypt. You should make a
 # secure backup of this folder now. This configuration directory will
 # also contain certificates and private keys obtained by Certbot so
 # making regular backups of this folder is ideal.
 #cert.pem chain.pem fullchain.pem privkey.pem

Bon c’est bien on a un certificat valide pour notre site, encore faut-il dire à NGINX de l’utiliser et proposer HTTPS sur le port 443 avec ce certificat. Éditez votre fichier de configuration du site dans /etc/nginx/sites-enabled/wordpress, et ajouter les lignes suivantes dans votre bloc « server {…} »

listen 443 ssl default_server;        #écoute en IPV4 sur le port 443 en HTTPS
listen [::]:443 ssl default_server;  #écoute en IPV6 sur le port 443 en HTTPS
ssl_certificate /etc/letsencrypt/live/<dns.tdl>/fullchain.pem;   #le certificat (et sa chaîne) sont ici 
ssl_certificate_key /etc/letsencrypt/live/<dns.tdl>/privkey.pem; #La clé privée associé a utiliser est là

Redémarrer le serveur web avec « service nginx restart » et vous devriez avoir accès à votre site en HTTPS.

Renouvellement automatique du certificat

Le certificat de Let’s Encrypt expire au bout de 3 mois. Il est donc nécessaire de mettre en place un renouvellement automatique si vous ne voulez pas revenir faire l’action à la main tous les 2 mois et demi… Pour cela créer un bash pour certbot et l’intégrer dans une crontab pour ne plus avoir à vous en soucier :

echo 'certbot renew --quiet' > /Path/to/your/crontab/scripts/certrenew.sh
chmod +x /Path/to/your/crontab/scripts/certrenew.sh

Pour l’ajouter comme tache planifié une fois par semaine :

> crontab -e
6 6 * * 1 Path/to/your/crontab/scripts/certrenew.sh # execute tous les lundi à 6h06 (6h66 étant impossible, à mon grand regret)

Enfin, pour s’assurer que le renouvellement fonctionne sans effectuer l’action : certbot renew –dry-run

https et NGINX

Configurer HTTPS sur NGINX… correctement !

Bon avoir HTTPS c’est une chose, le configurer dans les règles de l’art s’en est une autre. Pour contrôler ça j’utilise SSLlabs, mais à priori l’utilitaire Sslyze permet aussi d’obtenir ces infos sans faire tester votre site par un service externe (plus mieux en entreprise si vous ne voulez pas indiquer à la NSA que votre configuration SSL est naze). L’API pour SSLlabs en ligne de commande est disponible ici (note : le test passe quand même par leur infra du coup), si vous voulez faire des test à grande échelle. En rédigeant l’article je suis tombé sur ce Gitbub qui maintient à jour une configuration type pour NGINX donnant la note A+ chez SSLlabs.

De mon côté, ca donné ces lignes supplémentaires suivantes dans mon fichier /etc/nginx/nginx.conf :

 # SSL Settings
 ##
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # TLS only, pas de SSL
 ssl_prefer_server_ciphers on;        # entre les suites du serveur et du client, le serveur choisi (évite les downgrade attack)
 
 ssl_dhparam /etc/ssl/dhparam.pem; # Clé Diffie-Hellman de 4096 dédié (et pas well-known)
 # A générer avec la commande suivante : openssl dhparam 4096 -out /etc/ssl/dhparam.pem
 # et prévoir 4h...
 
 #Liste de Ciphers choisi avec soins pour la robustesse et une compatibilité maximum de avec les clients
 ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
 
 # Cache de session TLS court 2min (détails https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache)
 ssl_session_cache shared:TLS:2m;
 
 # Activer l'OCSP stapling ou l'agrafage OCSP en français.
 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 8.8.8.8; # avec un DNS de Google (qu'on espère neutre)
 
 # Active HSTS pour un an. 
 # Attention : cela va imposer HTTPS sur votre site pour tous les clients qui le supporte.
 add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';

On redémarre un coup NGINX : et voilà, un beau A+ chez SSLlabs pour G33KERIES.ORG.

HSTS et conclusion

Configurer HTTPS sur NGINX
Pour gérer HSTS dans : chrome://net-internals/#hsts

Maintenant qu’on a vu comment configurer HTTPS sur NGINX, j’aimerai conclure sur HSTS. J’ai hésité un bon moment avant de l’activer, car ce faisant je force pour la majorité des navigateurs l’utilisation de HTTPS. Pour le coup, je n’étais pas bien certain que ce soit mon rôle de vous forcer la main la dessus. Après tout mon site n’héberge rien de sensible et si vous voulez accéder en HTTPS automatiquement : l’extension HTTPS Everywhere fera le boulot tout en vous laissant le choix. De plus l’accès en HTTPS réduit un peu les performances du site, shootant un bon paquet des optimisations mises en oeuvre dans le TP précédent.

Pourtant, j’ai préféré l’activé quand même car je crois que c’est le mon rôle de vous « montrer la voie » (<lumière divine>), et de prendre la main des néophytes qui n’y comprennent rien. En d’autres termes, je préfère être « trop loin » que « juste ce qu’il faut » et vous forcer la main pour votre bien… En bonus pour moi, Google indique clairement que les sites utilisant HTTPS sont mieux classé que ceux ne le proposant pas. C’est toujours ça, et si ça vous pose un problème  vous pourrez toujours trouver comment désactiver HSTS pour un site dans votre navigateur !

Pour finir, dans le premier article, je vous ai dis que j’allais tester Cloudflare, ce que j’ai fait…. vraiment pas longtemps : juste ce qu’il faut pour me rendre compte que leur infrastructure peut agir comme un bon gros proxy SSL. Le risque c’est que sous couvert de vous remonter un jolie A chez SSLLabs, sans que vous ayez à vous soucier de la moindre configuration d’https, vous permettez à Cloudflare (et la NSA puisque société américaine) de récupérer tout vos accès et de déchiffrer toutes les communications de vos utilisateurs… Donc non.

Et si vous avez un autre avis sur HSTS ou Cloudflare, je suis intéressé de l’avoir dans les commentaires !

@+

2 commentaires on “Configurer HTTPS sur NGINX… correctement !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *