Si vous aimez les articles et la gratuité d' Abyss Project, merci de faire un don par paypal pour nous financer icon wink class=


Soutenons La Quadrature du Net !

Bonjour à tous,

À la suite de l’article Compiler NGINX, pourquoi ? Comment ?, j’avais envie de vous faire un petit article sur ma recherche personnelle (pour l’instant aucun commit sur github) de la configuration parfaite pour NGINX qui permets de trouver le meilleur équilibre entre les performances et la sécurité (sans négliger l’un ou l’autre).

 

Je reprécise pour ceux qui lissent en diagonale, ce n’est (peut-être) pas la configuration parfaite, mais j’aimerais un coup de main pour que ça le devienne 🙂

 

Les besoins :

Avant tout, il faut comprendre mes besoins :

Le fichier de configuration nginx.conf doit fonctionner pour la dernière mainline de NGINX et OpenSSL 1.1.0 (ou la dernière version stable de OpenSSL).

Il est nécessaire d’avoir au minimum les résultats suivants sur différents tests en ligne :

 

Aussi, la configuration ne doit pas être destructrice ou trop restrictive.

Cela explique deux choses :

  • Premièrement, TLS 1.0 et 1.1 sont actifs.
  • Deuxièmement, Content-Security-Policy n’est pas dans son réglage le plus strict.

 

 

Détail de la configuration actuelle :

La dernière configuration en date est toujours disponible sur mon repo GitHub.

Pour information, je me base sur mon serveur Web qui dispose d’un Intel Xeon D-1531 avec 32Gb de RAM pour faire cette configuration, ce qui explique certaines valeurs assez élevées.

Faites jouer les divisions (ou les multiplications) pour adapter le bordel à votre serveur.

 

Le début du fichier :

On commence par déclarer l’utilisateur et le pid avec lesquels NGINX va se lancer.

En plus de cela on indique le nombre de processus de Nginx que l’on souhaite lancer en parallèle.

Idéalement, il en faut un ou deux par cœurs / thread.

user www-data;
worker_processes 12; # Number of CPU Cores
pid /run/nginx.pid;

 

La partie Events :

La première chose que l’on déclare ici, c’est les worker_connections.

C’est le nombre maximum de personnes que votre serveur NGINX peut servir en simultané. Pas de calcul miracle ici, ajustez le en fonction de vos tests de charges.

Multi_accept est activé ici pour pouvoir démarrer plusieurs nouvelles connexions en parallèle. Si vous n’activez pas ce paramètre, vous aurez vite un blocage.

Finalement, epoll est utilisé en tant que mécanisme d’entrée / sortie pour des performances améliorées lors des fortes charges.

events {
 worker_connections 16384;
 multi_accept on;
 use epoll;
}

 

Enfin, on défini la variable worker_rlimit_nofile, voyez ce post pour plus d’informations.

Pour faire simple :

# worker_rlimit_nofile = (worker_connections * 1) + 500
# worker_rlimit_nofile = (worker_connections * 2) + 500 si on utilise NGINX en tant que reverse proxy.

worker_rlimit_nofile 16884;

 

Les paramètres TLS :

On passe les paramètres basiques et on attaque directement la partie TLS.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
 ssl_session_timeout 1d;
 ssl_session_cache shared:SSL:50m;
 ssl_session_tickets off;
 ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305-D:ECDHE-RSA-CHACHA20-POLY1305-D:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384';
 ssl_prefer_server_ciphers on;

 

Comme indiqué précédemment, j’autorise tous les protocoles TLS pour une plus large compatibilité.

On utilise uniquement des courbes ECDH pour les échanges, a savoir : X25519, sect571r1, secp521r1 et secp384r1.

Cela nous permet d’être compatible avec beaucoup de monde tout en gardant le meilleur niveau de sécurité possible.

Le timeout des sessions est réglé sur une journée. Le cache entre toutes les sessions est lui réglé sur 50 minutes.

On désactive les tickets de sessions ssl car ce n’est pas sécurisé. Voir ce post pour plus d’informations.

 

Enfin, on liste spécifiquement tous les chippers que l’on autorise et on force le client a utilisé les préférences du serveur.

 

Les paramètres d’header :

Ah les headers, l’une des choses les plus importantes pour la sécurité d’un serveur web qui est bien trop souvent complètement oublié au bénéfice des paramètres de caches ou des paramètres d’échange TLS.

Dans un premier temps, on va désactiver toutes les informations renvoyées par NGINX pour que votre numéro de version ne soit pas renvoyé en clair.

server_tokens off;

 

Ensuite, on va régler tous les headers nécessaires pour la sécurité de vos visiteurs de vos sites.

Dans un premier temps, on active HSTS avec les paramètres recommandés :

 add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";

 

Ensuite, on autorise uniquement les Iframes provenant du même domaine :

 add_header X-Frame-Options "SAMEORIGIN" always;

 

Ensuite, on configure CSP pour autoriser uniquement les contenus externes en HTTS :

 add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always;

 

On active la protection contre les attaques Xss et MIME :

add_header X-Xss-Protection "1; mode=block" always;
 add_header X-Content-Type-Options "nosniff" always;

 

Pour finir, vous devez aussi activer la validation OCSP pour vos certificats en suivant ce tutoriel.

 ssl_stapling on;
 ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/private/ocsp-certs.pem
 resolver 8.8.4.4 8.8.8.8 valid=300s;
 resolver_timeout 5s;

 

Les paramètres des logs :

Ici on désactive simplement les access logs pour la performance. On garde uniquement les erreurs :

access_log off;
 error_log /var/log/nginx/error.log;

 

Les paramètres GZIP :

Rien de bien nouveau ni de transcendant ici, on règle simplement le niveau de compression sur 6 en indiquant les types de fichiers que l’on compresse.

gzip on;
 gzip_disable "msie6";
 gzip_vary on;
 gzip_proxied any;
 gzip_comp_level 6;
 gzip_buffers 16 8k;
 gzip_http_version 1.1;
 gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

 

Les paramètres de caches et de performances :

On active d’abord sommairement les Threads AIO pour de gros gains de performances. Pour plus d’informations, lisez le post de Nginx.

 aio threads;

 

Ensuite, on active une mitigation très basique contre les attaques par déni de service. Pour plus d’informations, regardez mon article de l’époque.

 ##Max c/s by ip
 limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m;
 limit_conn limit_per_ip 40;

##Max rq/s by ip
 limit_req_zone $binary_remote_addr zone=allips:10m rate=400r/s;
 limit_req zone=allips burst=400 nodelay;

 

On définit tous les paramètres de cache pour tout ce que l’on n’a pas vu avant.

Pas de recette miracle, il faut potasser le wiki de nginx et faire du bench. Voici ce que j’utilise moi.

#PHP
 fastcgi_buffers 256 32k;
 fastcgi_buffer_size 256k;
 fastcgi_connect_timeout 4s;
 fastcgi_send_timeout 120s;
 fastcgi_read_timeout 120s;
 fastcgi_busy_buffers_size 512k;
 fastcgi_temp_file_write_size 512K;
 reset_timedout_connection on;

#Others
 open_file_cache max=2000 inactive=20s;
 open_file_cache_valid 60s;
 open_file_cache_min_uses 5;
 open_file_cache_errors off;

client_max_body_size 50M;
 client_body_buffer_size 1m;
 client_body_timeout 15;
 client_header_timeout 15;
 keepalive_timeout 65;
 send_timeout 15;
 sendfile on;
 tcp_nopush on;
 tcp_nodelay on;

 

Vous l’aurez compris, pas de miracle, mais beaucoup de doc potassée pendant plusieurs années d’utilisation de NGINX.

Si des gens veulent contribuer et apporter leurs lignes de configurations à l’édifice, il faut aller sur le github : https://github.com/stylersnico/nginx-secure-config/

 

Le fichier de configuration a jour est toujours disponible ici : https://github.com/stylersnico/nginx-secure-config/blob/master/nginx.conf

 

Vous aurez besoin d’une version custom de nginx pour utiliser ce fichier de configuration. J’en ai parlé dans le dernier article.

 

Bonne journée 🙂