Bonnes pratiques de sécurité Nginx : Protégez votre serveur web

Protégez votre serveur web Nginx grâce à des bonnes pratiques de sécurité essentielles. Ce guide couvre la sécurisation des connexions SSL/TLS, la mise en œuvre d'une limitation de débit efficace pour prévenir les abus, l'atténuation des attaques web courantes comme le XSS et l'injection SQL, ainsi que l'importance cruciale de maintenir Nginx à jour. Découvrez des étapes concrètes et des exemples de configuration pour renforcer la sécurité de votre serveur et protéger votre présence en ligne.

Meilleures pratiques de sécurité Nginx : Protégez votre serveur web

Votre serveur Nginx est souvent le premier service public que les utilisateurs et les attaquants peuvent atteindre. Ces meilleures pratiques de sécurité Nginx se concentrent sur les contrôles que Nginx peut réellement appliquer : TLS, limites de requêtes, en-têtes, règles d'accès, paramètres par défaut plus sûrs et mises à jour régulières.

Nginx ne peut pas corriger à lui seul un code d'application vulnérable. Traitez-le comme une couche devant votre application, votre base de données, votre système d'authentification et votre pare-feu hôte.

Sécurisez les connexions avec TLS

TLS chiffre le trafic entre le navigateur et votre serveur. Utilisez un certificat de confiance, redirigez HTTP vers HTTPS et désactivez les versions de protocole obsolètes.

Obtenez un certificat

Let's Encrypt est courant pour les sites web publics, mais toute autorité de certification de confiance peut fonctionner. Sur de nombreux serveurs Linux, Certbot stocke les fichiers sous /etc/letsencrypt/live/votre_domaine.com/.

Configurez HTTPS

Modifiez le bloc serveur pour votre domaine. Le chemin est souvent /etc/nginx/sites-available/ sur Debian/Ubuntu ou /etc/nginx/conf.d/ sur les systèmes de type RHEL.

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name votre_domaine.com www.votre_domaine.com;

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

    # Incluez vos paramètres TLS partagés
    include /etc/nginx/snippets/ssl-params.conf;

    # ... autres configurations (racine, blocs d'emplacement, etc.)
}

server {
    listen 80;
    listen [::]:80;
    server_name votre_domaine.com www.votre_domaine.com;

    # Redirigez HTTP vers HTTPS
    return 301 https://$host$request_uri;
}

Utilisez des paramètres TLS prudents

Vous pouvez conserver les paramètres TLS partagés dans un snippet tel que /etc/nginx/snippets/ssl-params.conf.

# /etc/nginx/snippets/ssl-params.conf

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# Activez HSTS (HTTP Strict Transport Security)
# Ajoutez includeSubDomains si applicable
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

# Activez l'OCSP Stapling pour des vérifications de certificat plus rapides
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# Paramètres Diffie-Hellman (générez-en un fort si nécessaire)
# ssl_dhparam /etc/nginx/ssl/dhparams.pem;

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;

N'ajoutez includeSubDomains ou preload à HSTS qu'après avoir vérifié que chaque sous-domaine prend en charge HTTPS. Un mauvais déploiement de HSTS peut bloquer les utilisateurs sur d'anciens sous-domaines.

Implémentez la limitation de débit

La limitation de débit aide à ralentir les tentatives de force brute, le scraping et les inondations accidentelles de requêtes. Ce n'est pas une solution DDoS complète, mais cela donne plus de marge à votre application.

Exemple de limitation de débit de base

limit_req_zone définit un état partagé, et limit_req applique la limite à un emplacement.

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

    server {
        # ...

        location /login {
            limit_req zone=malimite burst=10 nodelay;
            # ... votre configuration du gestionnaire de connexion
        }

        location / {
            limit_req zone=malimite burst=20 nodelay;
            # ... votre configuration du site principal
        }
    }
}

Dans cet exemple : $binary_remote_addr indexe la limite par adresse IP du client. burst=10 permet une courte rafale au-dessus du débit moyen, et nodelay rejette les requêtes excessives au lieu de les retarder.

Soyez prudent derrière un équilibreur de charge ou un CDN. Si Nginx ne voit que l'adresse IP du proxy, la limitation de débit par $binary_remote_addr peut pénaliser tous les utilisateurs comme un seul client. Configurez la gestion des adresses IP de confiance avant de vous fier aux limites par client.

Réduisez la surface d'attaque courante

Nginx peut réduire l'exposition, mais votre application a toujours besoin de validation des entrées, d'encodage des sorties, de SQL paramétré, de contrôles d'authentification et de correctifs de dépendances.

Ajoutez des en-têtes de sécurité

Les en-têtes de sécurité peuvent réduire les risques côté navigateur :

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Une politique de sécurité de contenu peut aider contre XSS, mais elle doit correspondre aux scripts, styles, images et services tiers de votre application. Commencez en mode rapport uniquement avant de l'appliquer sur un site de production.

Bloquez les scanners évidents avec précaution

Des blocages de motifs simples peuvent arrêter les scanners bruyants, mais ils ne remplacent pas un WAF. Gardez-les étroits pour ne pas bloquer les utilisateurs légitimes.

http {
    # Définissez une map pour bloquer les mauvais bots/scanners
    map $http_user_agent $mauvais_bot {
        default 0;
        "~*motif_malveillant_bot" 1;
        "~*autre_agent_suspect" 1;
    }

    server {
        # ...
        if ($mauvais_bot) {
            return 403;
        }
        # ...
    }
}

Restreignez les chemins sensibles

Utilisez try_files, gardez autoindex désactivé sauf si vous avez besoin de listes de répertoires, et refusez l'accès aux fichiers cachés qui ne devraient jamais être servis.

location / {
    root /var/www/html;
    index index.html index.htm;
    try_files $uri $uri/ =404;
    autoindex off; # Désactivez la liste des répertoires
}

# Exemple de restriction d'accès aux fichiers sensibles
location ~ /\.ht {
    deny all;
}

Cachez la version de Nginx

server_tokens off supprime la version de Nginx des pages d'erreur générées et réduit les détails dans l'en-tête de réponse Server.

http {
    server_tokens off;
    # ...
}

Limitez les méthodes HTTP là où c'est approprié

Si un point de terminaison n'accepte que GET et POST, rejetez les autres méthodes à cet endroit. Faites-le par emplacement pour ne pas casser les requêtes CORS preflight ou les points de terminaison API qui utilisent légitimement PUT, PATCH ou DELETE.

location /api/ {
    # Autorisez uniquement GET et POST
    if ($request_method !~ ^(GET|POST)$) {
        return 405;
    }
    # ...
}

Maintenez Nginx à jour

Les correctifs de sécurité arrivent souvent via le référentiel de paquets de votre distribution Linux. Gardez Nginx et les paquets liés à OpenSSL corrigés, et testez les rechargements après les mises à jour.

Pour Debian/Ubuntu :

sudo apt update
sudo apt upgrade nginx

Pour CentOS/RHEL :

sudo dnf update nginx

Utilisez yum update nginx sur les anciennes versions de RHEL/CentOS qui utilisent encore yum.

Ajoutez une protection au niveau de l'hôte

La sécurité de Nginx dépend également de l'hôte qui l'entoure :

  • Autorisez uniquement les ports nécessaires dans ufw, firewalld, les groupes de sécurité cloud ou les ACL réseau.
  • Surveillez /var/log/nginx/access.log et /var/log/nginx/error.log pour les pics, les réponses 401/403 répétées et les chemins suspects.
  • Utilisez Fail2ban ou un outil similaire lorsque les motifs de journal peuvent identifier les clients abusifs.
  • Exécutez sudo nginx -t avant chaque rechargement pour qu'un changement de sécurité ne mette pas le site hors ligne.

À retenir

Commencez par HTTPS, les mises à jour, les ports restreints, les en-têtes sécurisés et les limites de débit sur les chemins sensibles comme /login. Ensuite, examinez régulièrement vos journaux. La plupart des gains de sécurité de Nginx proviennent d'une maintenance régulière et d'une configuration claire, et non d'un gros fichier de durcissement copié depuis un autre site.