Mettre en place un serveur WebNginx : Se protéger des attaques Flood

Télécharger la vidéo

Pour débuter
Outils de base
VIM
06 min
SSH
14 min
rsync
20 min
Shell fish
13 min
Serveur HTTP
Apache
40 min
Nginx
30 min
PHP
NodeJS
Base de données
MySQL
15 min
Redis
08 min
Emails
HTTPS
FTP
ProFTPD
14 min
Sécurité
Pour le confort
Déploiement

Nous allons découvrir aujourd'hui comment se protéger des attaques par flood (non distribuées) avec nginx et fail2ban. Le principe de cette attaque est relativement simple et consiste à surcharger un serveur de demandes afin de la rendre lent ou indisponible. Pour s'en protéger il faut être capable de détecter un nombre de requêtes anormalement rapproché provenant d'une même IP.

Nginx, le module ngx_http_limit_req_module

nginx possède un module (préinstallé depuis la version 0.7.21) qui permet de mettre en place une limite sur le taux de traitement des requêtes.

Pour définir une nouvelle limite on utilise la directive limit_req_zone

http {

    # ...

    # limit_req_zone key zone=name:size rate=rate;
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    # ...

}
  • key est la clef utilisée pour limiter la fréquence, on utilise ici l'adresse ip du client.
  • zone permet de donner un nom à notre limite et de définir l'espace alloué pour stocker les informations (avec 1Mo on peut sauvegarder 8000 "states" sur un système 64bits). Les "states" contiennent le nombre de requêtes dépassant la limitation par exemple.
  • rate, exprimé en requêtes par seconde (r/s) ou requêtes par minute (r/m), indique la limite de traitement par rapport à la clef donnée.

Une fois nos différentes zones définies il est possible de les utiliser dans la partie server de notre configuration à l'aide de la directive limit_req.

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server {

    # Vous pouvez l'écrire ici pour que la règle s'applique à tout votre serveur

    location ~ \.php$ {

        # ou seulement sur des pages à problèmes

        # limit_req zone=name [burst=number] [nodelay]
        limit_req zone=one burst=5;
    }

Cette directive permet de définir la zone mémoire à utiliser (définie via le limit_req_zone) ainsi que le débordement maximum autorisé (burst).

Si la fréquence des requêtes dépasse le taux défini par la zone, le traitement de ces-dernières est mis en attente afin de ne pas dépasser le taux de traitement. Les requêtes sont mises en attente jusqu'à dépasser la taille définie dans le burst. Dans le cas d'un dépassement, la requête est terminée avec un status 503. L'option nodelay, quant à elle, vous permet d'enlever ce processus de mise en attente des requêtes.

Les requêtes terminées par la mise en place de cette limitation seront sauvegardées dans les logs.

2016/01/12 19:11:58 [error] 6148#0: *68 limiting requests, excess: 1.102 by zone "one", client: 70.210.232.111, server: localdevserver.com, request: "GET /wp-login.php?loggedout=true HTTP/1.1", host: "localdevserver.com", referrer: "https://localdevserver.com/wp-login.php?loggedout=true"

Fail2ban, création d'une prison

Maintenant que l'on a mis en place cette limitation, on veut punir automatiquement les personnes qui essaieraient d'abuser de notre système. Nous allons pour cela créer un nouveau filtre sur fail2ban.

# /etc/fail2ban/filter.d/nginx-req-limit.conf

[Definition]
failregex = limiting requests, excess:.* by zone.*client: <HOST>
ignoreregex =

Avant de mettre en marche ce nouveau filtre vous pouvez le tester à l'aide de la commande

fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/nginx-req-limit.conf 

Une fois validé, vous pouvez ajouter ce filtre dans votre configuration fail2ban local

# /etc/fail2ban/jail.local (faites une copie de jail.conf si ce fichier n'existe pas)
[nginx-req-limit]
enabled = true
filter = nginx-req-limit
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = %(nginx_error_log}s
findtime = 600
bantime = 7200
maxretry = 10

Vous pouvez affiner ces paramètres suivant vos besoins

  • findtime définit l'intervalle de recherche du nombre d'occurence
  • maxretry définit le nombre de correspondances à obtenir pour déclencher l'action
  • bantime définit la durée du ban en secondes

Maintenant que votre filtre est enregistré vous pouvez activer votre configuration en relançant fail2ban

service fail2ban restart

Enfin, si vous voulez connaitre l'état de votre prison vous pouvez utiliser la commande

fail2ban-client status nginx-req-limit

Vous pouvez aussi analyser les logs de fail2ban

tail -f /var/log/fail2ban.log