Durcir un reverse proxy est facile ; le durcir sans casser de client demande de savoir ce qu'on retire. Voici la configuration que j'applique par défaut, et surtout la vérification qui va avec.
Le socle
Trois directives font l'essentiel du travail :
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305;
Laisser ssl_prefer_server_ciphers off est contre-intuitif : en TLS 1.3, le client choisit mieux que nous, parce qu'il sait sur quel matériel il tourne.
Ce qu'on retire, et ce que ça coûte
| Retiré | Casse | Verdict |
|---|---|---|
| TLS 1.0 / 1.1 | Android < 5, IE sur XP | à retirer |
| Suites CBC | Clients Java 7 anciens | selon le parc |
ssl_session_tickets | rien de visible | à retirer |
Règle que je m'impose : on ne retire une suite qu'après avoir regardé les logs d'accès réels, pas la théorie.
Vérifier avant de recharger
Dans l'ordre, jamais l'inverse :
nginx -t— la syntaxe seulement- le handshake, depuis l'extérieur :
openssl s_client -connect exemple.be:443 -tls1_2testssl.sh --severity HIGH exemple.be
nginx -s reload— rechargement sans coupure
L'erreur classique est d'inverser 2 et 3 : on découvre la casse après l'avoir mise en production.
HSTS, en dernier
Strict-Transport-Security est la seule directive de cette liste qui soit difficile à annuler : une fois l'en-tête servi avec un max-age long, les navigateurs refusent le HTTP pendant toute cette durée. Je commence toujours à max-age=300, je laisse tourner une semaine, puis je monte.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Le always compte : sans lui, l'en-tête disparaît sur les réponses d'erreur.