Sécurisation SSH avec Fail2Ban
Mise en place d'une solution de protection contre les attaques par force brute SSH sur un serveur Rocky Linux, incluant le durcissement de la configuration SSH et la détection/blocage automatique des tentatives d'intrusion.
Contexte et Objectifs
Dans le cadre de ce projet de sécurité Linux, j'ai mis en place un environnement de test permettant de simuler des attaques par force brute SSH et de démontrer l'efficacité des mesures de protection. L'objectif était de sécuriser un serveur Linux contre les tentatives d'intrusion via SSH en utilisant plusieurs couches de défense.
Technologies utilisées
Pourquoi cette solution ?
J'ai choisi Fail2Ban plutôt que DenyHosts ou SSHGuard pour sa légèreté, sa flexibilité et son excellente intégration avec FirewallD. Fail2Ban surveille les logs en temps réel et bannit automatiquement les IP malveillantes vià des règles de pare-feu. Sa configuration par "jails" permet de protéger facilement plusieurs services (SSH, Apache, Nginx) avec des paramètres personnalisés. C'est la solution de référence pour la protection contre les attaques par force brute sur Linux.
Infrastructure de Test
VM-DEFENSE
Serveur Rocky Linux cible à sécuriser. Héberge le service SSH et les solutions de protection (Fail2Ban, FirewallD).
VM-ATTAQUE
Machine d'attaque équipée de Hydra pour simuler les tentatives de force brute sur le service SSH.
Les deux machines virtuelles sont sur le même réseau VMware NAT (192.168.88.0/24) pour permettre les tests en toute sécurité.
Installation de Rocky Linux sur VM-DEFENSE dans VMware Workstation
Préparation initiale de la VM-DEFENSE : installation des paquets utiles et création du compte d'administration
Phase 1 : Simulation d'attaque avec Hydra
Installation de Hydra sur VM-ATTAQUE
J'ai commencé par installer Hydra sur la machine d'attaque. Hydra est un outil de force brute capable de tester rapidement de nombreuses combinaisons utilisateur/mot de passe contre divers services réseau.
# Installation de Hydra sur Rocky Linux sudo dnf install -y hydra # Vérification de l'installation hydra -h
Préparation des dictionnaires
Pour l'attaque, j'ai créé deux fichiers de dictionnaire : un pour les noms d'utilisateurs et un pour les mots de passe. Ces fichiers contiennent des combinaisons courantes.
# Fichier users.txt - Liste d'utilisateurs à tester cat > users.txt << EOF root admin user test guest EOF # Fichier passwords.txt - Liste de mots de passe à tester cat > passwords.txt << EOF 123456 password admin root qwerty letmein EOF
Exécution de l'attaque par dictionnaire
J'ai lancé l'attaque Hydra contre le service SSH de VM-DEFENSE pour tester toutes les combinaisons utilisateur/mot de passe de mes dictionnaires.
# Attaque par dictionnaire SSH hydra -L users.txt -P passwords.txt ssh://192.168.88.139 -t 4 -vV # Options utilisées : # -L : fichier de liste d'utilisateurs # -P : fichier de liste de mots de passe # -t 4 : 4 threads parallèles # -vV : mode verbose
Sans protection, Hydra à pu tester des centaines de combinaisons par minute, démontrant la vulnérabilité d'un serveur SSH non protégé face aux attaques par force brute.
Phase 2 : Durcissement SSH
Changement du port SSH
La première mesure de sécurité consiste à changer le port SSH par défaut (22) vers un port non standard (15000). Cela réduit considérablement les tentatives d'attaque automatisées qui ciblent le port 22.
# Modification du port SSH Port 15000 # Désactivation de l'accès root direct PermitRootLogin no # Activation de l'authentification par clé uniquement PubkeyAuthentication yes PasswordAuthentication no
Fichier de configuration /etc/ssh/sshd_config avec PermitRootLogin no
Configuration SELinux
SELinux étant actif sur Rocky Linux, j'ai dû autoriser le nouveau port SSH dans la politique de sécurité.
# Vérifier le statut SELinux getenforce Enforcing # Ajouter le port 15000 au contexte SSH sudo semanage port -a -t ssh_port_t -p tcp 15000 # Vérifier que le port est bien ajouté sudo semanage port -l | grep ssh ssh_port_t tcp 15000, 22
Ajustements système autour du nouveau port SSH avec vérification du contexte SELinux ssh_port_t
Configuration FirewallD
J'ai ensuite configuré FirewallD pour autoriser les connexions sur le nouveau port SSH et bloquer le port 22.
# Ajouter le nouveau port SSH sudo firewall-cmd --permanent --add-port=15000/tcp # Supprimer le service SSH standard (port 22) sudo firewall-cmd --permanent --remove-service=ssh # Recharger la configuration sudo firewall-cmd --reload # Vérifier les règles actives sudo firewall-cmd --list-all public (active) target: default interfaces: ens160 ports: 15000/tcp
Configuration du service SSH dans FirewallD avec le port 15000
Génération des clés SSH
Pour renforcer davantage la sécurité, j'ai mis en place l'authentification par clé publique/privée, qui est beaucoup plus sécurisée que les mots de passe.
# Sur la machine cliente - Générer la paire de clés ssh-keygen -t ed25519 -C "admin@vm-defense" # Copier la clé publique vers le serveur ssh-copy-id -p 15000 user@192.168.88.139 # Test de connexion avec la clé ssh -p 15000 user@192.168.88.139
Test de connexion SSH réussi sur le port 15000
Phase 3 : Déploiement de Fail2Ban
Fail2Ban est un framework de prévention d'intrusion qui surveille les fichiers de logs et bannit les adresses IP montrant des signes d'activité malveillante. Il fonctionne en détectant les tentatives d'authentification échouées répétées et en bloquant automatiquement les adresses IP sources vià des règles de pare-feu.
Installation de Fail2Ban
# Activer le dépôt EPEL sudo dnf install -y epel-release # Installer Fail2Ban sudo dnf install -y fail2ban fail2ban-firewalld # Activer et démarrer le service sudo systemctl enable --now fail2ban
Configuration de la jail SSH personnalisée
J'ai créé une jail personnalisée pour SSH avec des paramètres adaptés à notre configuration (port 15000) et des règles de bannissement strictes.
[DEFAULT] # Adresse email pour les notifications destemail = admin@localhost sender = fail2ban@localhost # Action par défaut : bannir via firewalld banaction = firewallcmd-rich-rules banaction_allports = firewallcmd-rich-rules [sshd] # Activer la jail SSH enabled = true # Port SSH personnalisé port = 15000 # Fichier de log à surveiller logpath = /var/log/secure # Nombre de tentatives avant bannissement maxretry = 5 # Fenêtre de temps pour compter les tentatives (10 minutes) findtime = 10m # Durée du bannissement (1 heure) bantime = 1h # Backend pour la détection backend = systemd
Avec cette configuration, une IP sera bannie pendant 1 heure après 5 tentatives échouées en 10 minutes. Ces valeurs peuvent être ajustées selon le niveau de sécurité souhaité.
Vérification de la configuration
# Redémarrer Fail2Ban pour appliquer la configuration sudo systemctl restart fail2ban # Vérifier le statut de la jail SSH sudo fail2ban-client status sshd 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:
Test du bannissement
J'ai relancé l'attaque Hydra depuis VM-ATTAQUE pour vérifier que Fail2Ban détecte et bloque bien les tentatives d'intrusion.
# Sur VM-DEFENSE - Vérifier les IP bannies sudo fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 23 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 1 |- Total banned: 1 `- Banned IP list: 192.168.88.138 # Vérifier les règles firewall sudo firewall-cmd --list-rich-rules rule family="ipv4" source address="192.168.88.138" port port="15000" protocol="tcp" reject
L'adresse IP de l'attaquant (192.168.88.138) a été automatiquement bannie après avoir dépassé le seuil de 5 tentatives échouées.
Status Fail2Ban montrant l'IP 192.168.88.138 bannie
Tentative de connexion refusée depuis l'IP bannie (timeout)
Phase 4 : Collecte des preuves
Pour une analyse forensique complète, j'ai collecté les logs pertinents montrant les tentatives d'attaque et les actions de Fail2Ban.
# Logs des tentatives SSH échouées sudo journalctl -u sshd | grep "Failed password" # Logs Fail2Ban sudo cat /var/log/fail2ban.log | grep -E "(Ban|Unban)" # Historique des IP bannies sudo fail2ban-client get sshd banip --with-time # Export des preuves horodatées sudo journalctl -u sshd --since "1 hour ago" > /tmp/ssh_evidence.log
2026-02-17 10:23:50,123 fail2ban.filter [1234]: INFO [sshd] Found 192.168.88.138 2026-02-17 10:23:50,456 fail2ban.actions [1234]: NOTICE [sshd] Ban 192.168.88.138 2026-02-17 11:23:50,789 fail2ban.actions [1234]: NOTICE [sshd] Unban 192.168.88.138
Archivage des fichiers de configuration et logs pour analyse forensique
Administration de Fail2Ban
# Débannir manuellement une IP sudo fail2ban-client set sshd unbanip 192.168.88.138 # Bannir manuellement une IP sudo fail2ban-client set sshd banip 192.168.88.138 # Voir toutes les IP bannies sudo fail2ban-client status sshd # Recharger la configuration sans redémarrer sudo fail2ban-client reload # Suivre les logs Fail2Ban en temps réel sudo tail -f /var/log/fail2ban.log
Débannissement manuel d'une IP avec fail2ban-client
Compétences Mobilisées
Recensement et documentation de l'infrastructure de test, gestion des configurations SSH et des règles de sécurité.
Détection et réponse automatisée aux tentatives d'intrusion, collecte de preuves pour analyse forensique.
Sécurisation des accès distants et protection des services exposés sur le réseau.
Planification et exécution méthodique des phases de test et de déploiement des solutions de sécurité.
Mise en oeuvre de Fail2Ban, durcissement SSH, configuration SELinux et FirewallD pour une défense en profondeur.
Administration système Linux, gestion des services systemd, configuration du pare-feu et des politiques SELinux.
Conclusion et Bilan
Ce projet m'a permis de mettre en pratique une approche de sécurité en profondeur pour protéger un service SSH contre les attaques par force brute. Les principales leçons apprises sont :
Défense multicouche
La combinaison de plusieurs mesures (changement de port, désactivation root, clés SSH, Fail2Ban) offre une protection bien plus robuste qu'une seule mesure isolée.
Automatisation de la réponse
Fail2Ban permet de réagir automatiquement aux menaces sans intervention manuelle, ce qui est essentiel pour un serveur en production.
Importance des logs
La collecte et l'analyse des logs sont cruciales pour comprendre les attaques et améliorer continuellement la posture de sécurité.
Test avant production
L'utilisation d'un environnement de test avec une VM d'attaque permet de valider les configurations avant déploiement en production.