Fail2ban – Bloquer les requêtes Apache ^null$

Par le dans . Marqué comme , , , , , avec 10 Commentaires

Fail2ban – Bloquer les requêtes Apache ^null$

— Article mis à jour le 22/11/2012 —

Aujourd’hui je partage avec vous un petit billet « un peu » technique concernant Fail2ban. Si vous lisez assidûment le blog, vous avez déjà appris par cœur l’article vous permettant d’installer et de configurer proprement Fail2ban sur un serveur Debian …

COMMENT ÇA NON ?! Si ce n’est pas encore fait, c’est par ici que cela se passe : Protéger son serveur avec Fail2ban

Et pour les moins assidus d’entre vous, interrogation écrite dans une heure, vous êtes prévenus !!

Bon trêve de plaisanteries, j’écris aujourd’hui à propos de Fail2ban car je suis embêté depuis plusieurs semaines par des vilaines requêtes Apache qui {spamment|surchargent} mon serveur. Je ne sais pas vraiment d’où viennent ces requêtes car j’ai lu de tout et de rien à leur sujet sur la Toile (bots malveillants, scripts kiddies, requêtes normales pour plusieurs navigateurs, requêtes anormales suite à un problème pour certains navigateurs …).

Quoi qu’il en soit, les rapports générés quotidiennement par Logwatch (un analyseur de logs, j’en parlerai sûrement dans un prochain billet si cela vous tente) en sont remplis, il fallait donc bien faire quelque chose non ?!

Voici ce que me retourne ces fameux rapports Logwatch :

Attempts to use known hacks by 12 hosts were logged 48 time(s) from:
    88.168.XXX.55: 12 Time(s)
       ^null$ 12 Time(s)
    149.XXX.63.13: 6 Time(s)
       ^null$ 6 Time(s)
    90.10.24.XXX: 6 Time(s)
       ^null$ 6 Time(s)
    XXX.21.109.225: 4 Time(s)
       ^null$ 4 Time(s)
    84.XXX.62.203: 4 Time(s)
       ^null$ 4 Time(s)
    85.14.XXX.21: 4 Time(s)
       ^null$ 4 Time(s)
    123.125.71.XXX: 2 Time(s)
       ^null$ 2 Time(s)
    124.168.XXX.6: 2 Time(s)
       ^null$ 2 Time(s)
    2.XXX.145.136: 2 Time(s)
       ^null$ 2 Time(s)
    78.193.XXX.84: 2 Time(s)
       ^null$ 2 Time(s)
    80.248.71.XXX: 2 Time(s)
       ^null$ 2 Time(s)
    XXX.64.21.134: 2 Time(s)
       ^null$ 2 Time(s)

 A total of 12 sites probed the server

Hacks ou pas, je me suis donc mis à la recherche des ces fameuses requêtes dans mes fichiers de logs Apache et après quelques minutes voilà ce que j’ai fini par trouver :

90.10.24.XXX - - [19/Oct/2012:08:34:22 +0200] "-" 408 0 "-" "-"
90.10.24.XXX - - [19/Oct/2012:08:34:22 +0200] "-" 408 0 "-" "-"
90.10.24.XXX - - [19/Oct/2012:08:34:22 +0200] "-" 408 0 "-" "-"
90.10.24.XXX - - [19/Oct/2012:08:34:22 +0200] "-" 408 0 "-" "-"
90.10.24.XXX - - [19/Oct/2012:08:34:23 +0200] "-" 408 0 "-" "-"
90.10.24.XXX - - [19/Oct/2012:08:34:23 +0200] "-" 408 0 "-" "-"

Après une petite recherche sur la Toile, voilà ce que signifie le code erreur 408 :

408 – Request Time-out – Temps d’attente d’une réponse du serveur écoulé

Comme vous pouvez le voir, malveillantes ou non, ces requêtes posent problèmes et surchargent le serveur Web inutilement. J’ai donc eu l’idée de m’en débarraser une bonne fois pour toute en utilisant Fail2ban.

Après avoir cherché en vain un filtre Fail2ban prêt à l’utilisation ET prenant en compte ce type de requêtes sur le Net, je me suis décidé à créer le filtre moi-même … (j’ai de ces idées parfois -_-‘)

Comment créer un nouveau filtre Fail2ban :

Allons-y, je vais dans cette partie du billet, décrire étape par étape les différentes manipulations à réaliser pour la création d’un nouveau filtre Fail2ban (pour information, ces manipulations ont été réalisées sous Debian 6.0.6).

Avant toute chose, sécurité oblige, nous allons faire une sauvegarde de notre fichier de configuration Fail2ban avant d’intervenir sur son contenu. On est jamais trop prudent et faire une fausse manipulation arrive vite … trop vite.

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.save

Création d’un nouveau filtre Fail2ban :

Nous allons ensuite créer un nouveau filtre que Fail2ban prendra en compte pour le blocage de ces fameuses requêtes.

Pour cela, il vous faudra vous rendre dans le répertoire stockant les différents filtre de Fail2ban :

cd /etc/fail2ban/filter.d/

Nous allons ensuite créer un nouveau filtre dans ce répertoire :

touch apache-null.conf

J’ai personnellement appelé ce filtre apache-null.conf en fonction des traces que j’ai observées dans les rapports de Logwatch, mais vous pouvez appeler votre filtre comme bon vous semble, il faudra par contre reporter convenablement le bon nom de fichier dans la jail (prison) que nous ajouterons ensuite au fichier de configuration de Fail2ban.

Éditez le nouveau filtre avec votre éditeur de texte préféré et ajoutez-y les lignes suivantes :

#
# Auteur : Joël LE CORRE - Sublimigeek -
# Créé le : 18/10/2012 - Modifié le : 21/10/2012
#

#############################################################################
# Fichier de configuration Fail2ban                                         #
# Jail permettant de blacklister les adresses IP des machines scannant      #
# le serveur Web Apache2 via les requêtes "^null$"                          #
#############################################################################

[Definition]
# Format de la requête à bloquer avec Fail2ban
# XX.XX.XX.XX - - [19/Oct/2012:08:34:23 +0200] "-" 408 0 "-" "-"

# Regex parsant les logs du serveur
failregex = ^<HOST> - - (.*) "-" 408 0 "-" "-"

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
ignoreregex =

Enregistrez ensuite les modifications. J’ai tout simplement écrit une expression régulière capable de retrouver toutes les lignes présentes dans les fichiers de logs de mon serveur ayant la forme suivante : ADRESSE_IP - - [19/Oct/2012:08:34:23 +0200] "-" 408 0 "-" "-".

Ce sera tout en ce qui concerne le filtre. Il ne nous reste plus qu’à l’ajouter dans la configuration de fail2ban, chose que nous allons faire tout de suite :)

Ajouter un filtre à Fail2ban :

Hop, nous allons maintenant préciser à Fail2ban qu’un nouveau filtre doit être pris en compte pour les prochains blocages d’adresses IP.

Pour cela, nous allons éditer le fichier jail.conf (pensez à faire un backup du fichier avant) :

vi /etc/fail2ban/jail.conf

Et nous allons ajouter les lignes suivantes à notre fichier :

#
# Sublimigeek - Protection contre les requêtes ^null$ sur le serveur Web Apache2
#
[apache-null]
enabled  = true
port = http,https
filter   = apache-null
banaction = iptables-multiport
logpath  = /var/log/apache*/*access.log
bantime  = 600
maxretry = 3

Vous pouvez bien entendu ajuster les différentes valeurs selon vos besoins.

Tester son nouveau filtre :

Avant de redémarrer Fail2ban pour que les modifications que nous venons de faire soient prises en compte définitivement, nous allons réaliser quelques tests fonctionnels :)

Il existe pour cela la commande fail2ban-regex qui prend en compte deux paramètres :

  • Le premier paramètre est le fichier de logs que l’on souhaite analyser
  • Le second paramètre est le filtre que l’on souhaite utiliser pour réaliser le test

Voici la forme de la commande à exécuter :

fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/apache-null.conf

Et voici la forme des résultats que la commande vous retournera :

En cas de retours positifs :

/usr/share/fail2ban/server/filter.py:442: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5

Running tests
=============
Use regex file : /etc/fail2ban/filter.d/apache-null.conf
Use log file   : /var/log/apache2/access.log

Results
=======
Failregex
|- Regular expressions:
|  [1] ^<host> - - (.*) "-" 408 0 "-" "-"
|
`- Number of matches:
   [1] 230 match(es)

Ignoreregex
|- Regular expressions:
|
`- Number of matches:

Summary
=======

Addresses found:
[1]
    84.XXX.22.43 (Sun Oct 14 17:26:03 2012)
    [...]
    109.130.XXX.83 (Sat Oct 20 17:40:29 2012)

Date template hits:
0 hit(s): MONTH Day Hour:Minute:Second
0 hit(s): WEEKDAY MONTH Day Hour:Minute:Second Year
0 hit(s): WEEKDAY MONTH Day Hour:Minute:Second
0 hit(s): Year/Month/Day Hour:Minute:Second
0 hit(s): Day/Month/Year Hour:Minute:Second
0 hit(s): Day/Month/Year Hour:Minute:Second
10856 hit(s): Day/MONTH/Year:Hour:Minute:Second
0 hit(s): Month/Day/Year:Hour:Minute:Second
0 hit(s): Year-Month-Day Hour:Minute:Second
0 hit(s): Day-MONTH-Year Hour:Minute:Second[.Millisecond]
0 hit(s): Day-Month-Year Hour:Minute:Second
0 hit(s): TAI64N
0 hit(s): Epoch
0 hit(s): ISO 8601
0 hit(s): Hour:Minute:Second
0 hit(s): <month/Day/Year@Hour:Minute:Second>

Success, the total number of match is 230

However, look at the above section 'Running tests' which could contain important
information.

En cas de retours négatifs :

/usr/share/fail2ban/server/filter.py:442: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5

Running tests
=============
Use regex file : /etc/fail2ban/filter.d/apache-null.conf
Use log file   : /var/log/apache2/sublimigeek.fr-access.log

Results
=======
Failregex
|- Regular expressions:
|  [1] ^<host> - - (.*) "-" 408 0 "-" "-"
|
`- Number of matches:
   [1] 0 match(es)

Ignoreregex
|- Regular expressions:
|
`- Number of matches:

Summary
=======
Sorry, no match

Look at the above section 'Running tests' which could contain important
information.

Nous pouvons également vérifier si une recherche manuelle retourne le même nombre d’occurrences d’apparitions de la requête ^null$ dans nos logs :

cat /var/log/apache*/access.log | grep -i '"-" 408 0 "-" "-"' | wc -l
<<< 230 >>>

Nous obtenons bien 230 lignes présentes dans les logs d’Apache2 où cette fameuse requête apparaît. Ce nombre de lignes est identique au résultat renvoyé par Fail2ban, notre filtre est donc fonctionnel :)

Ultimes manipulations :

Notre filtre étant fonctionnel, il ne nous reste plus qu’à redémarrer fail2ban avec la commande suivante :

/etc/init.d/fail2ban stop

Puis la commande suivante :

/etc/init.d/fail2ban start

Vous allez recevoir pas mal de courriels de la part de Fail2ban vous précisant que les différentes jails actives dans votre configuration ont été stoppées puis redémarrées.
Ces messages ne sont pas importants, vous pouvez donc les supprimer sans problème.

Pour information, je n’ai pas fait un restart de Fail2ban, car il est parfois capricieux et ne réactive pas la totalité des jails présentes dans le fichier de configuration.

Une dernière chose à faire, vérifier que les filtres Fail2ban soient bien pris en compte par IPTABLES sur votre serveur :

iptables -nL

Cette commande listera l’ensemble des règles chargées dans la configuration d’iptables qui est le firewall de votre serveur.

Voici un extrait du résultat retourné par mon serveur, je n’ai gardé que les résultats concernant Apache :

fail2ban-apache-overflows  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443 
fail2ban-apache-bloquescan  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443 
fail2ban-apache-noscript  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443 
fail2ban-apache-null  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443
fail2ban-apache-badbots  tcp  --  0.0.0.0/0            0.0.0.0/0           
fail2ban-apache  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443 
fail2ban-apache-phpmyadmin  tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 80,443 
fail2ban-apache-w00tw00t  tcp  --  0.0.0.0/0            0.0.0.0/0

Pour vérifier si le filtre fonctionne comme vous le souhaitez, il ne vous restera plus qu’à vous armer de patience et à attendre les prochaines requêtes qui seront bannies.

Voici un exemple de courriel transmis par le serveur Fail2ban :

Hi,

The IP 125.205.219.23 has just been banned by Fail2Ban after
2 attempts against apache-null.

Here are more information about 125.XXX.219.23:

Lines containing IP:125.XXX.219.23 in /var/log/apache*/*access.log

/var/log/apache2/access.log:125.XXX.219.XXX - - [21/Oct/2012:07:03:00 +0200] "-" 408 0 "-" "-"
/var/log/apache2/access.log:125.XXX.219.XXX - - [21/Oct/2012:07:03:00 +0200] "-" 408 0 "-" "-"

Informations supplémentaires :

Ce billet décrit la mise en place d’un filtre pour Fail2ban bloquant les requêtes de la forme ^null$ et retournant une erreur 408 sur le serveur Web Apache2.

Les manipulations que je décris ici sont de la « pure expérimentation », donc si jamais vous découvrez une erreur dans ce que je détaille ici, n’hésitez pas à m’en faire part, j’éditerai le billet afin de le mettre à jour le plus rapidement possible.

De la même façon, si jamais vous pensez que votre adresse IP a été bannie sur mon serveur, n’hésitez pas à me contacter par courriel à l’adresse suivante : contact[at]sublimigeek.fr ou via Twitter, je ferai le nécessaire pour vous rendre l’accès au blog et j’étudierai le fonctionnement du filtre plus en détails afin de trouver l’origine de ce blocage.

Histoire de vous rassurer, ce filtre est en production depuis maintenant une bonne semaine sur le serveur hébergeant Sublimigeek et à ce jour, je n’ai pas observé d’effet de bord particulier ou de modification dans le fonctionnement de Fail2ban.

Dans tous les cas, si mon filtre s’avère inefficace et/ou buggé, les étapes que je décris dans ce billet restent valides ET permettent la création d’un nouveau filtre à ajouter dans la configuration de Fail2ban. Vous pourrez toujours vous en inspirer pour vos besoins personnels :)

Sources des images utilisées en illustrations :
– L’image utilisée comme illustration principale de ce billet a été trouvée et téléchargée depuis le portofolio de Salvatore Vuono sur le site FreedigitalPhotos.net, je l’ai ensuite adapté selon mes besoins pour ce billet.

10 Commentaires


  1. Can I make a suggestion:
    Replace:
    failregex = ^ – – (.*) « – » 408 0 « – » « – »

    with this:
    failregex = ^ – – (.*) « – » 408 (0|-) « – » « – »

    Thanks!

  2. Hello,

    J’espère que tu vas bien. Sysadmin dans le sang je constate 2 petits problèmes à la lecture de ton article :

    – Dans [apache-null] tu mets logpath = /var/log/apache*/access.log alors que c’est /var/log/apache*/*access.log sinon adios les scans de vhost.

    – Tu écris failregex = ^ – – (.*) « – » 408 0 « – » « – » mais la norme c’est en majuscule et c’est bizarre que fail2ban ne te couine pas dessus.

    j’aimerais que l’on se revoit un jour quand tu auras 5 min …. :(

    • Salut Nil la forme ?!

      Merci pour tes retours, c’est toujours bon à prendre :)

      Concernant le premier point, tu as en effet raison pour les scans des vhosts, c’est un oubli de ma part dans le billet vu que j’ai bien la double « * » dans ma conf Fail2ban qui prend en compte tous les fichiers de types xxxxxx-acces.log ^^
      Je mets donc à jour cette partie … et dire que je me suis relu 200000 fois avant de le publier pour éviter ce genre de boulette …

      En ce qui concerne le second point par contre, j’ai fait le tour de plusieurs fichiers de configuration présents dans le dossier filter.d et en effet la règle de la majuscule à l’air d’être prise en compte, mais en faisant un peu attention, on remarquera que dans les regex d’exemples, cette règle n’est pas respectée. J’en conclue donc (vu que ma jail est fonctionnelle) que Fail2ban ne fait pas attention à la case et que c’est pour cela qu’il ne retourne pas d’erreur.

      Dans le doute et vu qu’en général je suis assez pointilleux sur ce genre de chose (qui a dit que je suis maniaque ?), je modifie le tout pour respecter cette norme même si elle n’est pas réellement nécessaire.

      En tout cas, merci pour tes retours et pourquoi pas se (re)croiser un de ces jours. J’avais répondu à ton courriel la dernière fois, mais pas de retours de ta part depuis …

      @+

  3. Une envie de partager ;)

    Pour ma part j’utilise
    => ^(.*):80 – – (.*) « – » 408 0 « – » « – »

    car les infos sont stocker dans un log dans other_vhost

    • Salut Brandon,

      Merci pour ce partage !

      En effet, selon la configuration des logs que l’on paramètre dans les vhosts, il peut être utile de modifier un peu la règle Fail2ban pour qu’elle prenne en compte l’ensemble des logs Apache ou non un seul et unique nom de domaine (ou sous domaine ou autres …).

      @+

  4. Hello,
    Attention quand même avec cette règle..
    J’ai l’impression quand même que Google provoque des 408

    Je viens de voir via Google webmaster tools que depuis que j’ai appliqué cette règle le crawl des pages à baisser d’une manière impressionnante !

    • Salut,

      Merci pour ton retour, je vais consulter mes logs pour voir ce que cela donne de mon côté, mais jusqu’à maintenant, je n’ai pas remarqué de réactions louches de la part des bots de Google ^^
      Si jamais tu mets à jour la règle, n’hésites pas à la partager ici, je mettrais le billet à jour si utile ;)

      @+

  5. Pingback : Protéger vos services auto-hébergés avec Fail2ban | Sublimigeek | Geek, Astuces, High Tech et découvertes du Net

N'hésitez pas, laissez un commentaire — DoFollow activé sur ce site —


« »