Aller à la recherche

fail2ban proteger son serveur des bots

Nous allons mettre en place sous FreeBSD 11 fail2ban afin de stopper les bots qui font des requêtes sur des URL qui n’existe pas sur notre site par exemple : http://www.example.com/wp-admin.php.

Fail2ban l'anti bot

Installation depuis le package se fait simplement pkg install py27-failtoban

Installation depuis les sources cd /usr/port/security/py-failtoban make install

Une fois l’installation terminée voyons les fichiers situés à /usr/local/etc/fail2ban

|-- action.d  { Contient les actions prédéfinies }
|-- fail2ban.conf { Fichier de configuration principal de fail2ban }
|-- fail2ban.d { }
|-- filter.d { Contient les filtres prédéfinis sous forme d’expression régulière pour différent programme  }
|-- jail.conf { Option par défaut des bind de filtre et des actions }
|-- jail.d { Permet de placer nos bind (liaison) }
|-- paths-common.conf { chemin des différents programmes commun aux différentes plates-formes }
|-- paths-debian.conf  { chemin des programmes sous debian }
|-- paths-fedora.conf   { chemin des programmes sous fedora }
|-- paths-freebsd.conf  { chemin des programmes sous freebsd }
|-- paths-opensuse.conf  { chemin des programmes sous opensuse }
`-- paths-osx.conf  { chemin des programmes sous osx }

La configuration générale

La configuration des options générales se fait au niveau du fichier fail2ban.conf en voici quelques paramètres

  • loglevel = définit le niveau des logs, par défaut est positionné à INFO qui peut être un peu trop verbeux en production
  • logtarget = définit le fichier log
  • socket = socket crée pour la communication avec le serveur
  • dbpurgeage = définit la durée maximale pendant laquelle sont stockés les ip bannis dans la base de données.
  • dbfile = base de données de type sqlite
    • vous pouvez utiliser une base en mémoire en la définissant à :memory:

Les actions (action.d)

On y trouve les actions à appliquer si une règle (que nous verrons un peu plus bas) match, cela peut être : le loguer dans un fichier, l’envoie d’un mail, le blocage de l’ip grâce au pare-feu... Si on jette un coup d’œil dans pf.conf cat pf.conf | grep -v '^#\|^$'

[Definition]
actionstart = 
actionstop = 
actioncheck = 
actionban = /sbin/pfctl -t <tablename> -T add <ip>/32
actionunban = /sbin/pfctl -t <tablename> -T delete <ip>/32
[Init]
tablename = fail2ban

Nous pouvons voir que nous avons une section « Init » qui permet d’initialiser les variables, et une section « Definition » qui permet de définir les actions à effectuer.

  • actionstart et actionstop sont les actions à effectuer lors du démarrage et l’arrêt de fail2ban, **exemple : envoyer un mail à l’administrateur système.
  • actioncheck : permet de définir l’action à effectuer avant l’actionban, cela peut être une initiation, la vérification d’un fichier etc...
  • actionban : action à exécuter si la règle à matché, cela peut être l’envoie d’un mail ou le blocage d’une ip avec le firewall.
  • actionunban : action à exécuter pour sortir une ip d’un ban, ici aussi ce n’est pas forcement le blocage d’ip

Revenons à notre exemple

Nous avons

actionban=  /sbin/pfctl -t <tablename> -T add <ip>/32 

Cette règle demande à pf d’ajouter à la table persistante <tablename> l’adresse <ip>. Or ici ce n’est pas vraiment adapté, effectivement en général pour soulager le par-feu nous avons ce genre de règle dans /etc/pf.conf

pass in quick on $if inet proto tcp from any to $addr port 80 keep state

Le keep state sauvegarde cette connexion dans la table des états de connexions, ainsi si une nouvelle connexion (même ip/port) est initialisée, elle sera acceptée directement sans que les règles (celles qui bloquent la table <fail2ban> par exemple) ne soient réévaluées.

Ce comportement dans notre cas est problématique car si un script en face a un listing de 100 URL à tester, pour son premier passage la connexion est acceptée (pf intervenant avant nginx) puis la connexion est sauvegardée dans la table des états de connexions. fail2ban détecte ensuite que l’ip doit être bloquée, car elle a demandé une URL qui matche avec nos règles, il ajoute donc l’adresse ip à la table fail2ban de pf. Au second passage pf après avoir lu sa table des états de connexion retrouve la connexion (ip/port) et sait qu’il doit accepter cette connexion. Il laisse donc passer celle-ci, ceci même si cette ip a été bannie entre temps. Pour corriger ce problème nous devons ajouter la réinitialisation des états de connexion pour cette ip/port, grâce à l’option -k de pfctl. Ce qui donne pour actionban

actionban= /sbin/pfctl -f <tablename> -T add <ip>/32 && /sbin/pfctl -k <ip>/32

Les filtres (filter.d)

On y trouve des filtres préinstallés qui portent des noms assez explicite pour savoir de quel programme il est question. Un fichier filtre est composé de plusieurs sections

  • Init : permet d’initialiser des variables
  • Include : qui permet d’inclure des fichiers config à utiliser avant ou après les définitions
  • Definition : permet de définir les expressions régulières qui vont être utilisée pour prendre les décisions.

Nous allons ici voir celui qui nous intéresse à savoir nginx-botsearch.conf. cat nginx-botsearch.conf | grep -v ‘^#\|$’

[INCLUDES]
before = botsearch-common.conf
[Definition]
failregex = ^<HOST> \- \S+ \[\] "(GET|POST|HEAD) \/<block> \S+" 404 .+$
            ^ \[error\] \d+#\d+: \*\d+ (\S+ )?"\S+" (failed|is not found) \(2\: No such file or directory\), client\: <HOST>\, server\: \S*\, request: "(GET|POST|HEAD) \/<block> \S+"\, .*?$
ignoreregex = 

Nous pouvons voir que l’on inclut botsearch-common.conf avant d’utiliser les expressions régulières, voyons voir ce qu’il contient. grep -v ‘^#\|^$’ botsearch-common.conf

[Init]
block = \/?(<webmail>|<phpmyadmin>|<wordpress>|cgi-bin|mysqladmin)[^,]*
webmail = roundcube|(ext)?mail|horde|(v-?)?webmail
phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)
wordpress = wp-(login|signup|admin)\.php

Ici nous avons 3 règles (wordpress, phpmyadmin et webmail) qui permettent chacune de rechercher une ligne spéciale et 1 règle qui applique un ‘ou logique’ (|) entre toutes ces règles puis retourne le tout sous le nom d’une variable nommée block.

Nous allons maintenant utiliser cette variable dans le « failregex » et « ignoregexp »

  • failregexp : permet de définir les règles qui matcheront
  • ignoregexp : permet d’exclure des lignes qui auraient pu matcher avec failregexp, mais que nous ne voulons pas garder.

Si nous revenons à notre exemple nous avons cette ligne dans failregexp

^<HOST> \- \S+ \[\] "(GET|POST|HEAD) \/<block> \S+" 404 .+$
  • HOST : l’ip sera récupérée ici
  • <block> : sera remplacée par la variable que l’on a crée tout à l’heure grâce à l’inclusion

Il existe un outil fourni avec fail2ban qui permet de tester nos expressions régulières, il s’agit de fail2ban-regex au quel nous devons fournir un fichier log et une expression régulière

Usage: /usr/local/bin/fail2ban-regex [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]
  • LOG : Fichier log ou nous devons chercher
  • REGEX : qui peut être fournies sous deux formats
    • String : permet de définir une expression régulière à tester
    • Nom de fichier : fichier filtre qui doit contenir la variable failregex

fail2ban-regexp /srv/log/example.com_access.log /usr/local/etc/fail2ban/filter.d/nginx-botsearch.conf

Fichier log contenant des lignes du genre.

192.168.100.110 - - [08/Jan/2017:11:28:53 +0100] "GET /wp-admin.php HTTP/1.1" 404 210 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0"
Lines: 238 lines, 0 ignored, 153 matched, 85 missed
[processed in 0.64 sec]

Nous savons maintenant que nos expressions régulières matcheront les lignes.

Nous avons maintenant une action ainsi qu’un filtre, nous allons les lier dans un jail afin de pouvoir les utiliser.

Les liaisons (bind) : jail.d

Le répertoire contient les fichiers qui permettent de lier les filtres et les actions. Nous allons donc créer un fichier nommé nginx-pf.conf contenant

[nginx-botsearch]
enabled = true
filter = nginx-botsearch
#port = http, https
action = pf
logpath = /srv/log/example.com_access.log
findtime = 3600
maxretry = 1
bantime = 86400
  • [nginx-botsearch] : nom du bind
  • enabled : défini si le bind est actif
  • filter : défini le fichier dans filter.d (sans l’extension)
  • action : défini le fichier dans action.d (sans l’extension)
  • logpath : Les logs ou fail2ban doit chercher les expressions régulières définies dans le filtre
  • bantime : permet de définir le temps de bannissement par défaut vaut 600s (10 min) ce qui n’est sans doute pas assez.
  • findtime : défini jusqu’à où remonter dans les fichiers log pour chercher les expressions régulières.
  • maxretry = correspond au nombre de fois que la ligne match le filtre avant d’être exécutée, dans notre cas dès le premier match l’action doit être effectuée.

On peut ici mettre en place des variables que l’on pourra passer à l’action du type

  • port : Qui nous permettrait de bloquer un port précis en fonction du filtre.

Ajout de fail2ban au fichier rc.conf et lancement du service sysrc fail2ban_enable=YES service fail2ban start

2017-01-09 22:15:37,775 fail2ban.server         [16592]: INFO    Starting Fail2ban v0.9.6
2017-01-09 22:15:37,778 fail2ban.server         [16592]: INFO    Starting in daemon mode

Nous pouvons afficher les jails qui sont chargés fail2ban status

Status
|- Number of jail:	1
`- Jail list:	nginx-botsearch

Nous pouvons voir les informations d’un jail particulier fail2ban-client status nginx-botsearch

Status for the jail: nginx-botsearch
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	0
|  `- File list:	/srv/log/example.com_access.log
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:	

Nous pouvons bannir / dé-bannir une ip manuellement fail2ban-client set nginx-botsearch banip 192.168.100.111 fail2ban-client set nginx-botsearch unbanip 192.168.100.111

Après toute modification de fichier filtre ou action, il est possible de recharger les configurations fail2ban-client reload

Voilà, ça sera tout...

La discussion continue ailleurs

URL de rétrolien : https://www.binsp.net/?trackback/42

Fil des commentaires de ce billet

Page top