fail2ban bannit temporairement des adresses IP par injection de règles iptables. Il est basé sur la recherche de motifs dans des journaux (échecs d'authentification dans /var/log/auth.log par exemple). C'est une sorte de pare-feu dynamique.

Machines

fail2ban est actuellement installé sur bulbe.

Fichiers

Avec ce programme, on a affaire à deux types de fichiers : les fichiers de configuration (dans /etc/fail2ban) et les journaux (/var/log/fail2ban.log*).

Configuration

Les fichiers de configuration sont répartis en trois catégories :

/etc/fail2ban/*.{conf,local}
Configuration globale du programme : niveau de verbosité, emplacement du journal, activation et options principales des jails, etc.
/etc/fail2ban/filter.d/*.{conf,local}
Filtres à appliquer, correspondant à la variable filter. Les motifs du filtre sont à comparer avec le contenu du journal défini par la variable logpath.
/etc/fail2ban/action.d/*.{conf,local}
Actions à appliquer, correspondant à la variable action.

Journaux

Les fichiers /var/log/fail2ban.log* enregistrent toutes les adresses IP attrapées par le programme (et donc temporairement bannies) en fonction de ses paramètres. Sa lecture et sa comparaison avec les autres journaux permet de savoir s'il faut ou non durcir une politique de bannissement pour protéger un service.

Afin d'appliquer une politique particulière (voir plus bas), des fichiers ont été créés ou modifiés :

/etc/fail2ban/weekly_report
Script shell chargé d'écrire un rapport hebdomadaire à partir de l'analyse des journaux de fail2ban et des autres services concernés.
/etc/logrotate.d/fail2ban
La directive prerotate appelle le script weekly_report et envoie son résultat à root.

Configuration

Les fichiers *.conf se trouvant dans /etc/fail2ban ne doivent pas être modifiés. La procédure recommandée pour modifier la configuration est de copier fichier.conf en fichier.local et de modifier ce dernier. Ça permet de voir facilement ce qui a changé par rapport à la configuration par défaut :

for custom in $(find /etc/fail2ban -type f -name "*.local"); do
[ -f ${custom%.local}.conf ] &&
origin="${custom%.local}.conf" ||
origin="/dev/null"
diff -u ${origin} ${custom}
done | view -

Une modification ou un ensemble de modifications de la configuration de fail2ban est prise en compte par la commande :

sudo fail2ban-client reload [JAIL]

Politique

  • Les bannissements d'adresse IP relatifs à des échecs d'authentification par mot de passe sont traités en temps réel par l'envoi (par fail2ban) d'un courrier à root. Pour chaque bannissement, un courrier; dans chaque courrier, on trouve la sortie de la commande whois appliquée à l'adresse bannie et les lignes du journal concerné (par exemple /var/log/nginx/error.log) contenant cette IP.

  • Chaque semaine un rapport hebdomadaire est envoyé (par logrotate) à root. Ce rapport contient :

    • La liste des IP bannies au cours de la semaine
    • La liste, parmi ces IP de la semaine, de celles qui ont déjà été bannies durant les quatre dernières semaines.
    • Pour chaque IP bannie au moins deux fois dans le mois (dont au moins une fois dans la semaine) : le whois et les extraits des journaux.

Configuration globale

Dans le fichier /etc/fail2ban/jail.local :

[DEFAULT]
findtime = 600
C'est en fait la valeur appliquée quand cette variable n'est pas définie, mais la définir ici évite d'avoir tout un tas de WARNING inutiles quand on lance fail2ban-client reload.
destemail = root
Adresse e-mail de destination utilisée pour les interpolations des fichiers jail.{conf,local}

Le seul jail activé par défaut est [ssh]. Compte tenu des services qui tournent sur bulbe, on a donc activé ou ajouté ou configuré :

  • [nginx-http-auth]
  • [nginx-nohome]
  • [nginx-noproxy]
  • [nginx-noscript]
  • [nginx-notilde]
  • [postfix]

Configurations spécifiques

/etc/fail2ban/filter.d/nginx-no*

nicoo s'est fendu d'un certain nombres de filtres pour Nginx, qui font l'équivalent des filtres fournis pour Apache.

nohome

Ce filtre détecte les malotrus qui voudraient explorer les répertoires « maison » des utilisateurs en visitant /~user, ce que notre configuration ne supporte de toutes façons pas.

[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ .* client: <HOST>, server: \S+, request: "GET /~.* HTTP
ignoreregex =

noproxy

Ce filtre détecte les bots tentant d'utiliser notre serveur HTTP comme un proxy ouvert. À nouveau, c'est quelque chose qu'on ne supporte pas.

[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ .* client: <HOST>, server: \S+, request: "GET https?://
ignoreregex =

noscript

Ce filtre là s'en prends aux bots cherchant des scripts exécutables à exploiter.

[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ .* client: <HOST>, server: \S+, request: "GET .*\.(php|asp|exe|cfm|pl|cgi|scgi|py) HTTP
ignoreregex =

notilde

Un dernier filtre détecte les curieux qui cherchent des fichiers « en tilde », comme index.php~, qui seraient lisible et contiendraient des informations de configuration intéressantes.

(On se souviendra d'un potentiel hébergeur qui avait les mots de passes de sa base de données accessibles ainsi)

[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ .* client: <HOST>, server: \S+, request: "GET /.*~ HTTP
ignoreregex =

Comment tester les règles ?

C'est bien d'avoir écrit toutes ces jolies règles, c'est mieux de les tester.

Fail2ban est livré avec un utilitaire, fail2ban-regex(1), qui permet de tester une règle donnée sur un journal. En plus, les admins sont dans le groupe adm donc il n'y a pas besoin de faire les tests en tant que root:

fail2ban-regex -v /var/log/nginx/error.log '^ma petite règle à moi'

/etc/fail2ban/jail.local

Pour [nginx-http-auth], qui traque les échecs d'authentification par mot de passe, on utilise une action spécifique action_mwl, qui envoie en temps réel un e-mail à root en plus de bannir l'IP.

De plus, on utilise iptables-xt_recent-echo comme action de bannissement (au lieu de iptables-multiport) qui réinitialise le temps de bannissement d'une IP si ce même client cherche à se connecter durant cette période de bannissement, et qui s'applique à tous les ports.

Le nombre de tentatives a été réduit à 3.

/etc/fail2ban/action.d/sendmail*.local

Désactivation de l'envoi d'e-mails pour les commandes

sudo fail2ban start|stop|reload [JAIL]

/etc/fail2ban/filter.d/sshd.local

Modification des filtres, pour correspondre à ce qu'on trouve réellement dans /var/log/auth.log

Il faut voir à l'usage, mais il faudrait éviter de bannir trop vite les hôtes générant des messages du type POSSIBLE BREAK-IN ATTEMPT!, ce qui pénaliserait les users de Tor.

/etc/fail2ban/weekly_report

Script shell ad hoc qui sert à générer le rapport hebdomadaire. Son résultat est envoyé sur la sortie standard.

Intégration avec ferm

fail2ban est intégré au pare-feu à l'aide de deux hooks dans /etc/ferm/ferm.conf :

@hook post "if fail2ban-client ping >/dev/null; then fail2ban-client reload; fi";
@hook flush "if fail2ban-client ping >/dev/null; then fail2ban-client reload; fi";

Cela permet de recharger automatiquement les règles produites par fail2ban quand on redémarre ou qu'on arrête ferm.