Let’s Encrypt, reverse-proxy NginX, https

Avec l’arrivée de Let’s Encrypt, il est désormais possible pour les particuliers d’obtenir des certificats SSL/TLS pour leurs sites et de passer ainsi de http à https. Je vous propose dans cet article de voir comment obtenir des certificats Let’s Encrypt et comment les installer sur un reverse-proxy Nginx.Voici le schéma des flux après installation du certificat et configuration du reverse proxy.

Réseau - https sur reverse-proxy Nginx avec Let's Encrypt.
Réseau – https sur reverse-proxy Nginx.

N.B. : la distribution utilisée est Ubuntu server 16.04 LTS mais les commandes sont facilement adaptables pour d’autres distributions.

Protocole https

Pour rappel, l’avantage de passer en https est de chiffrer le trafic entre le client et le serveur (ici le reverse-proxy nginx). C’est intéressant lorsqu’il y a des champs de saisie, notamment identifiant/mot de passe. C’est également un facteur supplémentaire de bon référencement de vos sites dans les moteurs de recherche. L’inconvénient en revanche est la charge supplémentaire liée au chiffrement/déchiffrement sur le client et le serveur, ainsi éventuellement que sur les équipements de sécurité (pare-feu, IPS, IDS).

Installation de Certbot

Certbot est le logiciel qui va automatiser toute la procédure de création et de téléchargement du certificat pour votre site. Au passage, il vérifie que vous possédez bien les droits sur le serveur qui héberge le site, en déposant un fichier dans un répertoire.

Toutes les opération suivantes s’effectuent sur le serveur reverse-proxy Nginx.

Installation proprement dite (enregistrement du PPA et installation avec APT).

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

Le challenge de Let’s Encrypt

Let’s Encrypt ne distribue ses certificats qu’aux propriétaires des droits sur les sites ou les DNS. Il existe donc à ma connaissance deux méthodes pour montrer patte blanche. Une consiste à modifier des enregistrements DNS (je n’ai pas étudié cette méthode), l’autre à créer un répertoire sur le site pour montrer que vous avez les droits sur ce site. Nous allons donc créer un répertoire sur le reverse proxy qui ne servira qu’à la vérification opérée par Let’s Encrypt. Ce répertoire est à la racine est s’appelle .well-known.

Pour faciliter les choses, je prends pour exemple ce site (au départ http://w3.nonsenz.org).

Création d’un répertoire pour le challenge

# mkdir -p /var/www/html/w3.nonsenz.org/.well-known

Une fois le répertoire créé, nous modifions la configuration de Nginx dans le fichier /etc/nginx/sites-enabled/conf_du_virtualhost.conf pour utiliser ce répertoire local malgré la configuration en mode reverse-proxy.

Avant la section location /{ proxy_pass… } nous introduisons les directives suivantes :

 

location /.well-known {
    alias /var/www/html/w3.nonsenz.org/.well-known;
}

Ensuite, on vérifie que le fichier de configuration est toujours cohérent et on redémarre nginx.

# nginx -t
# service nginx restart

Nous sommes maintenant prêts à générer le certificat Let’s Encrypt… Tadaaaa !

Création et installation du certificat

Nous allons utiliser la méthode dit « manuelle » qui me semble plus claire, surtout si on héberge plusieurs sites sur la même infrastructure.

# certbot certonly --webroot -w /var/www/html/w3.nonsenz.org/ -d w3.nonsenz.org

L’option certonly permet de réaliser la méthode « manuelle », l’option –webroot -w indique où se trouve le répertoire caché et l’option -d permet d’indiquer le nom d’hôte du site. Dans le cas où il y a des alias pour le serveur (par exemple, www.nonsenz.org, rezo.nonsenz.org et nonsenz.org), on répète l’option -d.

[...] -d nonsenz.org -d www.nonsenz.org -d rezo.nonsenz.org

Si tout se passe bien, certbot réalise le challenge, crée et copie le certificat et la chaîne de confiance et place tous les fichiers ici : /etc/letsencrypt/live/w3.nonsenz.org

Il s’agit en fait de liens symboliques vers des fichiers présents dans /etc/letsencrypt/archives/…

Configuration du reverse-proxy nginx en https

On crée un nouveau fichier de configuration « de virtualhost » : /etc/nginx/sites-available/https-monsite.conf

####w3.nonsenz.org
server {
  listen 443 ssl;

  server_name w3.nonsenz.org;

  ssl_certificate /etc/letsencrypt/live/w3.nonsenz.org/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/w3.nonsenz.org/privkey.pem;

# Turn on OCSP stapling as recommended at
# https://community.letsencrypt.org/t/integration-guide/13123
# requires nginx version >= 1.3.7
  ssl_stapling on;
  ssl_stapling_verify on;

# Uncomment this line only after testing in browsers,
# as it commits you to continuing to serve your site over HTTPS
# in future
  #add_header Strict-Transport-Security "max-age=31536000";

  access_log /var/log/nginx/w3-https.log combined;

  location /.well-known {
    alias /var/www/html/w3.nonsenz.org/.well-known;
  }
  location / {
    proxy_pass http://albert.nonsenz.lan:8005/;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    expires off;
    add_header Cache-Control private;
  }
}

Pour info, une directive est encore commentée, add_header Strict-Transport-Security « max-age=31536000 »; mais elle pourra être décommentée plus tard, quand nous aurons vérifié que tout fonctionne bien au niveau https et que nous aurons fait la redirection de http vers https.

Par ailleurs, vous vous posez peut-être des questions sur les deux dernières directives. Elles indiquent que les entêtes http « expires » ne doivent pas être modifiées par le reverse proxy (je les gère directement sur le serveur web d’applications) et qu’il faut ajouter l’entête http Cache-Control private, qui indique que les entêtes « expires » doivent être gérées par le client final (le navigateur) et non pas par les proxies intermédiaires.

Vous remarquerez également que le coup de répertoire .well-known a été replacé dans la configuration https. En effet, lors des renouvellements de certificats, si on a fait la redirection http vers https, il faut bien que le https ait cette configuration ou le renouvellement échouera.

Ne pas oublier de faire le lien symbolique dans /etc/nginx/sites-enabled/ pour que ce fichier de configuration soit pris en compte.

On teste et on redémarre nginx.

# nginx -t
# service nginx restart

Vous pouvez désormais tester le site en https, et vérifier la validité du certificat dans le navigateur. Si le site est bien fait (uniquement des adresses relatives) tout va bien. Si le site est fait avec un CMS, il faudra peut-être faire des choses au niveau du site. Changer par exemple la variable $base_url dans le settings.php de Drupal, ou ajouter une extension dans WordPress. Nous verrons d’ailleurs la mise ne place de https pour WordPress dans un autre article.

Redirection du http vers le https dans Nginx

Il reste à modifier le fichier de configuration du site en http pour faire la redirection permanente vers la version en https. On replace les directives proxy_pass par un rewrite. Le fichier de configuration du virtualhost en http ressemble désormais à ceci :

#### w3.nonsenz.org
server {
  listen 80;
  server_name w3.nonsenz.org;

  location /.well-known {
    alias /var/www/html/w3.nonsenz.org/.well-known;
  }

  location / {
    rewrite ^ https://$host$request_uri? permanent;
   # proxy_pass http://albert.nonsenz.lan/w3.nonsenz.org/;
  }
}

On redémarre nginx et on teste. Si ça fonctionne, on peut décommenter la directive qui permet aux clients de mémoriser que le site est en https (dans le fichier de configuration du virtualhost en https). On redémarre nginx.

Renouvellement des certificats Let’s Encrypt

Les certificats Let’s Encrypt sont émis pour une durée relativement courte, 90 jours. La bonne nouvelle, c’est que le renouvellement peut être automatisé dans un cron, toujours avec certbot. Comme le renouvellement est possible au bout de 60 jours, une tentative de renouvellement par semaine est largement suffisante.

Tout d’abord, vous pouvez vérifier que votre architecture supportera bien le renouvellement en lançant la commande de simulation de renouvellement

# certbot --dry-run renew

Certbot va simuler le renouvellement de tous les certificats du serveur et vous indiquer si ça marche ou non.

Si tout va bien, on peut créer une tâche planifiée pour lancer le renouvellement automatiquement. Attention, après un renouvellement de certificat, il faut absolument redémarrer le serveur web nginx, sinon le nouveaux certificats ne seront pas pris en compte.

Personnellement, mon crontab ressemble à ceci :

#Tous les mercredis à 3h42 tentative de renouvellement des certificats
42 3 * * 3 /usr/bin/certbot renew --quiet --renew-hook "service nginx reload"

Il est possible de forcer le renouvellement avec l’option –force-renew mais ce n’est pas conseillé car cela charge inutilement la plate-forme Let’s Encrypt et celle-ci a mis en place des limites de renouvellement.

Sécurisation des flux SSL/TLS

La sécurisation des flux SSL/TLS consiste à limiter le nombre de protocole (exclure tous les protocoles qui ont des failles connues), limiter également les algorithmes de chiffrement, et enfin réaliser des clés plus robustes. Le site parfait pour vous aider à réaliser ces différentes opérations est https://www.ssllabs.com/ qui propose à la fois de tester votre site et vous renvoie vers différentes documentations permettant de renforcer la sécurité.

Liens utiles

Queqlues liens utiles :

N’hésitez pas à me signaler toute erreur ou tout dysfonctionnement lors de l’utilisation de cette documentation. Bisous !

Laisser un commentaire