Nginx : améliorer la sécurité et la rapidité de votre site HTTPS

Vous avez suivi mes 2 article précédents expliquant comment passer votre site en HTTPS gratuitement avec Let’s Encrypt et vous avez désormais un site HTTPS smiley.
C'est bien mais il est possible d'aller plus loin en améliorant la rapidité des connexions HTTPS et en améliorant la sécurité de ces connexions.

Pour voir comment se situe votre site, je vous invite à utiliser Qualsys SSL Labs test
Geek17.com a la note maximale A+, ce n'est certainement pas la note de votre site aura par défaut et je vous explique dans la suite de cet article comment obtenir ce A+ yes

 

Création d'un cache pour les connexions SSL

Etablir une liaison SSL entre un utilisateur et un serveur consomme du temps et des ressources.
En mettant en cache les paramètres de connexion, les requêtes suivantes seront considérablement plus rapides.

Nous allons donc commencer par mettre en place un cache Nginx pour les connexions SSL.
Pour cela, il est nécessaire d'ajouter quelques options dans le fichier de configuration général de nginx.
C'est très important d'ajouter ces 2 options dans le fichier nginx.conf et non dans vos vHost.
Sinon, lors de votre test sur Qualsys SSL Labs test vous obtiendrez le message No (IDs assigned but not accepted) pour Session resumption (caching).

 

sudo nano /etc/nginx/nginx.conf

Puis ajouter les 2 lignes suivantes au début de la session http {

http {
    # Cache SSL sessions parameters
    # This improves performance by avoiding the costly session negotiation process where possible
    # Cache of 1MB = 4000 sessions; with 20MB, we are ready for 80000 sessions
    ssl_session_cache shared:SSL:20m;
    # The default value is 5 minutes; increasing it to 3 hours
    ssl_session_timeout 180m;

    ....

Cela va créer un cache partagé entre tous les workers de Nginx.
On a demandé ici une taille du cache de 20 Mo. Selon la documentation, Nginx peut stocker environ 4000 sessions dans 1 Mo, donc pour cet exemple, nous pouvons stocker environ 80000 sessions (​si vous attendez plus de trafic, augmenter la taille du cache en conséquence).
Et ces sessions seront conservées pendant 180 minutes, soit 3 heures.

 

Configuration des vHost

Le reste de la configuration se trouve dans le fichier de configuration de votre vHost

sudo nano /etc/nginx/conf.d/www.geek17.com.conf

Dans l'article Nginx : passer votre site en HTTPS gratuitement avec Let’s Encrypt notre configuration SSL se limitait à ça :

    ssl on;
    ssl_certificate /etc/letsencrypt/live/www.geek17.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.geek17.com/privkey.pem;

Après ces 3 options nous allons ajouter les paramètres suivants qui seront expliqués ligne par ligne dans la suite de l'article.

    # Support only known-secure cryptographic protocols
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # Make the server choose the best cipher instead of the browser
    ssl_prefer_server_ciphers on;
    # Support only believed secure ciphersuites using the following priority:
    # 1. prefer PFS enabled ciphers
    # 2. prefer AES128 over AES256 for speed (AES128 has completely adequate security for now)
    # 3. Support DES3 for IE8 support
    #
    # Disable the following ciphersuites completely
    # - null ciphers, ciphers with low security, fixed ECDH cipher (does not allow for PFS)
    # - known vulnerable cypers (MD5, RC4, etc), little-used ciphers (Camellia, Seed)
    ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !RC4 !EXP !PSK !SRP !CAMELLIA !SEED';
    # Allow Nginx to send OCSP results during the connection process
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/www.geek17.com/fullchain.pem;
    # Use google DNS and cache results for 1 hour
    resolver 8.8.8.8 8.8.4.4 valid=1h;

    # Use 2048 bit Diffie-Hellman RSA key parameters
    # (otherwise Nginx defaults to 1024 bit, lowering the strength of encryption # when using PFS)
    # Generated by OpenSSL with the following command: openssl dhparam -outform pem -out /etc/nginx/ssl/dhparam2048.pem 2048
    ssl_dhparam /etc/nginx/ssl/dhparam2048.pem;

    # HSTS: HTTP Strict Transport Security
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

 

Forcer le protocole TLS et non SSL

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Par défaut, Nginx permet toujours d'utiliser SSLv3, qui est vulnérable à l'attaque de POODLE depuis Octobre 2014.

Il est donc préférable de ne pas utiliser SSL pour se concentrer sur l'utilisation de son successeur : TLS.
Sachant que tous les navigateurs prennent en charge SSL (même IE6 qui utilise TLSv1),

 

Spécifier une suite de chiffrement

ssl_prefer_server_ciphers on;
ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !RC4 !EXP !PSK !SRP !CAMELLIA !SEED';

Les protocoles SSL/TLS ne fournissent pas de cryptage par eux-mêmes mais ils permettent simplement à un serveur et à un client de convenir d'un algorithme de cryptage qui sera utilisé pour initier la communication.
Il existe de nombreux algorithmes de cryptage, chacun ayant un niveau de sécurité, de performance... et tous ne sont pas supportés par les navigateurs.

Le but de la configuration de la suite de chiffrement (cipher suite) est d'assurer la compatibilité avec le plus grand nombre possible de navigateurs, sans compromettre la sécurité et la performance du site.

On force donc le serveur (et non le navigateur) à choisir l'algorithme de cryptage à utiliser (ssl_prefer_server_ciphers on;)
Puis on indique dans notre suite de chiffrement (ssl_ciphers) :

  • de supporter par ordre de prirorité, les algorithmes ci-dessous
  1. le chiffrement PFS
  2. le chiffrement AES128 sur AES256 pour des raisons de vitesse (AES128 a un bon niveau de sécurité actuellement)
  3. DES3 pour le support d'IE8
  • et de désactiver l'utilisation de:
  1. les algorithmes vides (!aNULL, !eNULL)
  2. les algorithmes avec un faible niveau de chiffrement (!LOW)
  3. l'algorithme ECDH (non compatible avec PFS)
  4. les algorithmes vulnerables (MD5, RC4, etc)
  5. les algorithmes peu peu utilisés (Camellia, Seed)

 

Utiliser OCSP

Lorsqu'un navigateur se connecte à un serveur en utilisant le protocole HTTPS, il doit vérifier si le certificat utilisé par le serveur est toujours valide et qu'il n'a pas été révoqué.
A la première connexion, le navigateur devra donc contacter l'émetteur du certificat pour vérifier son statut; Cela prendra un peu de temps et augmentera le temps avant l'affichage de votre page.

OCSP stapling permet à votre serveur Nginx de réaliser cette vérification à l'avance et de communiquer directement le résultat au navigateur qui n'aura plus à le faire.
Les réponses OCSP sont signées par votre autorité de certification, de sorte que les navigateurs sont en mesure de leur faire confiance, même si elles proviennent directement de votre serveur.
Cela permet de réduire de manière significative le temps d'affichage de votre première page.

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/www.geek17.com/fullchain.pem;
resolver 8.8.8.8 8.8.4.4 valid=1h;

Comme vous le voyez ci-dessus, pour utiliser OCSP stapling, vous devez spécifier

  • l'emplacement de votre certificat HTTPS fullchain (via la commande ssl_trusted_certificate)
  • un ou plusieurs serveurs DNS à utiliser via l'option resolver (j'utilise les DNS publique de google qui sont assez performants)

 

Passer la clé Diffie-Hellman en 2048 bits

ssl_dhparam /etc/nginx/ssl/dhparam2048.pem;

Par défaut, Nginx utilise une clé Diffie-Hellman de 1024 bits mais il préférable d'utiliser à présent une clé de 2048 bits.
On spécifie donc avec la commande ssl_dhparam notre clé personnelle de 2048 bits générée avec openssl.
Attention, n'oubliez pas de générer (avec la commande suivante) votre clé de 2048 bits que vous demandez à Nginx d'utiliser smiley

sudo openssl dhparam 2048 -out /etc/nginx/ssl/dhparam2048.pem

 

Activation de HSTS : HTTP Strict Transport Security

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

D'après wikipédia : HTTP Strict Transport Security (HSTS) est un mécanisme de politique de sécurité proposé pour HTTP, permettant à un serveur web de déclarer à un navigateur web compatible, qu'il doit interagir avec lui en utilisant une connexion sécurisée (comme HTTPS). La politique est donc communiquée à l'agent utilisateur par le serveur via la réponse HTTP, dans le champ d'en-tête nommé « Strict-Transport-Security ». La politique spécifie une période de temps durant laquelle l'agent utilisateur doit accéder au serveur uniquement de façon sécurisée.

Les sites fonctionnant en mode HTTPS ont souvent un le site fonctionnel en HTTP avec une redirection vers HTTPS.
Mais ce mécanisme n'est pas sûr, il peut être victime d'une attaque MITM.

Lorsque HSTS est activé, le navigateur remplace automatiquement tous les liens non sécurisés par des liens sécurisés.
Par exemple, http://www.geek17.com/fr/linux-debian est automatiquement remplacé par https://www.geek17.com/fr/linux-debian avant d'accéder au serveur.

 

Sources :

Tags: 

Add new comment

You must have Javascript enabled to use this form.