Protéger son serveur en utilisant Fail2Ban

Comme toutes les machines exposées au réseau Internet, mon serveur Web est continuellement la cible de tentatives d'attaques basiques de type brute force et DOS. J'avais déjà abordé le sujet sous la forme de billets tel que "Sécuriser son blog WordPress" ou "Détection des attaques DOS/DDOS avec Nagios". Nous allons aujourd'hui parler d'une solution de protection active se déclenchant automatiquement lors d'une de ces attaques: Fail2Ban.

Comment marche Fail2Ban ?

Développé en langage Python, Fail2Ban est un logiciel libre permettant d'analyser des fichiers de logs et de déclencher des actions si certaines choses suspectes sont détectées. La grande force de Fail2Ban est sa grande modularité que cela soit au niveau des mécanismes de détections basées sur les expressions régulières ou sur les actions à mener qui peuvent aller de l'expédition d'un mail à la mise en place de règles de Firewall.

Fail2Ban se base sur un système de prisons (jails) que l'on peut définir, activer ou désactiver dans un simple fichier de configuration (/etc/fail2ban/jail.conf).

Une prison (jail) est composée, entre autres, des éléments suivants:

  • Nom du fichier de log à analyser.
  • Filtre à appliquer sur ce fichier de log (la liste des filtres disponibles se trouve dans le répertoire /etc/fail2ban/filter.d). Il est bien sûr possible de créer ses propres filtres.
  • Paramètres permettant de définir si une action doit être déclenchée quand le filtre correspond ("match"): Nombre de "matchs" (maxretry), intervalle de temps correspondant (findtime)...
  • Action à mener si nécessaire. La liste des actions se trouve dans le répertoire /etc/fail2ban/action.d. Il est également possible de créer ses propres actions.

Installation de Fail2Ban

On commence par installer Fail2Ban sur son système. Il se trouve dans la grande majorité des distributions GNU/Linux et BSD. par exemple pour l'installer sur une machine Debian 6, il suffit de saisir la commande suivante (en root ou bien précédée d'un sudo):

Protection contre les attaques "brute force" SSH

Un exemple étant toujours plus parlant, nous allons configurer notre Fail2Ban pour bloquer automatiquement les adresses IP des machines essayant des attaques de type "brute force" sur notre port SSH (cette attaque est à la portée de n'importe quel "neuneu". On trouve de très bon tutoriaux sur le sujet sur le net).

Si une machine cliente échoue 3 fois de suite lors de la saisie du couple login/password sur le serveur SSH alors on bloque l'accès au port TCP/SSH pendant 15 minutes. On analyse pour cela le fichier de log /var/log/auth.log en lui appliquant le filtre /etc/fail2ban/filter.d/sshd.conf puis, si nécessaire, l'action /etc/fail2ban/action.d/iptables.conf. La définition de cette prison (jail) est à faire dans le fichier /etc/fail2ban/jail.conf:

Un fois le filtre activé en relançant Fail2Ban avec la commande (en root):

On peut rapidement voir son efficacité en regardant le fichier de log (par défaut sous /var/log/fail2ban.log):

Protection contre les attaques DOS (HTTP/GET)

Dans ce deuxième exemple nous allons voir comment lutter efficacement contre les attaques de type DOS ciblant vos serveurs Web. Ces attaques se caractérisent par un nombre inhabituel de requêtes HTTP venant d'un même client (du moins d'une même adresse IP source).

Le plus difficile est de trouver les bons paramètres correspondants à un comportement "inhabituel". Dans l'exemple suivant, je considère comme "inhabituel" le fait qu'un client effectue plus de 360 requêtes en 2 minutes (soit une moyenne de supérieurement à 3 req/sec) sur mon serveur Web. Dans ce cas, je bloque l'accès au port HTTP pendant une durée de 10 minutes.

La prison (jail) correspondante est la suivante (à ajouter dans votre fichier /etc/fail2ban/jail.conf):

En regardant de plus près cette prison, on remarque qu'elle utilise en entrée le fichier de log au format NCSA généré par le système de cache Varnish que j'utilise en frontal sur mes serveurs Web (/var/log/varnish/varnishncsa.log). Il est bien sûr possible d'utiliser directement le log de votre serveur Apache ou Nginx. Le filtre http-get-dos n'est pas fourni par défaut. Il faut donc éditer le fichier /etc/fail2ban/filter.d/http-get-dos.conf avec le contenu suivant:

Enfin, en cas de "match", on applique deux actions:

  1. blocage du port HTTP avec l'action iptables définie dans /etc/fail2ban/action.d/iptables.conf
  2. envoie d'un mail signalant le blocage avec l'action mail-whois-lines. L'adresse du mail est défini dans la variable destemail à modifier dans le fichier jail.conf.

Un fois le filtre activé:

On peut regarder le fichier de log (/var/log/fail2ban.log)...:

... et/ou attendre la réception des mails:

Conclusion

Ce billet est une simple introduction à l'utilisation de Fail2Ban qui peut être configuré de manière beaucoup plus personnalisé et en fonction de vous besoins. Si vous avez d'autres exemples d'utilisation, les commentaires ci-dessous sont fait pour cela !

  • http://www.abricocotier.fr/ Louis

    Ah merci pour ce tuto. J’avais installé Fail2Ban mais je ne l’utilisait que pour le SSH, et pas pour les attaques DOS sur le port 80. Je n’avais pas configuré l’envoi des mails non plus. Ce sera fait ce soir. Merci !

  • NmLs

    J’utilisais Fail2Ban avant, mais depuis je préfère OSSEC HIDS, bien plus complet et modulable selon moi :)
    Très bonne introduction de ce soft cependant !

    • JaShuGan

      +1

      J’utilise aussi OSSEC mais c’est vrai que fail2ban est plus simple à mettre en oeuvre.

  • Javamanxp

    Pour ce qui veulent bannir les personnes qui ont deja été banni et qui insiste, voici une astuce
    Créer un fichier filter fail2ban.conf dans /etc/fail2ban/filter.d

    # Filter Fail2Ban
    [Definition]
    failregex = fail2ban.actions: WARNING \[(.*)\] Ban
    ignoreregex = fail2ban.actions: WARNING \[fail2ban\] Ban
    # Fin Filter

    Coller le paragraphe ci-dessous dans /etc/fail2ban/jail.conf (A la fin, c’est mieux)

    [fail2ban]
    enabled = true
    filter = fail2ban
    action = iptables-allports[name=fail2ban]
    sendmail-whois[name=fail2ban]
    logpath = /var/log/fail2ban.log
    # findtime: 1 mois
    findtime = 2678400
    # bantime: 1 mois
    bantime = 2678400
    maxretry = 3

    Voila une personne qui a était bannie 3 fois en une période d’un mois, sera banni un mois.
    A vous de faire les réglages.
    @+

    • Maxime

      Sympa l’astuce…. je me posait justement la question de l’historique des ban :-)

  • Maxime

    Idéalement il faut définir les jails personnalisés dans /etc/fail2ban/jail.local afin d’éviter de perdre sa config lors d’un update.

    Pour Nginx, on peut également utiliser tel quel le filtre “apache-badbots.conf” sur le access.log de nginx
    ( j’ai juste ajouter le badbot “ZmEu” qui a tendance a squatter un peut trop souvent par chez moi.

    j’ai mis en place également le filtre ci-dessous pour essayer de contenir les parcours d’arbo et les tentatives d’executions de scripts php à l’aveugle.
    ( NOTE: la regex est peut être à améliorer, je l’ai mit en place il y a 3 jours seulement sur mon serveur ).

    ————–

    # 2012/02/20 04:37:02 [error] 20159#0: *3521 open() “/var/www/mysqladmin/scripts/setup.php” failed (2: No such file or directory), client: xxx.xxx.xxx.xxx, server: blabla.org, request: “GET /mysqladmin/scripts/setup.php HTTP/1.1″, host: “yyy.yyy.yyy.yyy”

    #
    [Definition]
    failregex = ^.*failed.*(No such file or directory).*client:.
    ignoreregex =

    ——–
    conf dans le jail.local :
    ——–

    [nginx-noscript]

    enabled = true
    port = http,https
    filter = nginx-noscript
    logpath = /var/log/nginx*/*error.log
    maxretry = 3

    • Maxime

      Arg.. a la fin de la regex, y a la balise ( sans les espaces) qui a sauté lors de l’ajout du commentaire.

  • http://toniob.net/ Toniob

    Pourquoi ne pas utiliser le rate-limiting d’iptables pour contrer les dos http ? Ça me semble tout de même vachement plus efficace que la lecture d’un log.

    • http://blog.info16.fr Bartounet

      Je regardait les option du rate limiting iptables, mais j’ai l’impression qu’il bloque si une limite à été atteinte, mais il bloque carrément l’accès entier au port non ?? on ne peut pas simplement bloquer une ip ??
      C’est embetant, tu va pas bloquer l’ensemble de tes clients quand une attaque dos est en train de se produire.

      • http://toniob.net/ Toniob

        Je te conseille le billet de l’excellent Stéphane Bortzmeyer : http://www.bortzmeyer.org/rate-limiting-dos.html .

        • http://blog.info16.fr Bartounet

          Oui je viens de voir ça autant pour moi..
          C’est très intéressant.
          Merci

      • http://simple.devue.org Alex Chauvin

        voir aussi haproxy pour le rate limiting mais également et surtout pouvoir travailler sur plusieurs frontaux web. J’utilise fail2ban devant haproxy également pour supprimer les clients recherchant des url comme /w00tw00t.at.ISC.SANS.DFind par exemple.

        Bon article pour démarrer, sera utile.

        Alex.

    • http://blog.m0le.net/ Nono

      HS: Merci, j’ai beaucoup ri quand j’ai lu ton apropos :) ( http://anthony.bourguignon.eu.org/apropos/ )

  • http://www.hackurx.info HacKurx

    Les filtres apache-admin, apache-404 et apache-w00tw00t sont également intéressant ;)

  • Pingback: Nicolargo : Protéger son serveur en utilisant Fail2Ban | Actualités de l'open source | Scoop.it

  • Pingback: Protéger son serveur en utilisant Fail2Ban | S-E-O | Scoop.it

  • Pingback: Protéger son serveur en utilisant Fail2Ban | Pierre-André Fontaine | Scoop.it

  • Pingback: Protéger son serveur en utilisant Fail2Ban | Developpement d'affaires - Pierre André Fontaine

  • Pingback: Protéger son serveur en utilisant Fail2Ban | business analyst | Scoop.it

  • http://blog.m0le.net/ Nono

    Très bon article (un peu comme d’habitude j’ai envie de dire).

    Pour me parer d’un ssh flood, je change le port du service SSH. J’ai BCP BCP BCP BCP moins d’essai de connexion :)

    Concernant l’envoie de mail, je comprend pas bien la syntaxe utilisé (et je n’arrive pas à la reproduire pour une autre filtre, peut-être pourrais-je obtenir d’autre explications ici ?

    En dernier lieu, parce que je pouvais pas m’en empêcher :

    Varnish, et les caches, s’évanouissent ? :D

  • http://id-libre.org/blogigor iGor

    Euh… Question de néophyte à peine lettré : si j’ai pas de auth.log dans /var/log (un apache sur une fedora), c’est normal ?

    • http://blog.m0le.net/ Nono

      /var/log/secure il me semble..

      • http://id-libre.org/blogigor iGor

        Ah ben oui, merci beaucoup !

  • haflinger

    bonjour,
    je suis sous Debian 6.0.4
    en installant fail2ban j’ai ces messages :
    # insserv: Starting fail2ban depends on iptables and therefore on system facility `$all’ which can not be true!
    [...]
    #insserv: There is a loop between service fail2ban and iptables if started

    En cherchant j’ai trouvé ces remarque sur un wiki :
    Things have changed in Debian Squeeze. Upgrading from etch or lenny to squeeze could cause any firewall.sh (or other) script to cause errors. This is due to the new dependency based boot in squeeze. Instead of using update-rc.d, you should use insserv firewall.sh Also, with dependency based boot with insserv LSB headers are required in all /etc/init.d/ scripts.
    Cela dépasse mes compétence, comment procéder et surtout comprendre ce changement ,
    merci d’avance

  • Pingback: Nono’s Vrac 46 « m0le'o'blog

  • http://blog.info16.fr Bartounet

    Bonjour.
    Je me casse la tête à protéger mes blogs wordpress des dos…
    J’ai beau mettre les mods evasive, les .htaccess etc..

    Avec un test avec siege je fini toujours par le faire tomber…
    Vous avez une idée…?

  • http://blog.info16.fr Bartounet

    J’ai des serveurs avec plusieurs vhosts avec un fichier de logs différent par vhost.

    Il faut creer une section par vhost dans le jail.conf ?

    • http://www.nicolargo.com NicoLargo

      Une jail est associée à un fichier de log. Donc à toi de voir comment sont organisés les logs de tes vhosts…

    • ArthurHoaro

      *1 an plus tard…*

      Je n’ai pas eu l’occasion de tester, mais apparemment on peut faire :
      logpath = /var/log/httpd/error.*.log

      Sinon, ça perd effectivement de son intérêt.

  • Nomis

    Existe t’il une appli web pour grapher les stats de fail2ban ?
    Ou est-il possible de faire un compte rendu sur les adresses bloquées ? Avec les pays, les heures … etc ?

    • http://www.sublimigeek.fr/ Joel

      J’arrive peut être un peu tard mais on ne sait jamais :)

      Il est possible de réaliser des graphes des statistiques de Fail2ban avec Munin.

      J’imagine qu’il existe de nombreux moyens pour le faire mais c’est le premier qui me vienne à l’esprit.

      • Nomis

        Merci, en effet, c’est ce que j’ai mis en place.

  • Pingback: Tech Digest 26/03/2012 | 3615 Alex

  • http://www.stephanethomas.com Stéphane

    Pour ceux qui utilisent un fichier de log commun à plusieurs virtual hosts, ce dernier a une syntaxe légèrement différente (paramètre vhost_combined) puisque chaque ligne est préfixée avec l’identifiant du virtual host correspondant. Du coup l’expression régulière mentionnée dans l’article ne fonctionne plus. Voici celle que j’utilise du coup (et qui fonctionne dans les deux cas) :

    ^(?:[a-zA-Z0-9.-]+:\d+)? .*\”GET

  • http://www.paschervetements.com/ tee shirt pas cher

    Most of what you point out is astonishingly legitimate and that makes me wonder why I had not looked at this with this light previously. Your article truly did switch the light on for me personally as far as this specific subject matter goes. But at this time there is actually one particular position I am not too comfy with and whilst I try to reconcile that with the core theme of the position, allow me see just what all the rest of your readers have to say.Nicely done.

  • Pingback: Secure your server using Fail2ban | TerraLtech

  • Pingback: Un serveur perso avec panneau d'administration derrière la Freebox - CLICK PANIC

  • Zpanel-Fr Zpanel-Fr

    Bonjour, je cherche un moyen pour analiser plusieurs logs avec [http-get-dos]

    mon architecture est la suivante /logs/domains/user/domain.com-access.log
    donc je cherche un moyen pour remplacer “user” et trouver le fichier log

    exemple qui fonctionne: /logs/domains/user/*access.log
    exemple qui fonctionne pas: /logs/domains/*/*access.log
    Quoi mettre la place de /*/ pour que sa analyse tout les sous dossiers du dossier “domains”?