Call-Informatique
Call-Informatique
Le média tech
 Fail2ban avance : bannissement incremental, filtres custom et ...
CybersécuritéGuides10 min de lecture

Fail2ban avance : bannissement incremental, filtres custom et ...

Configuration avancee de Fail2ban pour SSH : ban incremental, recidive, filtres regex personnalises, integration Telegram, hardening complet.

Fail2ban avance : bannissement incremental, filtres custom et alertes

Ce guide suppose que vous avez deja un Fail2ban fonctionnel avec la jail sshd activee. On va aller plus loin : bannissement progressif, detection d'attaques distribuees, filtres regex sur mesure et alertes en temps reel via Telegram.

Version cible : Fail2ban 1.1.0 (derniere stable, avril 2024). Les configurations fonctionnent egalement sur la version 1.0.2 presente dans les depots Ubuntu 24.04 / Debian 12.

Pre-requis

  • Serveur Ubuntu 22.04+ ou Debian 11+ avec Fail2ban installe
  • Acces root ou sudo
  • Jail sshd deja fonctionnelle
  • (Optionnel) Un bot Telegram pour les alertes

1. Bannissement incremental

Le ban fixe a un probleme : un attaquant banni 1 heure revient systematiquement apres. Le ban incremental augmente la duree a chaque recidive.

Editez /etc/fail2ban/jail.local :

bash
sudo nano /etc/fail2ban/jail.local

Configuration complete avec bannissement incremental :

ini
## /etc/fail2ban/jail.local
## Configuration avancee avec bannissement incremental

[DEFAULT]
## Adresses IP whitelist (adaptez a votre reseau)
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16

## Backend systemd pour les distributions recentes
backend = systemd

## Ban incremental : la duree double a chaque recidive
bantime.increment = true

## Premier ban : 10 minutes. Puis 20, 40, 80... jusqu'au max
bantime = 600

## Multiplicateur entre chaque ban (defaut : facteur x2)
bantime.factor = 2

## Duree max de bannissement : 4 semaines
bantime.maxtime = 4w

## Fenetre de detection
findtime = 600

## Echecs avant ban
maxretry = 5

## Utiliser la base de donnees pour persister les bans entre redemarrages
bantime.overalljails = true

## Base de donnees SQLite (chemin par defaut)
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 30d


[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
findtime = 300
bantime = 3600
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w

## Mode de detection agressif : attrape plus de patterns
mode = aggressive


[sshd-ddos]
## Protection contre les attaques DDoS sur SSH
enabled = true
port = ssh
filter = sshd-ddos
maxretry = 6
findtime = 60
bantime = 172800
bantime.increment = true


[recidive]
## Ban les recidivistes : IP bannie 3 fois = ban longue duree
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
maxretry = 3
findtime = 86400
bantime = 604800
banaction = iptables-allports

Le filtre sshd-ddos n'existe pas par defaut. On le cree :

bash
sudo nano /etc/fail2ban/filter.d/sshd-ddos.conf
ini
## /etc/fail2ban/filter.d/sshd-ddos.conf
## Detecte les connexions SSH excessives (flood)

[Definition]
failregex = ^sshd\[\d+\]: Connection from <HOST> port \d+ on .* rdomain .*$
            ^sshd\[\d+\]: Received disconnect from <HOST> port \d+:.*\[preauth\]$
            ^sshd\[\d+\]: Disconnected from authenticating user .* <HOST> port \d+ \[preauth\]$
ignoreregex =

Rechargez Fail2ban :

bash
sudo fail2ban-client reload

Verifiez que les trois jails sont actives :

bash
sudo fail2ban-client status

Resultat attendu :

terminal
Status
|- Number of jail:      3
`- Jail list:   recidive, sshd, sshd-ddos

2. Filtre regex personnalise

Les filtres par defaut couvrent les cas classiques. Mais si votre serveur subit des attaques specifiques, vous pouvez ecrire vos propres regles.

Exemple : detecter les tentatives avec des noms d'utilisateur inexistants.

bash
sudo nano /etc/fail2ban/filter.d/sshd-invalid-user.conf
ini
## /etc/fail2ban/filter.d/sshd-invalid-user.conf
## Ban les tentatives avec des utilisateurs qui n'existent pas

[Definition]
failregex = ^sshd\[\d+\]: Invalid user .* from <HOST>$
            ^sshd\[\d+\]: Connection closed by invalid user .* <HOST> port \d+ \[preauth\]$
            ^sshd\[\d+\]: Failed password for invalid user .* from <HOST> port \d+ ssh2$
ignoreregex =

[Init]
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd

Ajoutez la jail correspondante dans jail.local :

ini
[sshd-invalid-user]
enabled = true
port = ssh
filter = sshd-invalid-user
maxretry = 2
findtime = 300
bantime = 86400
bantime.increment = true

Pour tester un filtre avant de l'activer :

bash
## Tester le filtre contre les logs existants
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd-invalid-user.conf

## Sur systemd (pas de fichier log) :
sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd-invalid-user.conf

La commande fail2ban-regex affiche le nombre de correspondances trouvees. Si c'est 0 alors que vous savez qu'il y a des tentatives, votre regex a un probleme.

3. Alertes Telegram en temps reel

Recevoir un email pour chaque ban, c'est vite penible. Telegram est plus pratique pour du monitoring en temps reel.

Creer le bot Telegram

  1. Ouvrez Telegram, cherchez @BotFather
  2. Envoyez /newbot, suivez les instructions
  3. Notez le token du bot (format : 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)
  4. Demarrez une conversation avec votre bot, envoyez /start
  5. Recuperez votre chat ID : curl -s https://api.telegram.org/bot<VOTRE_TOKEN>/getUpdates | jq '.result[0].message.chat.id'

Creer l'action Fail2ban

bash
sudo nano /etc/fail2ban/action.d/telegram.conf
ini
## /etc/fail2ban/action.d/telegram.conf
## Envoie une notification Telegram a chaque ban/unban

[Definition]

actionstart = /usr/bin/curl -s -X POST \
    "https://api.telegram.org/bot%(token)s/sendMessage" \
    -d chat_id="%(chatid)s" \
    -d parse_mode="HTML" \
    -d text="🟢 <b>Fail2ban</b> demarre sur <code>%(hostname)s</code>%0AJail : <code><name></code>"

actionstop = /usr/bin/curl -s -X POST \
    "https://api.telegram.org/bot%(token)s/sendMessage" \
    -d chat_id="%(chatid)s" \
    -d parse_mode="HTML" \
    -d text="🔴 <b>Fail2ban</b> arrete sur <code>%(hostname)s</code>%0AJail : <code><name></code>"

actionban = /usr/bin/curl -s -X POST \
    "https://api.telegram.org/bot%(token)s/sendMessage" \
    -d chat_id="%(chatid)s" \
    -d parse_mode="HTML" \
    -d text="🚫 <b>BAN</b> sur <code>%(hostname)s</code>%0AJail : <code><name></code>%0AIP : <code><ip></code>%0ATentatives : <failures>%0ADuree : %(bantime)s sec"

actionunban = /usr/bin/curl -s -X POST \
    "https://api.telegram.org/bot%(token)s/sendMessage" \
    -d chat_id="%(chatid)s" \
    -d parse_mode="HTML" \
    -d text="✅ <b>UNBAN</b> sur <code>%(hostname)s</code>%0AJail : <code><name></code>%0AIP : <code><ip></code>"

[Init]
## Remplacez par vos valeurs
token = VOTRE_TOKEN_BOT_TELEGRAM
chatid = VOTRE_CHAT_ID
hostname = mon-serveur

Puis activez l'action dans jail.local :

ini
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
findtime = 300
bantime = 3600
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w
mode = aggressive
## Action : ban IP + notification Telegram
action = %(action_)s
         telegram

Rechargez et testez :

bash
sudo fail2ban-client reload

## Test : bannir une IP fictive
sudo fail2ban-client set sshd banip 192.0.2.1

## Verifier que la notification Telegram arrive
## Puis debannir
sudo fail2ban-client set sshd unbanip 192.0.2.1

4. Hardening SSH complementaire

Fail2ban protege contre la force brute, mais durcir la configuration SSH reduit encore la surface d'attaque.

bash
sudo nano /etc/ssh/sshd_config.d/hardening.conf
ini
## /etc/ssh/sshd_config.d/hardening.conf
## Durcissement SSH

## Desactiver l'authentification par mot de passe
## (uniquement si vous avez configure les cles SSH !)
## PasswordAuthentication no

## Desactiver la connexion root directe
PermitRootLogin prohibit-password

## Limiter les tentatives d'authentification par connexion
MaxAuthTries 3

## Fermer la connexion si pas d'auth en 30 secondes
LoginGraceTime 30

## Limiter le nombre de sessions SSH simultanees non authentifiees
MaxStartups 3:50:10

## Desactiver les methodes d'auth inutiles
KbdInteractiveAuthentication no
PermitEmptyPasswords no

## Algorithmes modernes uniquement
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Verifiez la syntaxe avant de recharger :

bash
## Tester la configuration SSH (ne redemarre rien)
sudo sshd -t

## Si pas d'erreur, recharger
sudo systemctl reload ssh

> Ne fermez pas votre session SSH actuelle. Ouvrez un nouveau terminal et testez la connexion. Si ca marche, vous pouvez fermer l'ancienne.

5. Script de monitoring

Un script rapide pour voir l'etat de toutes les jails d'un coup.

bash
sudo nano /usr/local/bin/f2b-status
bash
#!/bin/bash
## /usr/local/bin/f2b-status
## Affiche l'etat complet de Fail2ban

echo "=== Fail2ban Status ==="
echo ""

## Liste des jails
JAILS=$(sudo fail2ban-client status | grep 'Jail list' | sed 's/.*://;s/,//g')

TOTAL_BANNED=0

for jail in $JAILS; do
    STATUS=$(sudo fail2ban-client status "$jail" 2>/dev/null)
    BANNED=$(echo "$STATUS" | grep 'Currently banned' | awk '{print $NF}')
    TOTAL=$(echo "$STATUS" | grep 'Total banned' | awk '{print $NF}')
    FAILED=$(echo "$STATUS" | grep 'Currently failed' | awk '{print $NF}')
    
    echo "[$jail]"
    echo "  Bans actifs : $BANNED"
    echo "  Bans totaux : $TOTAL"
    echo "  Echecs en cours : $FAILED"
    
    if [ -n "$BANNED" ]; then
        TOTAL_BANNED=$((TOTAL_BANNED + BANNED))
    fi
    
    # Lister les IP bannies si il y en a
    BANNED_IPS=$(echo "$STATUS" | grep 'Banned IP list' | sed 's/.*://')
    if [ -n "$(echo $BANNED_IPS | tr -d ' ')" ]; then
        echo "  IPs bannies : $BANNED_IPS"
    fi
    echo ""
done

echo "=== Total bans actifs : $TOTAL_BANNED ==="
echo ""
echo "Derniers evenements :"
sudo tail -5 /var/log/fail2ban.log 2>/dev/null || sudo journalctl -u fail2ban -n 5 —no-pager
bash
## Rendre executable
sudo chmod +x /usr/local/bin/f2b-status

## Tester
sudo f2b-status

6. Depannage

Fail2ban ne demarre pas

bash
## Verifier la syntaxe de la configuration
sudo fail2ban-client -t

## Voir les logs detailles
sudo journalctl -u fail2ban -n 50 —no-pager

Erreur frequente : No file(s) found for glob /var/log/auth.log. Sur les systemes recents utilisant journald, il n'y a pas de fichier auth.log. Assurez-vous d'avoir backend = systemd dans votre config.

Fail2ban ne detecte rien

bash
## Tester le filtre manuellement
sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

## Verifier que le bon backend est utilise
sudo fail2ban-client get sshd logpath
sudo fail2ban-client get sshd journalmatch

Vous vous etes banni vous-meme

Si vous avez encore acces (console VPS, IPMI, KVM) :

bash
## Debannir votre IP
sudo fail2ban-client set sshd unbanip VOTRE_IP

## Ou, en dernier recours
sudo systemctl stop fail2ban
sudo iptables -F
sudo systemctl start fail2ban

Le ban incremental ne fonctionne pas

Verifiez que la base SQLite est active :

bash
## Verifier le chemin de la base
sudo fail2ban-client get dbfile

## Verifier les bans persistes
sudo sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "SELECT ip, jail, timeofban, bancount FROM bans ORDER BY timeofban DESC LIMIT 10;"

Les notifications Telegram n'arrivent pas

bash
## Tester l'envoi direct
curl -s -X POST "https://api.telegram.org/botVOTRE_TOKEN/sendMessage" \
    -d chat_id="VOTRE_CHAT_ID" \
    -d text="Test Fail2ban"

## Verifier que curl est installe
which curl || sudo apt install curl -y

Fail2ban utilise trop de RAM

Sur un petit VPS, la base SQLite peut grossir. Limitez la retention :

ini
## Dans jail.local, section [DEFAULT]
dbpurgeage = 7d

Les IPs bannies reviennent apres un reboot

Normal si dbfile n'est pas configure. Fail2ban 1.x persiste les bans par defaut dans SQLite, mais verifiez :

bash
sudo fail2ban-client get dbfile

Si la reponse est None, ajoutez dans jail.local :

ini
[DEFAULT]
dbfile = /var/lib/fail2ban/fail2ban.sqlite3

Conflit avec UFW ou firewalld

Si vous utilisez UFW, Fail2ban doit utiliser l'action ufw au lieu d'iptables :

ini
[DEFAULT]
banaction = ufw

Pour firewalld :

ini
[DEFAULT]
banaction = firewallcmd-rich-rules

7. Aller plus loin

Une fois Fail2ban en place, envisagez ces couches supplementaires :

  • Port knocking avec knockd : le port SSH n'est visible qu'apres avoir "frappe" sur une sequence de ports
  • Cles SSH + desactivation mots de passe : la meilleure protection contre la force brute, c'est de supprimer les mots de passe
  • CrowdSec : alternative/complement a Fail2ban avec partage communautaire des IPs malveillantes
  • Rate limiting au niveau reseau avec iptables ou nftables : limiter les nouvelles connexions SSH a 3/minute

Exemple de rate limiting nftables :

bash
sudo nft add rule inet filter input tcp dport 22 ct state new limit rate 3/minute accept
sudo nft add rule inet filter input tcp dport 22 ct state new drop

—-

Publie sur call-informatique.fr | Categorie : Cybersecurite
Sur le même sujet

À lire aussi

#tutoriel#guide-technique#fail2ban#ssh-hardening#intrusion-prevention