Pourquoi auto-héberger Fail2ban sur un VPS
Fail2ban est l'un des outils de protection les plus simples et les plus répandus pour un serveur exposé : il lit en continu vos journaux, applique des expressions régulières (les filtres) pour repérer les tentatives d'intrusion, et bannit l'IP fautive en l'ajoutant à nftables ou iptables pour une durée configurable. Sur un VPS, c'est une première ligne de défense à poser avant le reste, parce qu'il ne dépend d'aucun service externe, consomme peu et protège SSH contre le bruteforce dès l'activation du jail. Au-delà de SSH, vous pouvez l'étendre à Nginx (tentatives d'authentification, scans d'URL), Postfix, WordPress ou tout service qui écrit des journaux. Tout fonctionne en local sur votre machine : aucune donnée ne sort, aucun service tiers n'intervient. C'est une solution autonome et facile à auditer, à condition de la vérifier de temps en temps, comme nous le verrons plus bas.
Les bénéfices concrets de ce template
- Bannissement automatique — les IP qui forcent SSH sont bannies dès que le seuil
maxretryest atteint dans la fenêtrefindtime. - Filtres pour de nombreux services — SSH, Nginx, Apache, Postfix, WordPress, et filtres personnalisés écrits dans
filter.d. - Empreinte minimale — il tourne sans souci sur le plus petit des VPS.
- Bannissement progressif (récidive) — plus une IP récidive, plus le bannissement est long.
- Notifications par e-mail — possibles à chaque bannissement, avec les actions
action_mwouaction_mwldejail.conf. - Autonome et local — aucune dépendance réseau au quotidien, simple à auditer et à versionner.
Prérequis chiffrés pour l'héberger
Fail2ban est frugal : un VPS de 1 vCPU et 512 Mo de RAM suffit pour l'exécuter, sans impact perceptible (recommandation éditoriale, à mesurer sur votre charge). Côté logiciel, le README amont de la version 1.1.1 demande Python 3.5 ou plus. Deux composants sont optionnels : pyinotify 0.8.3 ou plus pour surveiller les fichiers (noyau Linux 2.6.13 ou plus), et systemd 204 ou plus avec le paquet python-systemd pour lire le journal. Fail2ban s'installe directement sur le système (pas besoin de Docker) et exige un accès root, un backend de pare-feu (nftables ou iptables) et l'accès aux journaux des services à protéger : le journal systemd ou /var/log/auth.log pour SSH selon la distribution, les journaux access et error de Nginx. Il garde son état dans une base SQLite, /var/lib/fail2ban/fail2ban.sqlite3 par défaut. Aucun domaine ni port supplémentaire n'est nécessaire. La règle d'or : renseignez ignoreip avec votre IP avant d'activer le bannissement, pour ne pas vous verrouiller hors de votre propre serveur.
Installer et configurer Fail2ban sur votre VPS
Installer Fail2ban
Sur Debian ou Ubuntu :
sudo apt update && sudo apt install fail2ban. Le service démarre automatiquement. Vérifiez avecsudo systemctl status fail2ban.Créer un jail.local
Ne modifiez jamais
jail.confdirectement. Écrivez vos réglages dans/etc/fail2ban/jail.local, qui les surcharge : c'est là que se définissentbantime,findtime,maxretryet surtoutignoreip = 127.0.0.1/8 ::1 VOTRE_IPpour vous protéger d'un auto-bannissement. Les valeurs par défaut dejail.confsontbantime = 10m,findtime = 10metmaxretry = 5.Activer la protection SSH
Tous les jails sont désactivés par défaut dans
jail.conf: activez explicitement[sshd]dansjail.localavecenabled = true, par exemplemaxretry = 3etbantime = 1h. Après 3 échecs dans la fenêtrefindtime, l'IP est bannie une heure au niveau du pare-feu.Ajouter un jail pour Nginx
Activez les jails
[nginx-http-auth]et[nginx-botsearch], fournis parjail.conf, en vérifiant quelogpathpointe vers vos journaux Nginx. Cela bloque les tentatives d'authentification répétées et les scans d'URL malveillants.Tester la configuration puis la recharger
Contrôlez d'abord la syntaxe :
sudo fail2ban-client -t. Puis appliquez-la :sudo fail2ban-client reload(ousudo systemctl restart fail2ban).sudo fail2ban-client statusliste les jails actifs etsudo fail2ban-client status sshdmontre les IP actuellement bannies.Tester un bannissement et le débannissement
Vérifiez le filtre sur votre propre journal avec
sudo fail2ban-regex systemd-journal sshd. Pour simuler un bannissement sans attaquer personne :sudo fail2ban-client set sshd banip 203.0.113.10, puis lisezsudo fail2ban-client status sshd. Pour libérer une IP légitime bloquée par erreur :sudo fail2ban-client set sshd unbanip X.X.X.X.Se connecter la première fois
Il n'y a aucune interface web ni compte à créer : fail2ban est un démon système qui, avec le réglage du template, bannit les IP après 4 échecs SSH en 10 minutes. En SSH :
fail2ban-client status sshd(IP bannies),fail2ban-client set sshd unbanip <IP>(débannir). Ajustez ces seuils dansjail.local.
ignoreip, durée de bannissement et récidive
ignoreip accepte des adresses IP, des masques CIDR ou des noms d'hôte DNS, séparés par des espaces ou des virgules. Par défaut, ignoreself = true : les adresses locales du serveur ne sont jamais bannies, mais votre IP de bureau ou de domicile ne l'est pas pour autant. Si elle change souvent, déclarez un nom d'hôte dynamique ou utilisez ignorecommand, une commande externe qui reçoit l'IP et répond si elle doit être ignorée. Gardez aussi un accès de secours indépendant de SSH, comme la console de votre fournisseur de VPS : un auto-bannissement se règle alors sans intervention extérieure. La durée se règle avec bantime, en secondes ou avec les suffixes m, h, d, w, mo et y. Elle sert de durée initiale quand le bannissement progressif est activé. Pour les récidivistes, jail.conf fournit aussi un jail recidive, qui relit le journal de fail2ban lui-même.
Bannissement progressif : formule, plafond et mémoire
Activez le bannissement progressif dans jail.local avec bantime.increment = true. La formule par défaut multiplie bantime par 1, 2, 4, 8, 16 et ainsi de suite à chaque récidive ; bantime.factor (1 par défaut) est un multiplicateur commun, et bantime.maxtime plafonne la durée en secondes, par exemple bantime.maxtime = 604800 pour sept jours. Un point se rate souvent : fail2ban retrouve les anciens bannissements dans sa base, purgée selon dbpurgeage (un jour par défaut dans fail2ban.conf). Pour que des récidives espacées soient retrouvées, relevez-le ; le commentaire du jail recidive dans jail.conf cite 648000 secondes. Couplez le tout à la désactivation de l'authentification par mot de passe (clés SSH uniquement) : Fail2ban devient alors un filet de sécurité plutôt que votre unique rempart.
Choisir le backend : auto, pyinotify, polling ou systemd
Le backend est la façon dont un jail lit ses journaux. La valeur par défaut de jail.conf est backend = auto, que chaque jail peut surcharger. Sur Debian et Ubuntu, le fichier paths-debian.conf de l'archive amont 1.1.1 fixe sshd_backend = systemd : sshd est alors lu dans le journal systemd, pas dans /var/log/auth.log. Lisez sudo fail2ban-client status sshd pour savoir ce qui est réellement surveillé : la ligne File list indique des fichiers, la ligne Journal matches indique le journal. Une distribution peut modifier ces valeurs, donc ne présumez rien : constatez. Changer de backend se fait jail par jail, dans jail.local, puis sudo fail2ban-client reload.
Les quatre backends de Fail2ban
Faites défiler le tableau
| Backend | Ce qu'il surveille | À retenir |
|---|---|---|
| auto | Des fichiers (pyinotify puis polling) ; bascule vers systemd si aucun fichier de `logpath` n'existe et que le filtre définit `journalmatch` | Valeur par défaut de `jail.conf` |
| pyinotify | Des fichiers, via les événements inotify du noyau | Linux seulement, module Python pyinotify requis ; mieux adapté aux fichiers que polling selon la documentation |
| polling | Des fichiers, par relecture à intervalle régulier | Aucune bibliothèque externe, repli le plus simple |
| systemd | Le journal systemd, via python-systemd | `logpath` n'est pas valide ; le filtre passe par `journalmatch` ; réglages `journalflags` et `rotated` |
Vérifier que le jail surveille encore
Un jail démarré n'est pas forcément un jail qui lit. Signalement rapporté, non confirmé par la maintenance : dans le ticket fail2ban n° 4250, ouvert en octobre 2026, un administrateur sous Debian avec fail2ban 1.1.1 décrit un jail sshd en backend systemd qui cesse de bannir un à deux jours après le démarrage, alors que ses jails Nginx et Postfix continuent de fonctionner. Deux autres administrateurs, tous deux sous FreeBSD d'après leurs messages, rapportent un symptôme voisin avec le backend pyinotify ; l'un dit être revenu à la stabilité en passant en polling. Un mainteneur a fait remarquer que le ticket d'origine portait sur le backend systemd et que les deux symptômes ne sont peut-être pas liés. Un dernier participant, sous Arch avec le backend systemd, décrit le même arrêt après une rotation du journal et avance une hypothèse sur le réglage rotated : elle reste non confirmée. La cause n'est pas établie à ce jour, et rien ne permet de généraliser à votre serveur. Le contrôle, lui, coûte une minute.
Contrôler en quatre gestes que le jail lit toujours
Lire l'état du jail
sudo fail2ban-client status sshdafficheCurrently failedetTotal failedpour le filtre,File listouJournal matchespour la source, puisCurrently banned,Total bannedetBanned IP listpour l'action. NotezTotal failed.Comparer avec le journal
Comptez les échecs réels sur la même période :
sudo journalctl _COMM=sshd --since "1 hour ago" | grep -c "Failed password", ousudo grep -c "Failed password" /var/log/auth.logsi le jail lit ce fichier. Relisez ensuiteTotal failed: il doit avoir progressé. Comparez la tendance, pas l'égalité exacte, car les IP deignoreipne comptent pas.Lire le journal de fail2ban
sudo tail -n 50 /var/log/fail2ban.log: un jail en bonne santé écrit des lignesFoundpuisBan. Plusieurs jours de lignesUnbanseules, alors que le journal d'authentification montre des tentatives, désignent un jail aveugle.Relancer et changer de backend si besoin
sudo systemctl restart fail2banrelance la lecture ; le ticket décrit un fonctionnement normal pendant un à deux jours après chaque démarrage. Pour un jail de fichiers,backend = pollingest le repli le plus simple. Planifiez ce contrôle (cron ou outil de supervision) plutôt que de compter sur l'absence d'alerte.
Dépannage : les messages d'erreur réels
Ces messages viennent du code source de Fail2ban 1.1.1 (clients et lecteurs de configuration) ; le niveau de journalisation par défaut est INFO. Pour chaque cas, la commande de départ est la même : sudo fail2ban-client -t teste la configuration, sudo journalctl -u fail2ban donne le début de l'histoire.
Messages d'erreur courants et remèdes
Have not found any log file for 'sshd' jail.— lelogpathdu jail ne désigne aucun fichier existant et le démarrage échoue, sauf siskip_if_nologs = true. En backendauto, un jail dont le filtre définitjournalmatchbascule sur systemd à la place. Corrigez le chemin ou fixezbackend = systemd.No file(s) found for glob /var/log/nginx/error.log— un motif delogpathne correspond à rien. Vérifiez l'emplacement réel des journaux Nginx avecls /var/log/nginx.Unable to read the filter 'nginx-xyz'— le nom donné àfilter =n'existe pas dansfilter.d. Corrigez la faute de frappe ou ajoutez votre fichier de filtre.Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?— le client ne trouve pas le socket du serveur. Le service est arrêté ou en échec :sudo systemctl status fail2ban, puis le journal.Permission denied to socket: ... (you must be root)— la commandefail2ban-clienta été lancée sans les droits suffisants. Relancez-la avecsudo.Unable to contact server. Is it running?— le socket existe mais le serveur ne répond pas. Redémarrez le service puis relisez son journal de démarrage.[sshd] Journal reader seems to be offline, reopen journal— fail2ban a détecté que sa lecture du journal systemd s'était interrompue (rotation) et la rouvre. Ce message est de niveauMSG, sousINFO: son absence dans un journal normal ne prouve rien, d'où le contrôle de la section précédente.Error reading line from systemd journal— erreur de lecture du journal systemd, suivie de la cause système. Vérifiez les droits du service et l'état du journal avecjournalctl --verify.
nftables ou iptables, pare-feu du VPS et sauvegarde
L'action de bannissement se choisit avec banaction. jail.conf propose iptables-multiport en exemple commenté ; le fichier paths-debian.conf de l'archive 1.1.1 fixe banaction = nftables et banaction_allports = nftables[type=allports]. L'action nftables crée par défaut la table f2b-table (famille inet) et la chaîne f2b-chain, accrochée à l'entrée avec la priorité -1 ; sudo nft list table inet f2b-table montre les IP bannies. Choisissez une seule famille d'actions, la même que le reste de votre pare-feu, sinon vous cherchez vos règles dans la mauvaise table. Le pare-feu du VPS agit en amont : il filtre ce qui atteint la machine, par exemple en limitant SSH à vos adresses, tandis que Fail2ban réagit à ce que les journaux racontent. Les deux se complètent, mais veillez à ce que ignoreip reste cohérent avec vos règles. Derrière un proxy ou un CDN, les journaux affichent l'IP du proxy : restituez la vraie IP avant de bannir, faute de quoi vous bannissez le proxy. Côté sauvegarde, archivez la configuration (sudo tar czf fail2ban-config.tar.gz /etc/fail2ban) et la sortie de sudo fail2ban-client --dp, qui documente la configuration effective. La base /var/lib/fail2ban/fail2ban.sqlite3 conserve la mémoire des bannissements.
La documentation officielle
Pour la configuration avancée, les options propres à l’outil et les changements de version, référez-vous à la documentation officielle de Fail2Ban. Ce guide couvre la mise en ligne sur VPS ServOrbit ; la documentation éditeur reste la référence pour les réglages fins.