PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Angristan : Configurer HTTPS sur Nginx

dimanche 17 janvier 2016 à 14:59

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 : Plusieurs versions de SSL et TLS sont disponibles : 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). 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. Voici la Cipher Suite que je vous conseille :
ssl_ciphers ECDHE+AESGCM:EECDH+AES;
Elle est compatible avec quasiment tous les OS et navigateurs qui fonctionnent avec TLS 1.2. On peut ajouter ceci, pour s'assurer que le client utilisera bien nos ciphers en priorité :
ssl_prefer_server_ciphers on;
La NSA recommande d'utiliser AES 256 bits, or cette suite est compatible avec AES 256 bits et 128 bits. Configurer HTTPS sur Nginx La cipher suite la plus sécurisée est donc :
ssl_ciphers ECDHE+AESGCM256:EECDH+AES256;
C'est cette suite qui vous permet d'obtenir 100% au chiffrement dans les tests HTTPS. Cependant je ne vous la recommande pas du tout puisque les navigateurs les plus utilisés aujourd'hui vont tenter de négocier l'établissement d'une connexion HTTPS en AES 128 bits. Dès lors, votre site ne sera plus accessible. La première cipher suite est donc la meilleure puisqu'elle est compatible avec un grand nombre de navigateurs et dans la plupart des cas, le chiffrement s'établira en AES 256 bits (on respecte quand même les conseils de la NSA du coup ;-) ) 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 : 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+AESGCM256:ECDHE+AES256;
 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

Gravatar de Angristan
Original post of Angristan.Votez pour ce billet sur Planet Libre.