Aller au contenu

Fail2Ban

Fail2ban est un service de surveillance des journaux qui détecte les comportements suspects, comme les échecs répétés d’authentification, et bloque automatiquement les adresses IP fautives.

Apprise s’intègre à Fail2ban comme action de notification, ce qui vous permet de recevoir des alertes via n’importe lequel des services pris en charge par Apprise, y compris l’e-mail, les notifications push, les plateformes de discussion et les webhooks.

Ce guide suppose :

  • Une installation récente de Fail2ban
  • systemd est disponible
  • Une configuration sur un seul hôte
  • sshd est le premier service surveillé

Les chemins propres à chaque distribution et les configurations avancées de prison sont volontairement laissés de côté.

Avant de commencer, assurez-vous que les éléments suivants sont installés :

  • Fail2ban
  • Apprise (CLI)
  • API Apprise est facultative (si la configuration est centralisée)

Vérifiez que les deux sont disponibles :

Fenêtre de terminal
fail2ban-client --version
apprise --version

Sur la plupart des systèmes, Fail2ban est disponible via le gestionnaire de paquets du système.

Activez et démarrez le service :

Fenêtre de terminal
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Vérifiez qu’il est en cours d’exécution :

Fenêtre de terminal
sudo systemctl status fail2ban

Assurez-vous d’être à l’aise avec les fichiers de configuration Apprise et de savoir quels services vous comptez utiliser. Ici, nous choisissons d’attribuer le tag fail2ban à tous les points de terminaison que nous souhaitons notifier lorsqu’un événement se produit :

/etc/fail2ban/apprise.conf
# Définissez ici le tag de configuration fail2ban et assignez-le, par exemple,
# à un webhook Discord pour les besoins de ce guide. Vous pouvez toutefois
# utiliser n'importe quel service de notification pris en charge.
fail2ban=discord://4174216298/JHMHI8qBe7bk2ZwO5U711o3dV_js

Ajoutez ce qui suit à /etc/fail2ban/jail.local

/etc/fail2ban/jail.local
[DEFAULT]
# ignoreip agit comme une liste d'autorisation ; les requêtes provenant de ces
# IP ne seront pas surveillées par Fail2Ban. Chaque entrée est séparée par un
# espace (' ').
# Indiquez uniquement des points d'accès de confiance :
# - 127.0.0.1/8 : localhost (ce poste) ; cela évite que Fail2Ban ne bloque
# des requêtes internes. Le suffixe `/8` peut être conservé.
# - YOUR_IP/32 : si vous accédez à distance au serveur exécutant Fail2Ban,
# remplacez 'YOUR_IP/32' ci-dessous par votre adresse IP
# réelle. Ajoutez `/32` pour une adresse IPv4 ou `/128` pour
# une adresse IPv6.
# IPv6 address.
ignoreip = 127.0.0.1/8 YOUR_IP/32
# how far back to look
findtime = 5m
# ban if we trigger on 4 failed authenticate within the findtime
maxretry = 4
# ban time; how long do we restrict this user from our system for?
bantime = 1d
#
# Now we define our Apprise Action
#
# - Read from /etc/fail2ban/apprise.conf
# - Only notify end points tagged with 'fail2ban'
#
action = apprise[config="/etc/fail2ban/apprise.conf", args="--tag fail2ban"]
#
# Now we will define our jails
#
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
# Optionally over-ride our defaults above
maxretry = 5
findtime = 10m
bantime = 1h
# The below entry is not nessisary as it's defined in the [DEFAULT] section above
# but this is to show that you could also define another entry here as well
# and assign it a different set of tags.
action = apprise[config="/etc/fail2ban/apprise.conf", args="--tag fail2ban"]

Redémarrez Fail2ban :

Fenêtre de terminal
sudo systemctl restart fail2ban

Vérifiez que la prison est active :

Fenêtre de terminal
sudo fail2ban-client status sshd

Déclenchez un bannissement de test en dépassant le nombre de tentatives d’authentification, ou simulez-le manuellement :

Fenêtre de terminal
sudo fail2ban-client set sshd banip 203.0.113.10

Vous devriez recevoir une notification Apprise immédiatement.

Fail2ban peut également surveiller le journal d’accès nginx placé devant l’API Apprise et bloquer les clients qui échouent plusieurs fois à s’authentifier, ignorent les limites de débit ou testent des routes non prises en charge.

L’API Apprise utilise des lignes de journal nginx ordinaires en mode normal comme en mode strict. Le mode strict limite aussi le trafic d’authentification et n’accepte que les routes connues. Il renvoie des états HTTP standards qu’un proxy inverse peut transmettre et journaliser :

  • 401 indique que les identifiants sont absents ou incorrects.
  • 404 indique que la route n’existe pas.
  • 405 indique que la route existe, mais refuse cette méthode HTTP.
  • 429 indique que nginx limite temporairement le client.

Ne considérez pas chaque réponse 403 comme un échec d’authentification. Apprise peut renvoyer 403 lorsque les identifiants sont valides, mais que le compte n’est pas autorisé à effectuer l’opération demandée.

Lorsqu’un nginx hôte sert de proxy inverse au conteneur, attribuez un journal dédié à l’hôte virtuel Apprise :

access_log /var/log/nginx/apprise_access.log combined;

C’est la solution la plus simple, car le journal externe contient déjà l’adresse du client qui se connecte.

Si le conteneur est exposé directement, vous pouvez monter /var/log/apprise depuis l’hôte et ajouter les deux destinations dans /etc/nginx/server-override.conf :

access_log /dev/stdout combined if=$apprise_access_loggable;
access_log /var/log/apprise/access.log combined if=$apprise_access_loggable;

Vérifiez que le répertoire est accessible en écriture par le PUID du conteneur, puis utilisez /var/log/apprise/access.log dans les prisons ci-dessous.

Créez /etc/fail2ban/filter.d/nginx-apprise-auth.conf :

[Definition]
# Identifiants absents ou incorrects. Un utilisateur valide mais non autorisé
# reçoit plutôt une réponse 403.
failregex = ^<HOST> - \S+ \[[^]]+\] "[^"]*" 401 \d+
ignoreregex =

Créez /etc/fail2ban/filter.d/nginx-apprise-rate-limit.conf :

[Definition]
# Le client continue après que nginx a commencé à renvoyer Too Many Requests.
failregex = ^<HOST> - \S+ \[[^]]+\] "[^"]*" 429 \d+
ignoreregex =

Créez /etc/fail2ban/filter.d/nginx-apprise-probe.conf :

[Definition]
# Requêtes mal formées répétées, routes absentes, méthodes non prises en charge,
# corps trop volumineux, URI trop longues ou mauvais hôte virtuel.
failregex = ^<HOST> - \S+ \[[^]]+\] "[^"]*" (?:400|404|405|413|414|421|431) \d+
ignoreregex =

Si vous possédez déjà un filtre nginx générique pour les réponses 429, ajoutez-y le journal Apprise au lieu d’en créer une copie.

Ajoutez les entrées suivantes à /etc/fail2ban/jail.local. Ces valeurs constituent un point de départ prudent ; ajustez-les après avoir observé votre trafic normal :

[nginx-apprise-auth]
enabled = true
filter = nginx-apprise-auth
port = http,https
logpath = /var/log/nginx/apprise_access.log
findtime = 10m
maxretry = 6
bantime = 1h
[nginx-apprise-rate-limit]
enabled = true
filter = nginx-apprise-rate-limit
port = http,https
logpath = /var/log/nginx/apprise_access.log
findtime = 5m
maxretry = 10
bantime = 1h
[nginx-apprise-probe]
enabled = true
filter = nginx-apprise-probe
port = http,https
logpath = /var/log/nginx/apprise_access.log
findtime = 10m
maxretry = 10
bantime = 1d

Fail2ban ne doit jamais bloquer le proxy inverse à la place du client. Le proxy hôte doit remplacer l’adresse transmise au lieu de l’ajouter :

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

Le conteneur Apprise a également besoin de l’adresse réelle pour les limites de débit du mode strict. N’autorisez que l’adresse exacte du proxy ou de la passerelle Docker dans /etc/nginx/server-override.conf :

set_real_ip_from 172.17.0.1; # Remplacez par l'adresse exacte du proxy fiable.
real_ip_header X-Forwarded-For;
real_ip_recursive on;

N’ajoutez pas un réseau Docker ou privé entier à set_real_ip_from, sauf si tous ses appareils sont fiables.

Testez chaque filtre avec de vraies lignes du journal :

Fenêtre de terminal
sudo fail2ban-regex /var/log/nginx/apprise_access.log \
/etc/fail2ban/filter.d/nginx-apprise-auth.conf
sudo fail2ban-regex /var/log/nginx/apprise_access.log \
/etc/fail2ban/filter.d/nginx-apprise-rate-limit.conf
sudo fail2ban-regex /var/log/nginx/apprise_access.log \
/etc/fail2ban/filter.d/nginx-apprise-probe.conf

Validez ensuite la configuration et rechargez Fail2ban :

Fenêtre de terminal
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-apprise-auth
sudo fail2ban-client status nginx-apprise-rate-limit
sudo fail2ban-client status nginx-apprise-probe

Affichez les journaux Fail2ban :

Fenêtre de terminal
journalctl -u fail2ban

Augmentez la verbosité des actions Apprise (en ajoutant -vv) et testez pour voir ce qui se passe :

Fenêtre de terminal
apprise -vv --tag fail2ban --config /etc/fail2ban/apprise.conf \
--body "fail2ban trigger test"

Vérifiez les URL Apprise séparément avant de déboguer Fail2ban.

Fail2ban est formidable, mais peut parfois être fastidieux à utiliser. Avoir quelques pense-bêtes sous la main peut aider au dépannage :

Fenêtre de terminal
# See all jails:
fail2ban-client status
# Look into the status of one of the specific jails
fail2ban-client status sshd
# quick and dirty way to unban an IP (regardless of which jail banned it)
fail2ban-client unban 1.2.3.4
Questions ou commentaires ?

Documentation

Vous avez repéré une faute de frappe ou une erreur ?

Problèmes Techniques

Vous rencontrez un problème avec le code ? Ouvrez un ticket sur GitHub :

Conçu avec amour depuis le Canada