Utiliser Fail2Ban pour bloquer un FLOOD HTTP

Hello,

Il existe plusieurs moyens d'attaquer un service Web, mais le plus courant reste de surcharger la machine. On peut le faire à trois niveaux : bande passante, connexions et requêtes "qui semblent réelles".

Le premier niveau est le pire, si vous êtes auto-hébergé (ou chez un vilain hébergeur qui ne tient pas la route) : votre bande passante est remplie de données inutiles et vous ne pouvez plus répondre aux requêtes légitimes. Pour le bloquer, il faut bloquer le trafic qui vient jusqu'à vous, ce qui est assez compliqué (nullroute).

Le second cas consiste tout simplement à ouvrir plein de connexions vers votre machine, sans pour autant effectuer d'opérations : la limite de connexions de votre serveur sera atteinte, et les nouvelles connexions seront mises en attente. La RAM peut aussi être un facteur limitant. En général, le CPU tolère la charge (sauf si vous avez un Intel Pentium 50).

Le troisième cas, celui qui nous intéresse aujourd'hui, correspond à l'ouverture de connexions et à la réalisation de requêtes simples, du point de vue du client. L'attaque est alors adaptée à votre application : on parle d'attaque Layer 7 (couche OSI).
Par exemple, récupérer la page d'accueil. En théorie, c'est simple à gérer : un cache côté applicatif et c'est très léger (encore faut-il que ce soit le cas !), mais vous oubliez un détail : votre serveur Web.

Et oui, il n'y a pas que votre application dans l'histoire, il y a aussi tout l'environnement qui l'entoure : si votre site est protégé par TLS, le client et le serveur doivent s'accorder sur une valeur commune à travers le TLS Handshake, et cette étape consomme beaucoup de CPU.

La principale conséquence de ce Handshake, c'est que même en bloquant l'attaque au niveau de nginx, votre machine souffrira. Même avec un Intel i7-4790K. Au contraire, et c'est assez paradoxal : plus votre machine peut supporter de requêtes, plus vous devez la protéger.

Voilà, assez de blabla, on peut commencer à s'amuser \o/


1. Installer Fail2Ban

Si vous avez un OS digne de ce nom et savez vous en servir, vous pouvez vous référer à ce tutoriel : Introduction à Fail2Ban.
Sinon, vous êtes un bricoleur du dimanche et vous savez vous servir de votre machine, donc vous n'avez pas besoin de mon aide.

2. Analyser l'attaque

Sortez vos outils, c'est ici que vous en aurez besoin !
La première chose à faire est d'attendre sagement une attaque HTTP FLOOD. Si vous préférez les interfaces "graphiques", je vous recommande ngxtop qui permet d'avoir une vision globale du trafic.
Second outil que je vous recommande, htop, qui saura vous hypnotiser avec ses graphiques.

Troisième et dernier outil : tail -f. Sa mission ? Vous afficher un flux continu d'un fichier, ici les journaux. Dans notre cas, on fera tail -f /var/log/nginx/access.log (ou n'importe quel fichier ;D) à la recherche des lignes de l'attaque.

Dans mon cas d'étude, l'attaque ressemble à ça :

50.62.76.200 - - [12/Mar/2016:20:19:44 +0100] "GET / HTTP/1.0" 403 169 "-" "WordPress/4.0.10; http://vitasys.com; verifying pingback from 23.239.64.15"  
54.148.219.170 - - [12/Mar/2016:20:19:44 +0100] "GET / HTTP/1.0" 403 169 "-" "WordPress/4.4.2; http://mpbb.crescendo.net; verifying pingback from 23.239.64.15"  
192.138.16.28 - - [12/Mar/2016:20:19:45 +0100] "GET / HTTP/1.0" 403 169 "-" "WordPress/3.0.3; http://twit.wave.net.ph"  
194.126.200.56 - - [12/Mar/2016:20:19:45 +0100] "GET / HTTP/1.0" 403 169 "-" "WordPress/4.1.10; http://observar.ch; verifying pingback from 23.239.64.15"  
64.207.158.188 - - [12/Mar/2016:20:19:45 +0100] "GET / HTTP/1.0" 403 169 "-" "WordPress/3.7.1; http://shifonkazan.ru"  

On remarque deux choses :

  • j'utilise nginx avec le format par défaut,
  • l'attaque touche uniquement / (avec HTTP/1.0, coucou PHP),
  • l'attaquant utilise un User-Agent qui commence par WordPress/ mais pas d'URL source (referrer).
  • je bloque déjà cette attaque au niveau nginx (code de retour 403)

Manque de bol, mon site n'intéresse pas les russes ni les chinois, et encore moins autant de personnes en même temps.
Super, on a un moyen de distinguer le traffic réel du traffic attaquant !

3. Fabrication de règles fail2ban

Fail2ban sépare sa configuration en trois parties, mais ça vous le savez déjà vu que vous avez lu mon Introduction à Fail2Ban !
Afin de bloquer cette attaque, en étant sévère et en bloquant les IP sur tous les ports, nous allons donc créer un Filtre et une Prison (Jail).

Le Filtre

Cette partie sera sans doute à adapter dans votre cas, si l'attaque ne ressemble pas à la mienne.
On place cette configuration dans le fichier /etc/fail2ban/filter.d/http-wordpress-dos.conf. Le nom du fichier est important, on en aura besoin pour la prison.

# Fail2Ban configuration file
[Definition]
failregex = ^<HOST> -.*403.*"WordPress/.*  
ignoreregex =  

Pas très compliqué, on définit une expression régulière qui filtre les "mauvaises lignes" et en extrait l'HOST.
Dans mon cas, je vérifie que le code de retour est 403 : j'évite ainsi les faux positifs (par exemple, si une page est appelée WordPress/que-faut-il-en-penser.html)

La Prison

Cette fois-ci, dans le fichier /etc/fail2ban/jail.d/http.conf :

[http-wordpress-dos]
enabled = true  
filter = http-wordpress-dos  
logpath = /var/log/nginx/access.log  
maxretry = 3  
findtime = 300  
bantime = 86400  
banaction = iptables-allports  
port = anyport  

Le nom du fichier n'a pas d'importance, mais le reste importe beaucoup.
Ici, je précise que j'utilise le filtre http-wordpress-dos (le nom du fichier précédent), que Fail2Ban doit lire le fichier /var/log/nginx/access.log et qu'il doit autoriser 3 essais avant de bannir les vilaines personnes.

Dans la mesure où Fail2Ban utilise inotify, il est informé en temps réel des modifications apportées au fichier : la vérification n'est pas effectuée toutes les 5 minutes, par exemple. Et dans le cas d'une attaque, 3 requêtes, ce n'est rien.
En somme, l'attaque pourra à peine effleurer votre serveur : vous serez touchés par 3 requêtes par IP source, qui seront ensuite bannies pour 24 heures ...


Voilà, vous savez comment analyser et bloquer une attaque. Maintenant, à vous de créer un contenu suffisamment intéressant pour vous faire attaquer ! :D

~> Partie 2, car les vilains n'abandonnent jamais