News

Https, les configurations possibles. Aucun commentaire

Https, les configurations possibles.
Si vous vous êtes déjà intéressés au backend de mon site, vous remarquerez que la configuration est ... un peu paranoïaque ...

Cet article à pour but de vous montrer 2 configurations possibles pour un site qui utilisera Nginx en temps que Serveur Web / Reverse Proxy afin que les connexion vers votre site soit "sûre" :

- Une configuration axée compatibilité
- Et la configuration que j'utilise sur mes sites.


Cet article parlant que de pratique (ou presque que) je vous conseille de lire l'article de notre cher Aeris qui expliquera pas mal de termes et protocoles qui vont être évoqués plus bas :)

Cliquez ici

On va donc partir du contexte suivant :

Nous disposons de la dernière version de Debian avec la dernière version de Nginx compilée avec la dernière version de LibreSSL.

Avant d'aborder les 2 configs, des paramètres communs doivent être appliqués.

Dans le conteneur http de nginx :

server_tokens off;
more_set_headers 'Server: Écrivez ce que vous voulez ici';
ssl_ecdh_curve sect571r1:X25519:secp521r1:secp384r1;


On retire donc l'affichage de la version de Nginx utilisée.
On change Le header HTTP "Server" afin qu'il ne sorte pas des informations comme le nom de votre serveur web ou encore sa version.
Et on change l'ordre des courbes ECC utilisées (les plus fortes d'abord).

Dans un premier conteneur server :

On va d'abord faire une redirection digne de ce nom afin que aucun visiteur ne puisse visionner votre site en HTTP.

server {
listen 80;
server_name exemple.domaine.com;
return 301 https://$server_name$request_uri;
}


Ainsi tout visiteur essayant de se connecter en HTTP se fera rediriger en HTTPS

Dans un deuxième conteneur server :

On va d'abord préciser quel port Nginx doit écouter et comment il doit répondre :

listen 443 ssl http2;


Ensuite le certificat TLS doit être RSA 2048 bits ou ECC 256 bits au minimum et RSA 4096 bits ou ECC 384 bits au mieux.
Si vous avez généré votre certificat avec LetsEncrypt il faut donc déclarer comme ceci :

ssl_certificate /etc/letsencrypt/live/exemple.domaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exemple.domaine.com/privkey.pem;


(fullchain.pem étant le certificat en lui même et privkey.pem la clée privée pour ce certificat)

Ensuite on va mettre en place l'OCSP Stapling.

ssl_trusted_certificate /etc/letsencrypt/live/exemple.domaine.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 208.67.222.222 208.67.220.220 valid=300s;
resolver_timeout 10s;


Quelques paramètres pour renforcer la sécurité :

ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;


Ensuite plusieurs En-têtes HTTP à rajouter :

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options DENY;


Et voilà pour la partie commune :)



La configuration axée compatibilité :


En protocole, on va garder que TLS 1.1 et TLS 1.2, donc sur Nginx :

ssl_protocols TLSv1.2 TLSv1.1;


Et en ciphers on dégage tout ce qui est cassé et / ou trop dangereux à savoir :

NULL : Oui oui ! Pas de chiffrement ...
MD5 : Cassable par un pc de bureau.
3DES : Trop faible et présente d'autres soucis.
RC4 : Cassable par un pc de bureau.
CAMELLIA : Support nul / quasi inexistant.
SEED : Mêmes raisons que pour CAMELLIA
RSA : Car sinon pas de PFS.
EDH+AES : Afin de refermer Logjam.

Sur Nginx ça donne ça :

ssl_ciphers HIGH:!aNULL:!MD5:!3DES:!RC4:!CAMELLIA:!SEED:!RSA:!EDH+AES;


Ainsi, la configuration finale de votre conteneur server sera :

Caché:
server {
listen 443 ssl http2;
server_name exemple.domaine.com;
ssl_certificate /etc/letsencrypt/live/exemple.domaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exemple.domaine.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/exemple.domaine.com/chain.pem;
ssl_protocols TLSv1.2 TLSv1.1;
ssl_ciphers HIGH:!aNULL:!MD5:!3DES:!RC4:!CAMELLIA:!SEED:!RSA:!EDH+AES;
ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options DENY;
ssl_stapling on;
ssl_stapling_verify on;
resolver 208.67.222.222 208.67.220.220 valid=300s;
resolver_timeout 10s;
}



La configuration de mes serveurs :

En protocole c'est TLS1.2 ou rien, donc :

ssl_protocols TLSv1.2;


Pour les ciphers, on dégage celles évoquées plus haut mais on en dégage une en plus :

SHA-1 : Collision trouvée par Google + montrait déjà des signes de faiblesse.

Sur Nginx ça donne donc ceci :

ssl_ciphers HIGH:!aNULL:!MD5:!3DES:!RC4:!CAMELLIA:!SEED:!RSA:!EDH+AES:!SHA;


Ainsi, la configuration finale de votre conteneur server sera :

Caché:
server {
listen 443 ssl http2;
server_name exemple.domaine.com;
ssl_certificate /etc/letsencrypt/live/exemple.domaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exemple.domaine.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/exemple.domaine.com/chain.pem;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5:!3DES:!RC4:!CAMELLIA:!SEED:!RSA:!EDH+AES:!SHA;
ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options DENY;
ssl_stapling on;
ssl_stapling_verify on;
resolver 208.67.222.222 208.67.220.220 valid=300s;
resolver_timeout 10s;
}



Après avoir configuré votre nginx, pensez à reload (nginx -s reload) et à vérifier si ça a bien été pris en compte ou sur SSLLabs ou sur CryptCheck :)

Et voilà, maintenant, les connexion entre le serveur et les clients sont sécurisées (pour de vrai).

NB : Je ne parle pas de DANE/TLSA et HPKP car ou déploiement risqué ou compliqué ou alors car c'est très mal supporté par les navigateurs.