Configurer HTTPS sur Nginx

Configurer HTTPS sur Nginx

Et non, HTTPS ne se résume pas avoir avoir le cadenas vert dans votre navigateur ! De plus en plus de sites sont compatibles HTTPS, et cela ne va qu'augmenter avec l'arrivée de Let's Encrypt qui propose des certificats X.509 gratuits tout comme StartSSL. Et même si vous utilisez un certificat auto-signé, votre sécurité reste importante. Nous allons voir dans ce tutoriel tous les paramètres à ajouter dans votre configuration Nginx pour avoir un chiffrement au top. Certains en ont bien besoin ! Configurer HTTPS sur Nginx   Tous les paramètres ci-dessous seront à mettre dans votre server block (HTTPS), c'est à dire ici :
server {
# 
# Votre conf
#
}

Redirection et ports

Lorsqu'un visiteur va aller sur votre site web, il va demander à voir la page en HTTP par défaut. Il faut donc rediriger toutes les requêtes HTTP en HTTPS.
server {
       listen         80;
       server_name    domain.com;
       return         301 https://$server_name$request_uri; #Redirection 
}

server {
       listen         443 ssl;
       server_name    domain.com;
       [....]
       # conf HTTPS
}

IPv4 et IPv6

Écouter en IPv4 sur le port HTTPS :
listen 443 ssl;
Écouter en IPv6 sur le port HTTPS :
listen [::]:443 ssl;

SPDY et HTTP/2

SPDY est un protocole développé par Google dont le principal avantage est le multiplexage des connections, c'est à dire de pouvoir faire plusieurs requêtes HTTP à la fois. SPDY est présent dans sa version 3.1 depuis Nginx 1.5. Il suffit d'ajouter spdy à la directive listen :
listen 443 ssl spdy;
La version 4 de SPDY n'a pas été aboutie puisqu'elle a servie de base à HTTP/2, qui dispose des même avantages en HTTPS. Configurer HTTPS sur Nginx   Le module HTTP/2 remplace le module SPDY depuis la version 1.9.5 de Nginx. Il suffit de remplacer spdy par http2 dans la directive listen :
listen 443 ssl http2;
Pour avoir un support complet de HTTP/2 avec ALPN, il faudra compiler Nginx avec OpenSSL 1.0.2, qui n'est pas encore présent dans toutes les distributions. Pour tester le support de HTTP/2 et de ALPN, vous pouvez utiliser l'outil de test de KeyCDN : Configurer HTTPS sur Nginx

SSL et TLS

SSL et TLS sont deux protocoles qui permettent d'échanger des données de manière sécurisée. Ils garantissent :
  • l'authetification du serveur
  • la confidentialité des données
  • l'intégrité des données
Plusieurs versions de SSL et TLS sont disponibles :
  • SSL v1
  • SSL v2
  • SSL v3
  • TLS v1.0
  • TLS v1.1
  • TLS v1.2
  • TLS v1.3 (en cours de développement)
Toutes les version de SSL sont à proscrire. Elle sont complètement trouées et contiennent de très nombreuses vulnérabilités. TLS 1.0 et et 1.1 sont à proscrire également le plus possible. Il n'y presque aucune raison de les utiliser aujourd'hui puisque la quasi-totalité des navigateurs et OS modernes sont compatibles avec (même Windows XP avec Chrome ou Firefox). L'ANSSI recommande également de n'utiliser que TLS (et si possible d'éviter TLS 1.0). La conf est donc très simple :
ssl_protocols TLSv1.2;

Certificat et clé

Après avoir généré votre certificat ou après l'avoir obtenu auprès de votre autorité de certification, vous vous retrouvez avec plusieurs fichiers, dont votre clé et quelques certificats.
ssl_certificate /chemin/vers/cert.pem;
ssl_certificate_key /chemin/vers/key.pem;
Si vous utilisez un certificat obtenu auprès d'une autorité de certification, il faudra ajouter le certificat intermédiaire correspondant dans cert.pem. Je vous conseille de vous référer à la doc pour cette étape. Exemple pour Let's Encrypt :
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;

Clé Diffie-Hellman (DH)

L'échange de clé DH est très impotant puisqu'il permet au serveur et au client de se mettre d'accord sur un secret commun sans qu'un tier puisse en prendre connaissance. La clé de base n'est que de 2048 bits, or la NSA recommande d'utiliser des DH d'au moins 3072 bits : Configurer HTTPS sur Nginx Nous allons en créer une de 4096 bit :
openssl dhparam 4096 -out dh4096.pem
Puis l'ajouter dans la configuration :
ssl_dhparam /etc/nginx/dh4096.pem;

Elliptic curve Diffie–Hellman (ECDH)

L'échange de clés Diffie-Hellman basé sur les courbes elliptiques est une variante du protocole vu ci-dessus, plus performante et plus sécurisée. En effet, si l'on utilise ce paramètre :
ssl_ecdh_curve secp521r1;
La clé sera alors équivalente à une clé DH de 15360 bits. Cependant je ne vous conseille pas d'utiliser P-521 puisqu'il est incompatible avec un très grand nombre de navigateurs, notemment Chrome, ou la compatibilité a été mystérieusement retirée... Notre chère NSA recommande d'utiliser P-384 au maximum, sachant que P-256 n'a pas encore été cassé. Configurer HTTPS sur Nginx P-384 fonctionne avec tous les navigateurs et OS compatibles avec TLS 1.2, on ne va donc pas s'en priver :
ssl_ecdh_curve secp384r1;
Pour info, ECDH P-384 équivaut à DH 7680 bits, ce qui est largement suffisant.

Cipher Suite

La suite cryptographique est... bon, on va citer Wikipédia ce sera plus clair pour tout le monde :D
Une suite cryptographique (cipher suite en anglais) est le nom de la combinaison des algorithmes d'échange de clés, d'authentification, de chiffrement par bloc et génération du code d'authentification de message (MAC) utilisée afin d'établir le paramétrage de sécurité pour une connexion réseau utilisant le protocole de communication Secure Socket Layer (SSL) et Transport Layer Security (TLS).
La Cipher Suite est très importante puisqu'elle va garantir que le client utilisera uniquement des paramètres dans cette liste s'il est compatible. L'ANSSI recommande d'utiliser AES 128 bits, et la NSA recommande d'utiliser AES 256 bits. Configurer HTTPS sur Nginx AES 256 bits ayant plus de potentiel pour une side timing attack, il est préférable de garder une compatibilité avec AES 128 bits. De plus, si vous n'autorisez que AES-256, les navigateurs compatibles avec HTTP/2 ne pourront pas accéder à votre site puisqu'à l'heure actuelle, la négociation ne se fait pas en AES-256. Voici donc la Cipher Suite que je vous conseille :
ssl_ciphers ECDHE+AESGCM:EECDH+AES;
Elle est compatible AES CBC/GCM 128/256 bits, soit avec quasiment tous les OS et navigateurs qui fonctionnent avec TLS 1.2. Elle est On peut ajouter ceci, pour s'assurer que le client utilisera bien nos ciphers en priorité :
ssl_prefer_server_ciphers on;
  Pour info, la suite cryptographique qui permet d'obtenir un 100% au chiffrement dans les tests HTTPS est  la suivante :
ssl_ciphers ECDHE+AESGCM256:EECDH+AES256;
Cependant, comme dis plus haut, elle n'est pas forcément plus sécurisante et est à proscrire si vous utilisez HTTP/2. Par ailleurs vous remarquerez que l'on utilise ECDHE et non pas DHE (le dernier E est pour Exchange)

Online Certificate Status Protocol (OCSP)

OCSP est un protocole qui permet de vérifier si un certificat est valide ou révoqué. Pour cela, à chaque connexion, le client fait une requête à un répondeur OCSP, ce qui peut poser des problèmes de performance et de confidentialité. C'est pour cela que maintenant, on utilise OCSP Stapling, qui corrige les problèmes de OCSP. En effet c'est le serveur qui fait les vérifications, et une confirmation signée de l'Autorité de Certification est directement donnée dans le TLS handshake, avec un timestamp, soit une durée de validité du message. Pour cela rien de plus simple (ou pas), il faut d'abord ajouter un fichier contenant le certificat root et le certificat intermédiaire de votre autorité de certification. Évidemment, Le OCSP Stapling ne peut pas être utilisé avec un certificat auto-signé. Une fois que cela est fait, il faut rajouter cette directive :
ssl_trusted_certificate /chemin/vers/chain.pem;
Cela permettra à Nginx de savoir à quelle autorité de certification il devra causer. Pour Let's Encrypt ce sera ceci :
ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
Ensuite, on active OCSP Stapling :
ssl_stapling on;
ssl_stapling_verify on;
Par défaut, Nginx résoudra les noms de domaines des répondeurs OCSP avec les serveurs DNS par défaut du système soit ceux dans /etc/resolv.conf. La plupart des sites recommandent les serveurs DNS publics de Google, mais on a aussi des serveurs DNS en France qui fonctionnent tout aussi bien : ceux du FAI Associatif FDN par exemple.
resolver 80.67.169.12 80.67.169.40 valid=300s;
resolver_timeout 5s;
Pour plus de rapidité et de confidentialité, vous pouvez utiliser un résolveur DNS local, et pourquoi pas le combiner avec un serveur DNS de la FDN pour la redondance :
resolver 127.0.0.1 80.67.169.12 valid=300s;
resolver_timeout 5s;
Vous pouvez vérifier que OCSP est fonctionnel avec la commande suivante :
openssl s_client -connect angristan.fr:443 -tls1_2 -tlsextdebug -status | grep "OCSP Response Status: successful"
Ou sur SSL Labs : Configurer HTTPS sur Nginx

HTTP Strict Transport Security (HSTS)

HSTS est un header HTTP qui dit à un visiteur de se connecter directement en HTTPS à sa prochaine visite. Cela permet donc d'avoir une communication entièrement chiffrée, et d'éviter la redirection que l'on a vu au début de l'article. Il suffit d'ajouter un header à Nginx :
add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; preload";
HSTS sera donc valide pendant 15552000 secondes soit pendant 180 jours, il sera aussi valable pour les sous-domaines. Faites donc attention, ils faut que tous vos sites sur ce domaine soit en HTTPS (certificat valide ou pas). Vous pouvez aller plus loin avec HSTS preload. Si vous avez ajouté le header ci-dessus, vous pouvez inscrire votre domaine sur cette liste. Comme le site l'indique, le domaine de votre site sera hardcodé dans les navigateurs suivant :
  • Chrome
  • Firefox
  • IE 11
  • Edge
  • Safari
Cela signifie que le navigateur n'aura même pas besoin de communiquer avec votre serveur une seule fois pour qu'il sache qu'il doit communiquer avec vous en HTTPS-only. Attention, vous pouvez difficilement vous retirer de la liste, il faudra donc être sur que votre site restera à tout jamais en HTTPS ! ;) HSTS preload sera activé au bout de quelques jours. Vous pouvez le vérifier sur SSL Labs : Configurer HTTPS sur Nginx Bien entendu, HSTS Preload n'est pas une obligation.

Cache de session

Ces directives définissent le cache et le temps qu'un client peut garder les paramètres HTTPS en cache :
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_session_tickets off;
Ils sont détaillés sur la doc Nginx.

Tester sa configuration

Il existe de très bon outils pour tester sa configuration HTTPS. Le premier est le très connu SSL Lab de Qualys. Il est très complet, et détaillera tous les aspects de votre configuration : les Ciphers, OCSP, HSTS, HPKP (je n'ai pas parlé de ce dernier dans cet article puisque je ne l'utilise pas). Un des ses principaux avantages est qu'il vous permet aussi de voir avec quels OS et navigateurs votre configuration actuelle est compatible : Configurer HTTPS sur Nginx Vous pouvez voir les protocoles et Ciphers Suites disponibles : Configurer HTTPS sur Nginx Et bien sûr, notre super note ! :D Configurer HTTPS sur Nginx Un autre super outil est CryptCheck fait par le fameux "crypto-terroriste individuel auto-radicalisé sur l’Internet digital" qu'est @Aeris22. Il est aussi super complet : Configurer HTTPS sur Nginx PS : il est bien possible d'avoir 100% partout avec la Cipher Suite (à ne pas utiliser) dont je vous ai parlé plus haut. Configurer HTTPS sur Nginx Enfin, il y a SSL  Decoder qui vous donnera tout un tas d'informations. Il ne vous donne pas de note mais est très complet en terme d'analyse. À utiliser pour les utilisateurs confirmés ;)

Sources et ressources

@Aeris22, alias Imirhil, est un pro en sécurité qui parle très souvent de chiffrement. Je vous conseille de regarder sa conférence SSL/TLS pour les nuls, et de lire ses articles sur CryptCheck ou encore Let's Encrypt. L'article étant un peu (très) long, voici un résumé de ma configuration HTTPS:
server {
 listen 80;
 server_name domain.com;
 return 301 https://$server_name$request_uri;
}
server {
 listen 443 ssl http2; #Nginx > 1.9.5
 listen 443 ssl spdy; #Nginx < 1.9.5
 server_name domain.com;
 
 [....]
 # Le reste de votre conf
 [....]

 ssl_certificate /etc/nginx/ssl/domain/cert.pem;
 ssl_certificate_key /etc/nginx/ssl/domain/key.pem;
 ssl_trusted_certificate /chemin/vers/chain.pem;
 ssl_dhparam /etc/nginx/dhparam.pem;
 ssl_protocols TLSv1.2;
 ssl_ciphers ECDHE+AESGCM:EECDH+AES
 ssl_prefer_server_ciphers on;
 ssl_ecdh_curve secp384r1;
 resolver 127.0.0.1 80.67.169.12 valid=300s;
 resolver_timeout 5s;
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_session_cache shared:SSL:10m;
 ssl_session_timeout 5m;
 ssl_session_tickets off;

 add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; preload";
}
N'hésitez pas à tester les configurations des sites que vous visitez (leur cadenas vert n'est peut-être pas si vert que ça), et partagez vos jolis A+ pour qu'on ait un web plus sécurisé ! Je remercie particulièrement @HLFH_Space qui m'a énormément aidé et qui est (presque) une bible en la matière. ;) Sources :

L'article Configurer HTTPS sur Nginx a été publié sur Angristan

Vus : 934
Publié par Angristan : 57