fail2ban avance : jails custom, alertes et protection multi-services
Guide fail2ban avance : jails custom SSH/Nginx, action Telegram, whitelisting. Protegez vos serveurs Linux avec des regles sur mesure.
fail2ban est probablement l'outil de sécurité Linux le plus universel qui soit — il tourne sur des millions de serveurs. Mais la majorité des admins ne l'utilisent qu'avec la jail SSH par défaut, ce qui ne représente que 10% de ce que l'outil peut faire. Ce guide explore les jails personnalisées, les actions d'alerte multi-canaux, la protection de services complexes (MySQL, Postfix, WordPress), et l'intégration avec des systèmes externes.
Rappel : comment fonctionne fail2ban
fail2ban surveille en permanence vos fichiers de logs. Quand il détecte un pattern suspect (X tentatives échouées en Y secondes), il exécute une 'action' — généralement ajouter une règle iptables pour bloquer l'IP. Après un délai configurable, l'IP est débloquée. Simple, efficace, mais puissant si bien configuré.
- Filters : expressions régulières qui définissent ce qui est 'suspect' dans les logs
- Jails : association d'un filter + une action + des seuils (maxretry, findtime, bantime)
- Actions : ce qui se passe quand un pattern est détecté (ban iptables, email, webhook...)
- Whitelists : IPs jamais bannies (votre bureau, votre accès VPN)

Installation et configuration de base
# Ubuntu / Debian
sudo apt update && sudo apt install -y fail2ban
# CentOS / Rocky Linux
sudo dnf install -y fail2ban
# Vérifier
sudo systemctl enable --now fail2ban
sudo fail2ban-client status⚠️ Règle impérative : ne jamais modifier /etc/fail2ban/jail.conf directement. Créez toujours un fichier jail.local qui surcharge les valeurs par défaut. Ainsi, les mises à jour de fail2ban n'écrasent pas votre configuration.
# Créer le fichier de configuration local
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local# /etc/fail2ban/jail.local — Section [DEFAULT]
[DEFAULT]
# IPs jamais bannies (VOTRE IP DE BUREAU, réseau VPN, réseau admin)
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
# Durée de bannissement par défaut (10 minutes)
bantime = 10m
# Bannissement progressif : 1h après 1 ban, 1j après 2 bans, 1 semaine après 3
bantime.increment = true
bantime.factor = 1
bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
# Fenêtre de temps pour compter les tentatives
findtime = 10m
# Nombre de tentatives avant bannissement
maxretry = 5
# Backend de lecture de logs (systemd pour les systèmes modernes)
backend = systemd
# Action par défaut (ban + notification email optionnelle)
action = %(action_mwl)sJails avancées par service
Protection SSH renforcée
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
/var/log/sshd.log
maxretry = 3
bantime = 1h
findtime = 30m
# Bannir aussi sur IPv6
banaction = iptables-multiport
banaction_allports = iptables-allportsProtection Nginx — Brute force + DDoS
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 1h
[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 30m
findtime = 5m
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 24h
Créer un filtre personnalisé pour une application métier
Supposons que vous avez une application web avec des logs comme : '2024-01-15 10:23:44 [AUTH FAIL] user@example.com from 1.2.3.4'. Voici comment créer un filtre fail2ban pour ça :
# Créer le filtre
sudo nano /etc/fail2ban/filter.d/mon-app.conf# /etc/fail2ban/filter.d/mon-app.conf
[Definition]
# Regex pour matcher les echecs d'authentification
# %(host)s capture automatiquement l'IP pour le bannissement
failregex = ^%(__prefix_line)s\[AUTH FAIL\] .+ from <HOST>$
^%(__prefix_line)s\[LOGIN ERROR\] IP: <HOST> .+$
ignoreregex = ^%(__prefix_line)s\[AUTH FAIL\] .+127\.0\.0\.1.+$# Tester le filtre avant de l'activer (très important !)
sudo fail2ban-regex /var/log/mon-app/auth.log /etc/fail2ban/filter.d/mon-app.conf
# Si des matchs sont trouvés → le filtre fonctionne
# Output attendu:
# Lines: 1243 lines, 0 ignored, 47 matched, 1196 missed# Ajouter la jail dans jail.local
[mon-app-auth]
enabled = true
port = 8080
filter = mon-app
logpath = /var/log/mon-app/auth.log
maxretry = 5
bantime = 2h
findtime = 15mActions avancées — Alertes multi-canaux
Alertes Telegram
# Créer l'action Telegram
sudo nano /etc/fail2ban/action.d/telegram.conf# /etc/fail2ban/action.d/telegram.conf
[Definition]
actionstart = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage -d chat_id=<CHAT_ID> -d text="🛡️ fail2ban démarré sur $(hostname)"
actionban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage -d chat_id=<CHAT_ID> -d parse_mode=HTML -d text="🚨 <b>BANNISSEMENT</b>%0AIPs: <ip>%0AService: <name>%0AServeur: $(hostname)%0ADate: $(date '+%%Y-%%m-%%d %%H:%%M:%%S')%0ARaison: %(reason)s"
actionunban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage -d chat_id=<CHAT_ID> -d text="✅ IP <ip> débloquée (service: <name>)"
[Init]
init = texte de test
Alertes Slack / Webhook
# /etc/fail2ban/action.d/slack.conf
[Definition]
actionban = curl -s -X POST <WEBHOOK_URL> -H 'Content-type: application/json' -d '{"text":"🚨 fail2ban: IP <ip> bannie\nService: <name>\nServeur: '"$(hostname)"'"}'
actionunban = curl -s -X POST <WEBHOOK_URL> -H 'Content-type: application/json' -d '{"text":"✅ IP <ip> débloquée (service: <name>)"}'Activer les alertes dans les jails
# Dans jail.local, section [DEFAULT]
[DEFAULT]
# Utiliser l'action telegram pour toutes les jails
action = iptables-multiport[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s"]
telegram[name=%(__name__)s]
# Ou par jail spécifique
[sshd]
enabled = true
action = iptables-allports
telegramGestion et maintenance
# Statut de toutes les jails
sudo fail2ban-client status
# Statut d'une jail spécifique
sudo fail2ban-client status sshd
# IPs actuellement bannies
sudo fail2ban-client status sshd | grep "Banned IP"
# Débannir une IP spécifique (faux positif)
sudo fail2ban-client set sshd unbanip 1.2.3.4
# Recharger la configuration sans redémarrage
sudo fail2ban-client reload
# Voir les logs fail2ban en temps réel
sudo tail -f /var/log/fail2ban.log
# Statistiques de bannissement
sudo fail2ban-client status | grep -E "(Jail|Currently)
Script de rapport quotidien
#!/bin/bash
# /usr/local/bin/fail2ban-daily-report.sh
# À lancer via cron : 0 8 * * * /usr/local/bin/fail2ban-daily-report.sh
JAILS=$(fail2ban-client status | grep "Jail list" | sed 's/.*Jail list:\s*//' | tr ',' '
' | tr -d ' ')
RAPPORT="📊 Rapport fail2ban $(date '+%Y-%m-%d')
"
RAPPORT+="Serveur: $(hostname)
"
TOTAL_BAN=0
for jail in $JAILS; do
COUNT=$(fail2ban-client status "$jail" | grep "Total banned" | awk '{print $NF}')
CURRENT=$(fail2ban-client status "$jail" | grep "Currently banned" | awk '{print $NF}')
RAPPORT+="$jail: ${COUNT} total / ${CURRENT} actifs
"
TOTAL_BAN=$((TOTAL_BAN + COUNT))
done
RAPPORT+="
Total tous services: $TOTAL_BAN bannissements"
# Envoyer par Telegram
curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage -d chat_id=<CHAT_ID> -d text="$RAPPORT"
echo "Rapport envoyé"
# Rendre exécutable
chmod +x /usr/local/bin/fail2ban-daily-report.sh
Prochaines étapes
- Migrer vers CrowdSec pour bénéficier de l'intelligence collective communautaire
- Intégrer fail2ban avec votre SIEM (Elasticsearch, Graylog) pour la corrélation d'événements
- Mettre en place une whitelist dynamique pour les IPs VPN de vos équipes
- Configurer des règles de bannissement géographique (GeoIP) pour bloquer les pays sources d'attaques
- Automatiser les tests de vos filtres dans votre pipeline CI/CD
Téléchargez ce guide en PDF pour le consulter hors ligne.
⬇ Télécharger le guide (PDF)🚀 Aller plus loin avec BOTUM
Ce guide couvre les bases. En production, chaque environnement a ses spécificités. Les équipes BOTUM accompagnent les organisations dans le déploiement, la configuration avancée et la sécurisation de leur infrastructure. Si vous avez un projet, parlons-en.
Discuter de votre projet →