ScreenshotNeo

BlogGuides

Guide de sécurité et de durcissement du serveur web NGINX

Configurez TLS, les accès, les méthodes, les limites de requêtes et les hôtes NGINX avec une méthode vérifiable et réversible.

By the ScreenshotNeo team1 October 20269 min read

Le durcissement de NGINX consiste à réduire ce qui est exposé, chiffrer correctement les échanges, limiter les méthodes et les abus, contrôler les hôtes reçus et appliquer chaque changement avec une vérification et un retour arrière possibles. Il n’existe pas de fichier universel : les directives disponibles, leurs valeurs par défaut et les exigences de compatibilité dépendent de la version, des modules compilés, de la distribution et du rôle de NGINX.

Réponse courte : l’ordre de travail recommandé

  1. Relevez la version, les modules et le rôle de NGINX (frontal, proxy inverse ou terminaison TLS).
  2. Protégez les clés privées et configurez HTTPS selon les versions réellement supportées.
  3. Réduisez les informations divulguées et les méthodes HTTP aux besoins de l’application.
  4. Définissez explicitement le serveur par défaut et testez les noms d’hôte inconnus.
  5. Ajoutez une limitation de requêtes adaptée au trafic et à la chaîne de proxys.
  6. Validez la configuration, rechargez progressivement, observez les erreurs puis gardez un retour arrière.

1. Faire l’inventaire avant de modifier la configuration

Notez la version exacte, le paquet ou la méthode de compilation, les modules statiques et dynamiques chargés, les fichiers inclus et le chemin des journaux. Une directive peut être absente si le module correspondant n’a pas été compilé. La documentation de compilation explique que les modules peuvent être activés ou omis explicitement dans les options de construction NGINX.

nginx -v
nginx -V 2>&1
nginx -T > /tmp/nginx-effective.conf
ps -ef | grep '[n]ginx'

nginx -T permet d’examiner la configuration effectivement assemblée, y compris les fichiers inclus. Conservez cette sortie avec le changement. Si njs ou un autre module d’extension est utilisé, suivez aussi son historique officiel et vérifiez régulièrement les versions : une entrée du 2 septembre 2026 décrit par exemple un contournement de contrôle d’accès concernant js_access dans des versions affectées. Cela justifie une revue récurrente, sans permettre de conclure qu’une installation précise est vulnérable.

2. Configurer HTTPS et protéger les clés privées

La documentation NGINX indique que les valeurs par défaut documentées comprennent TLS 1.2 et TLS 1.3, ainsi que la suite HIGH:!aNULL:!MD5, mais précise que ces valeurs ont changé au fil du temps. Vérifiez donc la version installée et la compatibilité de vos clients avant de figer une politique. La clé privée est un secret : la documentation demande un accès restreint tout en la laissant lisible par le processus maître NGINX (configuration HTTPS officielle).

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

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

    # Fixez explicitement ces valeurs seulement après vérification
    # de la version et des clients à supporter.
    ssl_protocols TLSv1.2 TLSv1.3;

    root /var/www/example;
    index index.html;
}

Restreignez la clé au compte et au groupe nécessaires, sans la rendre illisible au processus maître. N’activez pas ssl_early_data par défaut : NGINX le documente comme désactivé, et les requêtes en early data peuvent être rejouées. Si vous l’envisagez, l’application doit traiter explicitement le risque de rejeu.

sudo chown root:root /etc/letsencrypt/live/example.com/privkey.pem
sudo chmod 600 /etc/letsencrypt/live/example.com/privkey.pem

Testez le certificat et la négociation depuis un poste autorisé :

curl -I https://example.com/
openssl s_client -connect example.com:443 -servername example.com -tls1_2 < /dev/null
openssl s_client -connect example.com:443 -servername example.com -tls1_3 < /dev/null

3. Réduire les informations divulguées

server_tokens contrôle la version NGINX affichée dans les pages d’erreur et l’en-tête Server (directive officielle). La masquer réduit un indice, mais ne remplace pas les mises à jour, l’isolation et le contrôle d’accès.

http {
    server_tokens off;
}

Vérifiez le résultat sur les réponses normales et les erreurs, car un proxy ou l’application peuvent encore ajouter leurs propres en-têtes.

curl -sS -D - -o /dev/null https://example.com/not-found

4. N’autoriser que les méthodes nécessaires

Une route publique de lecture n’a généralement pas besoin d’accepter toutes les méthodes. Utilisez limit_except dans le contexte de la route concernée, puis vérifiez les héritages avec la configuration effective.

location /public/ {
    limit_except GET HEAD {
        deny all;
    }
    try_files $uri =404;
}

Ne bloquez pas automatiquement OPTIONS, POST, PUT ou DELETE si votre application, CORS ou un webhook les exige. Testez chaque méthode explicitement :

for method in GET HEAD OPTIONS POST PUT DELETE; do
  printf '%s: ' "$method"
  curl -sS -o /dev/null -w '%{http_code}\n' -X "$method" https://example.com/public/
done

5. Ordonner correctement les règles allow et deny

Les règles allow et deny sont évaluées séquentiellement jusqu’à la première correspondance. L’ordre change donc le résultat (module d’accès officiel).

location /admin/ {
    allow 192.0.2.10;
    allow 2001:db8::10;
    deny all;
}

Placez les exceptions avant le refus général. Vérifiez IPv4 et IPv6, les réseaux de supervision et les adresses réellement vues par NGINX. Derrière un proxy, ne faites pas confiance à un en-tête d’adresse client sans avoir configuré et vérifié la chaîne de confiance appropriée.

6. Limiter les requêtes sans casser le trafic légitime

ngx_http_limit_req_module limite le traitement selon une clé et utilise un mécanisme de type seau percé (module officiel). L’exemple ci-dessous est un point de départ, pas un débit universel :

http {
    limit_req_zone $binary_remote_addr zone=per_ip:10m rate=5r/s;

    server {
        listen 443 ssl;
        server_name example.com;

        location /api/ {
            limit_req zone=per_ip burst=20 nodelay;
            proxy_pass http://app_backend;
        }
    }
}

Choisissez la clé selon votre architecture. Si un CDN ou un équilibreur masque l’adresse du client, confirmez quelle adresse NGINX reçoit avant de limiter. Mesurez les réponses 429, les latences et les rafales légitimes, puis ajustez rate, burst et nodelay. Une limite trop basse peut bloquer des clients valides ; une clé partagée par tous les utilisateurs peut transformer le contrôle en panne collective.

7. Définir un serveur par défaut pour les hôtes inconnus

NGINX choisit le serveur virtuel en examinant Host. Si aucun nom ne correspond, ou si l’en-tête est absent, la requête arrive au serveur par défaut du port. Désignez-le explicitement et choisissez un comportement adapté : refus, réponse minimale ou redirection contrôlée (traitement des requêtes officiel).

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

server {
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate     /etc/ssl/default/fullchain.pem;
    ssl_certificate_key /etc/ssl/default/privkey.pem;
    return 444;
}

Le serveur TLS par défaut doit tout de même disposer d’un certificat utilisable pour terminer la connexion. Testez un nom inconnu et l’absence de Host sur un environnement de préproduction :

curl -i --resolve unknown.example:443:203.0.113.10 https://unknown.example/
curl -i --http1.1 https://203.0.113.10/ -H 'Host:'

8. Valider, recharger et prévoir un retour arrière

La page de contrôle NGINX décrit le rechargement par signal HUP : NGINX relit la configuration, démarre de nouveaux workers et arrête progressivement les anciens (contrôle officiel). Validez d’abord avec la commande fournie par votre binaire ou paquet :

sudo nginx -t
sudo nginx -s reload
# Variante fréquente avec systemd :
sudo systemctl reload nginx

La commande exacte peut varier selon la distribution. Gardez l’ancienne configuration, vérifiez les journaux et les sondes après le rechargement, puis restaurez-la et rechargez si une erreur apparaît.

Liste de contrôle avant production

  • Version et modules inventoriés ; correctifs suivis.
  • Certificat, chaîne et clé privée vérifiés ; permissions restreintes.
  • Protocoles TLS choisis après contrôle de compatibilité.
  • server_tokens évalué ; les en-têtes de l’application aussi.
  • Méthodes minimales par route, avec CORS et webhooks testés.
  • Règles allow/deny relues dans l’ordre effectif.
  • Clé et seuils de limitation validés avec l’architecture de proxy.
  • Serveur par défaut testé avec Host inconnu et Host absent.
  • Configuration testée, rechargement observé et retour arrière préparé.

Erreurs fréquentes et dépannage

Symptôme Cause probable Correction
nginx: [emerg] unknown directive Module absent ou directive non supportée par la version. Vérifiez nginx -V, la documentation de votre version et le paquet installé.
Le rechargement échoue Erreur de syntaxe, certificat illisible ou fichier inclus manquant. Lancez nginx -t, corrigez puis rechargez ; ne remplacez pas la configuration active à l’aveugle.
Les clients ne peuvent plus se connecter Politique TLS trop stricte pour ces clients. Identifiez les clients concernés et ajustez selon une exigence de compatibilité documentée.
La clé privée est refusée Permissions trop larges ou, inversement, clé illisible par le master NGINX. Restaurez un propriétaire, un groupe et des permissions restreints permettant la lecture au processus maître.
Des utilisateurs légitimes reçoivent 403 Un deny all précède une exception ou l’adresse observée n’est pas celle attendue. Relisez l’ordre des règles et l’adresse réellement vue par NGINX.
Des utilisateurs reçoivent 429 Débit ou clé de limitation inadaptés, souvent derrière un proxy. Mesurez les rafales, confirmez la chaîne d’adresses et ajustez rate/burst.
Un mauvais site répond Nom absent du server_name ou serveur par défaut implicite. Définissez default_server et testez les Host inconnus.

Performance, fiabilité et coût opérationnel

Chaque contrôle ajoute un coût à mesurer : limitation et journalisation consomment des ressources, une politique TLS stricte peut exclure des clients, et le chargement d’éléments complets augmente le travail du serveur applicatif. Commencez par les routes sensibles, observez les taux d’erreur et la latence, puis généralisez. Les rechargements NGINX sont conçus pour lancer de nouveaux workers et arrêter progressivement les anciens, mais votre supervision doit confirmer que les workers, certificats, upstreams et journaux restent sains.

Le durcissement ne corrige pas une application vulnérable, une dépendance obsolète ou un réseau mal segmenté. Associez ces réglages à des mises à jour, des sauvegardes de configuration, une gestion des secrets, des contrôles d’accès système et des tests depuis l’extérieur.

Or skip the browser setup

Si vous devez documenter ou surveiller l’apparence publique de votre serveur après ces changements, ScreenshotNeo fournit une capture par une seule requête GET. Consultez la documentation de l’API pour les options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Les bannières de consentement, fenêtres d’inscription et widgets de chat sont retirés avant la capture. Les contrôles anti-bot, pages blanches, échecs de chargement et résultats en cache ne sont pas facturés ; les en-têtes X-Page-Verdict et X-Billed indiquent le résultat. Le serveur MCP permet à Claude, Cursor et aux autres clients MCP d’utiliser take_screenshot, get_page_info et capture_pdf. Le forfait gratuit comprend 1 000 captures par mois sans carte ; les forfaits payants commencent à 5 $ pour 3 000 captures. Créer un compte gratuit ScreenshotNeo.

FAQ

Dois-je copier un fichier de durcissement complet ?

Non. Utilisez les contrôles pertinents pour votre version, vos modules et votre application, puis validez chaque changement.

Masquer la version NGINX suffit-il ?

Non. server_tokens off réduit une information divulguée ; les mises à jour et l’isolation restent nécessaires.

Quelle limite de requêtes choisir ?

Mesurez le trafic légitime, les rafales et l’adresse réellement reçue derrière vos proxys. Les valeurs de l’exemple sont seulement un point de départ.

Pourquoi un hôte inconnu reçoit-il mon application ?

Parce que NGINX utilise le serveur par défaut du port quand aucun server_name ne correspond. Définissez et testez un serveur par défaut explicite.