Comment stopper les attaques par force brute SSH
Dernière mise à jour:
Un serveur dont le port 22 est ouvert sur internet reçoit des tentatives de mot de passe quelques minutes après son démarrage, toute la journée, depuis des milliers d'adresses. Ce sont presque toujours des bots qui essaient root, admin et des noms courants avec des listes de mots de passe divulgués. Ils n'entrent que là où un mot de passe est faible, mais ils remplissent les journaux, consomment du CPU, et un seul compte faible suffit.
La solution se construit par couches : rendre les mots de passe inutiles (clés uniquement), écarter root, puis bannir et limiter ce qui reste. Les commandes ci-dessous valent pour Debian et Ubuntu, et pour la famille RHEL (RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora).
Vérifier si vous êtes attaqué
Le démon SSH journalise chaque tentative échouée. Comptez celles des dernières 24 heures, puis regardez quelles adresses en envoient le plus :
sudo journalctl --since "24 hours ago" | grep -cE "Failed password|Invalid user"sudo journalctl --since "24 hours ago" \
| grep -E "Failed password|Invalid user" \
| grep -oE "from [0-9a-fA-F.:]+ port" | awk '{print $2}' \
| sort | uniq -c | sort -rn | head -20Des centaines ou des milliers de lignes par jour, c'est normal pour un serveur sur une IP publique. Si le journal n'est pas conservé d'un redémarrage à l'autre, les mêmes lignes se trouvent dans /var/log/auth.log sur Debian et Ubuntu, et dans /var/log/secure sur la famille RHEL.
Mettre en place les clés SSH et les tester d'abord
Tout ce qui suit désactive les mots de passe : il faut donc d'abord une clé qui fonctionne. Sur votre ordinateur, créez une clé, copiez-la sur le serveur et connectez-vous avec. Remplacez deploy par votre utilisateur et SERVER_IP par l'adresse du serveur.
ssh-keygen -t ed25519 -C "laptop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@SERVER_IP
ssh -i ~/.ssh/id_ed25519 deploy@SERVER_IPLa dernière commande doit vous connecter sans demander le mot de passe du compte (elle peut demander la phrase de passe de la clé, qui reste sur votre ordinateur).
Attention: À partir d'ici, gardez une session SSH ouverte sur le serveur et faites chaque test depuis un second terminal. Si une modification vous enferme dehors, c'est cette session ouverte qui vous permet de l'annuler. Repérez aussi la console web de votre hébergeur (VNC ou série) avant de commencer : elle fonctionne sans SSH.
Créer un utilisateur sudo avant de désactiver root
Si vous vous connectez aujourd'hui en root, créez d'abord un utilisateur normal avec les droits sudo, et donnez-lui les mêmes clés.
sudo adduser deploy
sudo usermod -aG sudo deploysudo useradd -m deploy
sudo passwd deploy
sudo usermod -aG wheel deploysudo mkdir -p /home/deploy/.ssh
sudo cp /root/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keyssudo restorecon -R /home/deploy/.sshDepuis le second terminal, connectez-vous avec le nouvel utilisateur et lancez sudo -v : la commande doit accepter le mot de passe de l'utilisateur. Seulement ensuite, passez à la suite.
Désactiver la connexion par mot de passe et celle de root
Les versions actuelles de Debian, d'Ubuntu, de la famille RHEL 9 et de Fedora lisent des fichiers supplémentaires dans /etc/ssh/sshd_config.d/. Vérifiez que c'est le cas de la vôtre :
grep -i '^Include' /etc/ssh/sshd_configSi la commande affiche Include /etc/ssh/sshd_config.d/*.conf, écrivez les réglages dans un fichier à part. SSH garde la première valeur qu'il lit pour chaque réglage, et les fichiers sont lus par ordre de nom : le préfixe 00- l'emporte donc sur des fichiers comme 50-cloud-init.conf, qui sur certaines images cloud réactive les mots de passe.
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf > /dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
MaxAuthTries 4
LoginGraceTime 30
EOFS'il n'y a pas de ligne Include (RHEL 8 et ses recompilations), placez les mêmes six lignes directement dans /etc/ssh/sshd_config, à la place des lignes existantes. Testez ensuite la configuration et regardez les valeurs que SSH utilisera réellement :
sudo sshd -t && echo "config OK"
sudo sshd -T | grep -Ei '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|maxauthtries) 'Chaque ligne doit afficher la valeur que vous avez définie. Si root doit encore se connecter avec une clé, pour une sauvegarde par exemple, utilisez PermitRootLogin prohibit-password au lieu de no. Rechargez SSH : les sessions ouvertes restent connectées.
sudo systemctl reload sshsudo systemctl reload sshdAttention: Ne fermez pas encore la session ouverte. Depuis le second terminal, connectez-vous avec votre clé, puis vérifiez qu'un mot de passe est refusé : la commande ci-dessous doit se terminer par Permission denied (publickey).
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password deploy@SERVER_IPChanger le port SSH, en sachant ce que cela ne fait pas
Déplacer SSH hors du port 22 réduit le bruit dans les journaux, parce que la plupart des bots n'essaient que le 22. Cela ne rend pas SSH plus sûr : les scanners de ports trouvent le nouveau port en quelques heures, et un attaquant qui vous cible le trouve tout de suite. Avec une connexion par clé uniquement, le port compte peu. Faites-le pour avoir des journaux plus lisibles, pas pour la sécurité, et seulement après les étapes précédentes.
Choisissez un port (ici 2222), ouvrez-le dans le pare-feu et, sur la famille RHEL, indiquez à SELinux que SSH peut l'utiliser :
sudo ufw allow 2222/tcpsudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222Ouvrez aussi le port dans le pare-feu cloud ou le groupe de sécurité de votre hébergeur. Définissez ensuite le port et redémarrez SSH :
echo "Port 2222" | sudo tee /etc/ssh/sshd_config.d/01-port.conf
sudo sshd -t && echo "config OK"Sur Ubuntu 24.04 et suivantes, SSH peut être lancé par ssh.socket : si la première commande ci-dessous affiche active, exécutez les quatre lignes ; sinon, seulement la dernière.
systemctl is-active ssh.socket
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo systemctl restart sshsudo systemctl restart sshdssh -p 2222 deploy@SERVER_IPAttention: Ne retirez la règle du port 22 du pare-feu qu'une fois la connexion sur le nouveau port réussie. Fail2ban, sshguard et les limites de débit ci-dessous doivent eux aussi utiliser le nouveau port.
Bannir les récidivistes avec fail2ban ou sshguard
Une fois les mots de passe désactivés, les tentatives ne peuvent plus aboutir, mais bannir les adresses qui insistent réduit la charge et le bruit. fail2ban lit le journal et bannit une adresse au pare-feu après un certain nombre d'échecs.
sudo apt update
sudo apt install -y fail2ban python3-systemdsudo dnf install -y epel-release
sudo dnf install -y fail2banSur RHEL lui-même et sur Oracle Linux, activez EPEL comme l'indique leur documentation, puis installez fail2ban. Sur Fedora, il se trouve dans les dépôts principaux. Amazon Linux 2023 ne peut pas utiliser EPEL : utilisez plutôt la limite de débit du pare-feu décrite plus bas.
Les réglages vont dans jail.local, jamais dans jail.conf, que les mises à jour écrasent. Vérifiez que vous n'en avez pas déjà un, puis créez-le. Remplacez YOUR_OFFICE_IP par les adresses fixes depuis lesquelles vous travaillez, ou supprimez-le, et réglez port sur votre port SSH si vous l'avez changé.
ls -l /etc/fail2ban/jail.localsudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_OFFICE_IP
bantime = 1h
bantime.increment = true
findtime = 10m
maxretry = 5
[sshd]
enabled = true
backend = systemd
port = ssh
EOFAvec ces réglages, une adresse est bannie pendant une heure après 5 échecs en 10 minutes, et plus longtemps à chaque récidive. backend = systemd lit le journal systemd, ce qui fonctionne sur Debian 12 et suivantes, où /var/log/auth.log peut ne pas exister.
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdSous attaque, Total failed et Currently banned augmentent en quelques minutes. Si Total failed reste à 0 alors que le journal montre des connexions échouées, la jail ne lit pas le bon journal. Pour lever un bannissement :
sudo fail2ban-client set sshd unbanip 203.0.113.7sshguard, l'alternative plus légère
sshguard fait le même travail avec moins de configuration, et il est empaqueté pour Debian et Ubuntu (et dans EPEL). Mettez d'abord vos propres adresses dans sa liste blanche, puis suivez sudo journalctl -u sshguard -f pendant une attaque pour voir les blocages. Utilisez l'un ou l'autre, pas les deux.
sudo apt install -y sshguard
echo "YOUR_OFFICE_IP" | sudo tee -a /etc/sshguard/whitelist
sudo systemctl restart sshguardLimiter ou restreindre SSH au pare-feu
Sur Ubuntu et Debian avec ufw, limit refuse une adresse qui ouvre 6 connexions ou plus en 30 secondes. Cette règle remplace une simple règle allow 22/tcp. Si sudo ufw status affiche aussi une règle OpenSSH, supprimez-la une fois la limite en place (sudo ufw delete allow OpenSSH) : elle s'appliquerait avant la limite.
sudo ufw limit 22/tcp
sudo ufw enable
sudo ufw status verboseAttention: Si ufw n'est pas encore actif, ufw enable se met à bloquer tous les ports sans règle. Autorisez les services que le serveur propose (par exemple sudo ufw allow 80,443/tcp) avant de l'activer, et gardez la session ouverte.
Les rich rules de firewalld ont un limit, mais il compte toutes les sources ensemble : une attaque peut épuiser le quota et vous bloquer vous aussi. Sur la famille RHEL, utilisez fail2ban pour des limites par adresse.
N'autoriser SSH que depuis vos adresses
C'est la mesure la plus forte, si vous travaillez depuis des adresses fixes ou un VPN : personne d'autre ne peut même joindre SSH.
sudo ufw allow from YOUR_OFFICE_IP to any port 22 proto tcp
sudo ufw delete limit 22/tcp
sudo ufw status numberedsudo firewall-cmd --permanent --zone=trusted --add-source=YOUR_OFFICE_IP
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --zone=public --remove-service=ssh
sudo firewall-cmd --reloadAttention: Cela bloque toutes les autres adresses, y compris la vôtre si elle change. Testez une nouvelle connexion après le premier rechargement et avant de retirer la règle SSH publique, et gardez la console web de l'hébergeur comme porte de secours.
Comment InfraFence gère la force brute SSH
L'agent InfraFence lit le journal SSH au fil de l'eau et bannit une adresse au pare-feu dès qu'elle atteint le seuil d'échecs dans la fenêtre de temps, deux valeurs que vous pouvez modifier dans le tableau de bord.
- 15 motifs de détection : mots de passe erronés, utilisateurs inexistants, échecs PAM, scans avant authentification, incompatibilités de protocole et coupures pendant l'échange de clés.
- Bannissements progressifs : 24 heures, 7 jours, 30 jours, puis définitif, ou la durée que vous fixez. En option, une adresse bannie sur un serveur l'est sur tous vos serveurs.
- La même protection pour les connexions à Postfix, Dovecot, MySQL, PostgreSQL, MongoDB, Pure-FTPd, ProFTPD et vsftpd.
- Les vérifications de durcissement signalent la connexion de root, la connexion par mot de passe, le port par défaut et un
MaxAuthTriesélevé.MaxAuthTriesse corrige en un clic, dans un fichier à part (/etc/ssh/sshd_config.d/00-infrafence-hardening.conf) testé avant le rechargement de SSH. Root, les mots de passe et le port peuvent vous enfermer dehors : ils sont donc expliqués étape par étape, comme dans ce guide. - Chaque session SSH est suivie de la connexion à la déconnexion et reçoit un score de risque : vous savez qui était connecté quand une autre détection s'est déclenchée.
Il fonctionne à côté de fail2ban : l'agent le reconnaît et garde ses propres règles dans des chaînes INFRAFENCE séparées, qu'il remet en place après un rechargement du pare-feu.
Questions
- Changer le port SSH suffit-il à arrêter la force brute ?
- Non. Cela réduit le nombre de tentatives dans les journaux, parce que la plupart des bots n'essaient que le port 22, mais les scanners trouvent vite le nouveau port. C'est la connexion par clé uniquement qui rend les tentatives inutiles.
- Faut-il utiliser fail2ban ou sshguard ?
- Les deux conviennent pour SSH. fail2ban a plus de filtres pour d'autres services et plus d'options ; sshguard demande moins de configuration. Utilisez-en un seul, pas les deux, pour qu'ils ne se disputent pas les mêmes adresses.
- J'ai désactivé les mots de passe et je vois encore des connexions échouées. Y a-t-il un problème ?
- Non. Les bots continuent d'essayer parce qu'ils ne savent pas que les mots de passe sont désactivés. Les tentatives échouent avant même qu'un mot de passe soit vérifié. Les bannissements et les limites de débit réduisent le bruit.
Essayez gratuitement sur 1 serveur
Starter est gratuit pour un serveur, avec la protection complète et le blocage automatique. Sans carte bancaire.
Installez l'agent en root, avec votre jeton à la place de <TOKEN> :
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>Le jeton se crée dans le tableau de bord, dans Serveurs › Ajouter un serveur.
