Installer et configurer Fail2Ban sur un VPS Linux
Configurez Fail2Ban pour bloquer les attaques par force brute sur SSH et Nginx. Couvre les actions de bannissement UFW et nftables, les jails personnalisées, l'escalade recidive et le test de filtres sur Ubuntu 24.04 et Debian 12.
Fail2Ban surveille vos fichiers de logs à la recherche d'échecs d'authentification répétés et bannit les adresses IP fautives via votre pare-feu. Il stoppe les attaques par force brute avant qu'elles n'aboutissent. Un VPS fraîchement déployé reçoit généralement des tentatives de connexion SSH en quelques minutes. Fail2Ban est la défense standard.
Ce guide couvre l'installation sur Ubuntu 24.04 et Debian 12, la configuration des jails SSH et Nginx, les deux backends d'action de bannissement UFW et nftables, la jail recidive pour les récidivistes, et le test de filtres avec fail2ban-regex. Chaque modification de configuration est suivie d'une étape de vérification.
Prérequis : un VPS sous Ubuntu 24.04 ou Debian 12 avec un accès root ou sudo. Votre pare-feu doit déjà être actif et SSH doit être durci. Ce guide fait partie de la série sécurité VPS Linux.
Comment installer Fail2Ban sur Ubuntu 24.04 et Debian 12 ?
Installez Fail2Ban avec apt. Le paquet se trouve dans les dépôts par défaut des deux distributions. Ubuntu 24.04 fournit la version 1.0.2, Debian 12 également. Sur Debian 12, vous avez aussi besoin de python3-systemd pour que Fail2Ban puisse lire le journal systemd.
sudo apt update && sudo apt install -y fail2ban
Sur Debian 12, installez les bindings Python pour systemd :
sudo apt install -y python3-systemd
Activez et démarrez le service :
sudo systemctl enable --now fail2ban
Le flag enable fait démarrer Fail2Ban au boot. Le flag --now le démarre immédiatement. Vérifiez qu'il tourne :
sudo systemctl status fail2ban
Vous devez voir Active: active (running) dans la sortie. Si le statut affiche failed, consultez le journal :
journalctl -u fail2ban -n 20 --no-pager
Quelle est la différence entre jail.conf, jail.local et jail.d/ ?
jail.conf est le fichier de configuration par défaut livré avec le paquet. Les mises à jour du paquet l'écrasent. Ne modifiez jamais jail.conf directement. Vos changements disparaîtront au prochain apt upgrade.
jail.local est le fichier de surcharge traditionnel. Fail2Ban lit d'abord jail.conf, puis applique les paramètres de jail.local par-dessus. Ça fonctionne, mais le fichier finit par devenir un monolithe difficile à maintenir.
Le répertoire jail.d/ est la meilleure approche. Déposez un fichier .conf par jail. Fail2Ban les charge par ordre alphabétique après jail.conf et jail.local. Chaque service reste isolé et il est facile d'ajouter ou de supprimer des jails sans toucher aux autres configurations.
Ce guide utilise les fichiers drop-in dans jail.d/. Vérifiez que le répertoire existe :
ls /etc/fail2ban/jail.d/
Il devrait déjà exister. Si vous voyez des fichiers comme defaults-debian.conf, c'est normal. Sur Ubuntu 24.04, ce fichier active la jail sshd et définit banaction = nftables comme action de bannissement par défaut. Sur Debian 12, il active la jail sshd. Comme Fail2Ban charge les fichiers de jail.d/ par ordre alphabétique, tout fichier de défauts personnalisé doit se trier après defaults-debian.conf pour en écraser les paramètres. Ce guide utilise zz-defaults.conf pour cette raison.
Comment configurer la jail SSH dans Fail2Ban ?
La jail SSH surveille les logs d'authentification et bannit les IP qui échouent trop de fois à se connecter. Sur Ubuntu 24.04 et Debian 12, la jail sshd est activée par défaut via /etc/fail2ban/jail.d/defaults-debian.conf. Mais les valeurs par défaut sont laxistes (5 tentatives, bannissement de 10 minutes). Resserrez-les.
Créez un fichier de configuration drop-in :
sudo tee /etc/fail2ban/jail.d/sshd.conf > /dev/null << 'EOF'
[sshd]
enabled = true
mode = aggressive
port = ssh
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600
EOF
Signification de chaque paramètre :
| Paramètre | Valeur | Signification |
|---|---|---|
enabled |
true |
Active cette jail |
mode |
aggressive |
Détecte davantage de motifs d'échec SSH, y compris les échecs d'authentification par clé |
port |
ssh |
Surveille le port SSH (résolu en 22, ou votre port personnalisé) |
backend |
systemd |
Lit le journal systemd au lieu des fichiers de log |
maxretry |
3 |
Bannit après 3 tentatives échouées |
findtime |
600 |
Compte les échecs sur une fenêtre de 10 minutes |
bantime |
3600 |
Bannit pendant 1 heure (3600 secondes) |
Si vous avez changé votre port SSH (vous devriez), remplacez ssh par votre numéro de port :
port = 2222
Redémarrez Fail2Ban pour appliquer :
sudo systemctl restart fail2ban
Vérifiez que la jail est active :
sudo fail2ban-client status sshd
Sortie attendue :
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
la ligne Journal matches confirme que Fail2Ban lit le journal systemd et non un fichier de log. C'est correct pour Ubuntu 24.04 et Debian 12.
Comment configurer Fail2Ban avec UFW comme action de bannissement ?
Si vous utilisez UFW comme pare-feu, configurez Fail2Ban pour insérer les règles de bannissement via UFW. C'est le chemin le plus simple, adapté à la plupart des configurations.
Créez un fichier de défauts qui définit UFW comme action de bannissement. Le nom zz-defaults.conf est intentionnel : sur Ubuntu 24.04, le paquet livre defaults-debian.conf qui définit banaction = nftables. Votre fichier doit se trier alphabétiquement après pour écraser ce défaut.
sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = ufw
banaction_allports = ufw
backend = systemd
EOF
Redémarrez et vérifiez :
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Quand Fail2Ban bannit une IP, il exécute ufw insert 1 deny from <IP> to any. Vérifiez les règles UFW après un bannissement :
sudo ufw status numbered
Vous verrez les règles deny de Fail2Ban en haut de la liste.
Comment configurer Fail2Ban pour utiliser nftables au lieu d'iptables ?
Pour les serveurs de production utilisant nftables directement (sans UFW), utilisez l'action de bannissement nftables-multiport. Fail2Ban crée sa propre table nftables et y gère les règles de bannissement sans interférer avec votre jeu de règles existant.
Créez le fichier de défauts. Sur Ubuntu 24.04, defaults-debian.conf définit déjà banaction = nftables, donc cette étape est techniquement optionnelle. Mais il est préférable d'être explicite. Sur Debian 12, ce fichier est requis.
sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = nftables-multiport
banaction_allports = nftables[type=allports]
chain = input
backend = systemd
EOF
Redémarrez et vérifiez :
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Pour confirmer l'intégration nftables, listez la table Fail2Ban :
sudo nft list tables
La sortie affiche une table nommée inet f2b-table. Après un bannissement, inspectez son contenu :
sudo nft list table inet f2b-table
Comparaison des actions de bannissement UFW et nftables
| Aspect | UFW (banaction = ufw) |
nftables (banaction = nftables-multiport) |
|---|---|---|
| Commande de bannissement | ufw insert 1 deny from <IP> |
Ajoute l'IP à un ensemble nftables |
| Où apparaissent les règles | ufw status numbered |
nft list table inet f2b-table |
| Support IPv6 | Oui (UFW le gère) | Oui (famille inet) |
| Persistance | Les règles UFW persistent au redémarrage | Fail2Ban les réapplique au démarrage |
| Performance | Correspondance linéaire des règles | Recherche par ensemble (plus rapide à grande échelle) |
| Adapté pour | Configurations simples, service unique | Production, nombreuses jails, grand nombre de bannissements |
Choisissez une seule approche. Ne mélangez pas les actions de bannissement UFW et nftables sur le même serveur.
Comment ajouter mon adresse IP en liste blanche dans Fail2Ban ?
Ajoutez votre IP à ignoreip pour éviter de vous bannir vous-même. C'est important. Si vous tapez mal votre mot de passe trois fois, Fail2Ban bannira votre propre IP. Vous perdrez l'accès SSH.
Ajoutez votre IP aux défauts :
sudo tee /etc/fail2ban/jail.d/01-whitelist.conf > /dev/null << 'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_IP_HERE
EOF
Remplacez YOUR_IP_HERE par votre adresse IP publique réelle. Vous pouvez la trouver en exécutant curl -4 ifconfig.me depuis votre machine locale. Ajoutez plusieurs IP séparées par des espaces.
Redémarrez et vérifiez que la liste blanche est chargée :
sudo systemctl restart fail2ban
sudo fail2ban-client get sshd ignoreip
La sortie liste toutes les IP et plages en liste blanche. Confirmez que votre IP y figure.
Attention : si vous vous connectez depuis une IP dynamique, l'ajouter en liste blanche offre une protection limitée. Gardez un moyen d'accès secondaire (accès console depuis le panneau de votre hébergeur) comme solution de secours en cas de bannissement.
Comment protéger Nginx avec des jails Fail2Ban personnalisées ?
Fail2Ban est livré avec plusieurs filtres Nginx. Les plus utiles sont nginx-http-auth pour la force brute sur l'authentification HTTP basique et nginx-botsearch pour les scanners qui sondent des chemins inexistants. Vous pouvez aussi écrire des filtres personnalisés pour des motifs spécifiques à votre application.
Jail nginx-http-auth
Cette jail bannit les IP qui échouent de manière répétée à l'authentification HTTP basique. Elle lit le log d'erreur Nginx.
sudo tee /etc/fail2ban/jail.d/nginx-http-auth.conf > /dev/null << 'EOF'
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
findtime = 600
bantime = 3600
EOF
Jail nginx-botsearch
Cette jail attrape les bots qui scannent les chemins vulnérables (/wp-admin, /phpmyadmin, /.env). Elle lit le log d'accès Nginx pour les réponses 404.
sudo tee /etc/fail2ban/jail.d/nginx-botsearch.conf > /dev/null << 'EOF'
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 7200
EOF
Filtre personnalisé : bannir les erreurs 4xx excessives
Pour les applications derrière Nginx, vous pourriez vouloir bannir les IP qui génèrent trop d'erreurs 4xx. Cela attrape le bourrage d'identifiants (credential stuffing), l'abus d'API et l'énumération de chemins. Les filtres intégrés ne couvrent pas ce cas, alors créez un filtre personnalisé.
Créez le fichier de filtre :
sudo tee /etc/fail2ban/filter.d/nginx-4xx.conf > /dev/null << 'EOF'
[Definition]
failregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
ignoreregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ /favicon\.ico
^<HOST> - \S+ \[.*\] "[A-Z]+ /robots\.txt
EOF
La failregex correspond aux lignes du log d'accès Nginx où la réponse est un code 4xx. La ignoreregex exclut les faux positifs courants comme les requêtes favicon.ico et robots.txt.
Créez la jail :
sudo tee /etc/fail2ban/jail.d/nginx-4xx.conf > /dev/null << 'EOF'
[nginx-4xx]
enabled = true
port = http,https
filter = nginx-4xx
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 600
bantime = 3600
EOF
Le maxretry plus élevé de 20 évite de bannir les utilisateurs légitimes qui rencontrent quelques 404 en navigation normale.
Redémarrez Fail2Ban et vérifiez que toutes les jails sont chargées :
sudo systemctl restart fail2ban
sudo fail2ban-client status
Sortie attendue montrant toutes les jails actives :
Status
|- Number of jail: 4
`- Jail list: nginx-4xx, nginx-botsearch, nginx-http-auth, sshd
Pour en savoir plus sur la protection de Nginx au niveau applicatif, consultez le guide sur le rate limiting Nginx.
Comment tester les filtres Fail2Ban avec fail2ban-regex ?
Avant d'activer une jail, testez son filtre sur de vrais logs. L'outil fail2ban-regex exécute un filtre contre un fichier de log et rapporte les correspondances. Cela évite de déployer un filtre qui ne correspond à rien (inutile) ou qui correspond à tout (bannit les utilisateurs légitimes).
Testez le filtre personnalisé nginx-4xx :
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf
Exemple de sortie :
Running tests
=============
Use failregex filter file : nginx-4xx, basedir: /etc/fail2ban
Use log file : /var/log/nginx/access.log
Use encoding : utf-8
Results
=======
Failregex: 42 total
|- #) [# of hits] regular expression
| 1) [42] ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
`-
Ignoreregex: 3 total
Date template hits:
...
Lines: 1842 lines, 0 ignored, 42 matched, 1800 missed
la sortie montre 42 lignes correspondantes sur 1842. C'est un ratio raisonnable. Si le filtre correspondait à 90 % des lignes, la regex est trop large. S'il correspondait à 0 ligne, soit la regex est fausse, soit le log ne contient pas encore d'erreurs 4xx.
Pour voir quelles lignes ont correspondu :
sudo fail2ban-regex --print-all-matched /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf
Pour voir quelles lignes n'ont pas correspondu (utile pour affiner) :
sudo fail2ban-regex --print-all-missed /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf
Testez le filtre sshd intégré contre le journal systemd :
sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf
Comment configurer la jail recidive pour les récidivistes ?
La jail recidive surveille le propre log de Fail2Ban. Quand une IP est bannie plusieurs fois dans n'importe quelle jail, la jail recidive applique un bannissement plus long. C'est une escalade : première infraction = 1 heure, récidivistes = 1 semaine.
Sur un serveur de production actif, c'est la jail recidive qui tient réellement les attaquants persistants à distance.
sudo tee /etc/fail2ban/jail.d/recidive.conf > /dev/null << 'EOF'
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
maxretry = 3
findtime = 86400
bantime = 604800
EOF
| Paramètre | Valeur | Signification |
|---|---|---|
logpath |
/var/log/fail2ban.log |
Chemin de log de secours. Avec backend = systemd, Fail2Ban lit ses propres entrées de journal à la place (le filtre recidive a une directive journalmatch intégrée) |
maxretry |
3 |
Se déclenche après 3 bannissements par d'autres jails |
findtime |
86400 |
Remonte sur 24 heures (86400 secondes) |
bantime |
604800 |
Bannit pendant 1 semaine (604800 secondes) |
banaction |
%(banaction_allports)s |
Bloque tous les ports, pas seulement celui qui a déclenché le bannissement |
Le filtre recidive est livré avec Fail2Ban dans /etc/fail2ban/filter.d/recidive.conf. Pas besoin de le créer.
Redémarrez et vérifiez :
sudo systemctl restart fail2ban
sudo fail2ban-client status recidive
Comment surveiller les bannissements et débannir une adresse IP ?
Fail2Ban fournit fail2ban-client pour toutes les tâches de surveillance et de gestion. Ces commandes fonctionnent quel que soit votre backend d'action de bannissement.
Vérifier le statut global
sudo fail2ban-client status
Liste toutes les jails actives et leurs compteurs de bannissement.
Vérifier une jail spécifique
sudo fail2ban-client status sshd
Affiche les IP actuellement bannies, le total des bannissements et les échecs en cours.
Bannir manuellement une IP
sudo fail2ban-client set sshd banip 203.0.113.50
Débannir une IP
sudo fail2ban-client set sshd unbanip 203.0.113.50
Si l'IP a été bannie par la jail recidive, débannissez-la là aussi :
sudo fail2ban-client set recidive unbanip 203.0.113.50
Vérifier quelle action de bannissement utilise une jail
sudo fail2ban-client get sshd actions
Recharger la configuration sans redémarrer
sudo fail2ban-client reload
Lire le log Fail2Ban
journalctl -u fail2ban -f
Cela suit le log du service Fail2Ban en temps réel. Vous verrez les événements de bannissement et de débannissement au fil de leur apparition.
Le log applicatif de Fail2Ban avec les détails des bannissements :
sudo tail -f /var/log/fail2ban.log
Référence des commandes fail2ban-client
| Commande | Fonction |
|---|---|
fail2ban-client status |
Lister toutes les jails |
fail2ban-client status <jail> |
Afficher les détails d'une jail et les IP bannies |
fail2ban-client set <jail> banip <IP> |
Bannir manuellement une IP |
fail2ban-client set <jail> unbanip <IP> |
Débannir une IP |
fail2ban-client reload |
Recharger toute la configuration |
fail2ban-client reload <jail> |
Recharger une seule jail |
fail2ban-client get <jail> bantime |
Afficher la durée du bannissement |
fail2ban-client get <jail> findtime |
Afficher la fenêtre de comptage des échecs |
fail2ban-client get <jail> maxretry |
Afficher le seuil de tentatives |
fail2ban-client get <jail> ignoreip |
Afficher les IP en liste blanche |
fail2ban-client get <jail> actions |
Afficher l'action de bannissement utilisée |
Vérification de bout en bout : déclencher un bannissement et confirmer le fonctionnement
Ne partez pas du principe que votre configuration fonctionne. Testez-la. Déclenchez un vrai bannissement et vérifiez toute la chaîne : détection dans les logs, action de bannissement, règle de pare-feu et débannissement.
Étape 1 : depuis une autre machine (pas votre IP en liste blanche), tentez des connexions SSH avec un mauvais mot de passe. Après 3 échecs (correspondant à maxretry), la connexion devrait être refusée.
Si vous n'avez pas de seconde machine, utilisez fail2ban-client pour simuler un bannissement :
sudo fail2ban-client set sshd banip 198.51.100.25
Étape 2 : vérifiez que le bannissement est enregistré :
sudo fail2ban-client status sshd
L'IP bannie devrait apparaître dans Banned IP list.
Étape 3 : vérifiez que la règle de pare-feu existe.
Pour UFW :
sudo ufw status numbered | grep 198.51.100.25
Pour nftables :
sudo nft list table inet f2b-table
L'IP devrait apparaître dans un ensemble à l'intérieur de la table.
Étape 4 : débannissez et vérifiez la suppression :
sudo fail2ban-client set sshd unbanip 198.51.100.25
sudo fail2ban-client status sshd
L'IP ne devrait plus apparaître dans la liste des bannissements. Vérifiez à nouveau le pare-feu pour confirmer que la règle a été supprimée.
Référence des paramètres de configuration Fail2Ban
| Paramètre | Défaut | Recommandé | Description |
|---|---|---|---|
bantime |
10m |
1h ou 3600 |
Durée du bannissement |
findtime |
10m |
10m ou 600 |
Fenêtre de comptage des échecs |
maxretry |
5 |
3 pour SSH, 5-20 pour le web |
Échecs avant bannissement |
ignoreip |
127.0.0.1/8 ::1 |
Ajoutez votre IP | IP jamais bannies |
banaction |
nftables (Ubuntu 24.04), iptables-multiport (amont) |
ufw ou nftables-multiport |
Commande de pare-feu à exécuter |
backend |
auto |
systemd |
Source des logs (journal systemd sur les distributions modernes) |
destemail |
root@localhost |
Votre email | Destinataire des alertes |
action |
%(action_)s |
%(action_mwl)s pour les alertes email |
Action déclenchée lors d'un bannissement |
Quelque chose ne fonctionne pas ?
Fail2Ban ne démarre pas : vérifiez les erreurs de syntaxe dans vos fichiers de jail. Un crochet manquant ou une valeur invalide empêchera le démarrage.
sudo fail2ban-client -t
Cela teste la configuration sans démarrer le service. Corrigez les erreurs signalées.
La jail affiche 0 correspondance alors que des attaques ont lieu : le backend est probablement incorrect. Sur Ubuntu 24.04 et Debian 12, utilisez backend = systemd. Si vous utilisez backend = auto et que le système n'a pas de /var/log/auth.log, Fail2Ban ne lit rien.
L'IP bannie peut toujours se connecter : l'action de bannissement ne correspond pas à votre pare-feu. Si vous utilisez UFW, définissez banaction = ufw. Si vous utilisez nftables directement, définissez banaction = nftables-multiport. Vérifiez que la règle de pare-feu existe bien après un bannissement.
Vous vous êtes banni vous-même : accédez à votre serveur via la console web de votre hébergeur (VNC/KVM). Depuis celle-ci :
sudo fail2ban-client set sshd unbanip YOUR_IP
Ou arrêtez complètement Fail2Ban :
sudo systemctl stop fail2ban
Ensuite, corrigez votre configuration ignoreip et redémarrez.
Fail2Ban consomme trop de mémoire : sur les serveurs avec de gros fichiers de log, Fail2Ban peut consommer de la mémoire. Définissez dbpurgeage pour limiter la taille de la base de données :
sudo tee /etc/fail2ban/jail.d/99-performance.conf > /dev/null << 'EOF'
[DEFAULT]
dbpurgeage = 7d
EOF
Copyright 2026 Virtua.Cloud. Tous droits réservés. Ce contenu est une création originale de l'équipe Virtua.Cloud. Toute reproduction, republication ou redistribution sans autorisation écrite est interdite.