Des tentatives de connexion SSH dans mes logs : suis-je piraté ?
Vous vous connectez à votre serveur, jetez un œil à /var/log/auth.log, et ce sont des milliers de lignes Failed password for root venues d'adresses du monde entier. On dirait un siège. C'est surtout de la météo.
Le port 22 est la porte la plus prévisible d'internet : des scripts automatiques y frappent sans arrêt, partout, toute la journée. Ce n'est pas vous qu'ils visent. Ils essaient une courte liste de noms d'utilisateur (root, admin, oracle, ubuntu, test) avec les mots de passe les plus choisis, puis passent à autre chose. Un échec ne leur coûte rien et vous apprend seulement que SSH est joignable. Votre travail consiste à répondre à deux questions : une tentative a-t-elle réussi, et une tentative future le pourrait-elle ?
Où regarder
Sous Debian et Ubuntu avec rsyslog, SSH écrit dans /var/log/auth.log. Sous Red Hat, Fedora, Rocky et Alma, c'est /var/log/secure. Les installations Debian récentes peuvent ne pas écrire ce fichier du tout et tout garder dans le journal systemd. Le journal fonctionne partout où tourne systemd ; le service s'appelle ssh sous Debian et Ubuntu et sshd dans la famille Red Hat :
sudo journalctl -u ssh --since today # Debian, Ubuntu
sudo journalctl -u sshd --since "1 hour ago" # Red Hat, Fedora, Rocky, Alma
Trois comptages racontent l'essentiel :
sudo grep -c "Failed password" /var/log/auth.log
sudo grep "Accepted" /var/log/auth.log
sudo grep "Failed password" /var/log/auth.log | grep -oE "from [0-9.]+" | sort | uniq -c | sort -rn | head
Le premier donne l'ampleur du bruit. Le deuxième est celui qui compte : chaque connexion réussie. Le troisième montre quelles adresses insistent le plus.
Un exemple concret : une nuit sur un petit VPS
Douze lignes d'un serveur nommé web1. Les deux adresses de personnes (l'attaquant qui essaie admin, et le propriétaire qui se connecte le lendemain matin) sont des adresses de documentation : aucune personne réelle n'apparaît ici. Les autres appartiennent à des infrastructures publiques.
Nov 6 03:12:41 web1 sshd[24811]: Invalid user admin from 203.0.113.77 port 51022
Nov 6 03:12:43 web1 sshd[24811]: Failed password for invalid user admin from 203.0.113.77 port 51022 ssh2
Nov 6 03:12:44 web1 sshd[24811]: Connection closed by invalid user admin 203.0.113.77 port 51022 [preauth]
Nov 6 03:12:50 web1 sshd[24815]: Failed password for root from 185.220.101.1 port 40122 ssh2
Nov 6 03:12:53 web1 sshd[24815]: Failed password for root from 185.220.101.1 port 40122 ssh2
Nov 6 03:12:55 web1 sshd[24815]: Disconnected from authenticating user root 185.220.101.1 port 40122 [preauth]
Nov 6 03:14:02 web1 sshd[24830]: Invalid user oracle from 3.5.140.1 port 33412
Nov 6 03:14:04 web1 sshd[24830]: Failed password for invalid user oracle from 3.5.140.1 port 33412 ssh2
Nov 6 03:14:04 web1 sshd[24830]: Received disconnect from 3.5.140.1 port 33412:11: Bye Bye [preauth]
Nov 6 03:20:17 web1 sshd[24902]: Connection closed by 167.94.138.35 port 49212 [preauth]
Nov 6 08:41:09 web1 sshd[25510]: Accepted publickey for deploy from 198.51.100.20 port 52814 ssh2: ED25519 SHA256:k3X0exampleexampleexampleexampleexampleexa
Nov 6 08:41:09 web1 sshd[25510]: pam_unix(sshd:session): session opened for user deploy(uid=1001) by (uid=0)Passées dans l'analyse de journaux d'iplover, les cinq adresses se répartissent ainsi :
| Adresse IP | Lignes | Catégorie | Type de réseau |
|---|---|---|---|
| 203.0.113.77 | 3 | Privées ou réservées | Adresse privée ou réservée (non vérifiée) |
| 185.220.101.1 | 3 | Nœuds de sortie Tor | Nœud de sortie Tor |
| 3.5.140.1 | 3 | Cloud et hébergement | Hébergement, cloud ou centre de données |
| 167.94.138.35 | 1 | Scanners d'internet | Non identifié |
| 198.51.100.20 | 1 | Privées ou réservées | Adresse privée ou réservée (non vérifiée) |
(Les deux adresses de documentation apparaissent comme réservées ; dans votre propre log, les vraies adresses seraient vérifiées.) Lisez maintenant les lignes, car les catégories disent seulement qui a frappé, pas si la porte s'est ouverte.
Invalid user admin from 203.0.113.77: il n'y a aucun compteadminsur ce serveur, cette tentative ne pouvait donc jamais réussir. L'essentiel d'un auth.log typique ressemble à ça.Failed password for root from 185.220.101.1, deux fois : quelqu'un qui devine le mot de passe de root via Tor. Le compte existe, celle-ci compte donc davantage.Disconnected from authenticating user root … [preauth]signifie que la session s'est terminée avant la connexion : preauth veut littéralement dire « avant l'authentification ».Invalid user oracle from 3.5.140.1: un script sur un serveur cloud d'Amazon qui essaie un nom de compte de base de données.Bye Bye [preauth], c'est le client qui abandonne.Connection closed by 167.94.138.35 … [preauth]: Censys s'est connecté, a lu la bannière de version SSH et est reparti sans essayer de mot de passe. C'est un scanner qui fait l'inventaire, pas une attaque.Accepted publickey for deploy from 198.51.100.20: la seule connexion réussie de la nuit, par clé, celle du propriétaire. La lignesession openedjuste après confirme l'ouverture de la session.
Verdict : une connexion acceptée, et c'est celle du propriétaire. Personne n'est entré. Mais root accepte encore les mots de passe : les essais de la quatrième ligne pourraient donc réussir un jour si le mot de passe de root est faible. C'est ce qu'il faut corriger.
Quelqu'un est-il vraiment entré ?
Vérifiez chaque ligne Accepted. Pour chacune, demandez-vous : est-ce mon nom d'utilisateur, ma clé ou mon mot de passe, et une adresse que je reconnais (domicile, bureau, VPN) ? Puis croisez avec les registres de connexion :
last -a | head -20 # connexions réussies récentes, avec l'adresse distante
sudo lastb | head -20 # échecs récents (sur les systèmes qui les conservent)
who # qui est connecté en ce moment
Certaines distributions récentes ont remplacé last et lastb par d'autres outils ; s'ils manquent, le journal et auth.log contiennent les mêmes informations.
Une ligne Accepted password ou Accepted publickey que vous ne pouvez pas expliquer est le seul résultat qui change tout. Dans ce cas, considérez le compte comme compromis :
- Regardez
~/.ssh/authorized_keyspour chaque utilisateur (root compris) et supprimez les clés que vous ne reconnaissez pas. - Cherchez les nouveaux comptes (
/etc/passwd), les nouveaux droitssudoet les nouvelles tâches cron (crontab -lpour chaque utilisateur, plus/etc/cron.*). - Changez le mot de passe de chaque compte et renouvelez tous les secrets stockés sur le serveur.
- Si root était concerné, la réponse honnête est de reconstruire le serveur à partir d'une image saine et de restaurer vos données. Un attaquant qui a eu root peut cacher presque n'importe quoi.
Si vous voyez ceci, faites cela
| Ce que vous voyez | Ce que ça signifie | Que faire |
|---|---|---|
Invalid user … pour des noms que vous n'avez pas | Des essais qui ne peuvent pas marcher | Rien d'urgent. Ça disparaît une fois les mots de passe désactivés. |
Failed password for root ou pour un autre compte réel | Des essais contre un compte qui existe | Désactivez la connexion par mot de passe (plus bas), au moins pour root. |
Connection closed by … [preauth] sans mot de passe essayé | Un scanner qui lit votre bannière SSH | Rien. |
| Des milliers d'échecs par jour depuis quelques adresses | Des bots persistants | Ajoutez fail2ban, ou n'autorisez SSH que depuis vos propres adresses. |
Des lignes Accepted … qui sont toutes les vôtres | Personne d'autre n'est entré | Rien, à part renforcer la sécurité. |
Accepted … depuis une adresse ou pour un utilisateur que vous ne pouvez pas expliquer | Une intrusion probable | Suivez les étapes ci-dessus, en commençant par authorized_keys. |
Rendre les essais inutiles : uniquement des clés
Un mot de passe peut se deviner ; une clé SSH, en pratique, non. Dès que seules les clés sont acceptées, les bots peuvent essayer indéfiniment.
Commencez par créer une clé sur votre ordinateur et copiez-la sur le serveur. macOS et Linux intègrent le client OpenSSH. Sous Windows, c'est une fonctionnalité facultative, souvent déjà installée ; si ssh n'est pas reconnu, le guide de Microsoft Bien démarrer avec OpenSSH pour Windows explique comment l'ajouter :
ssh-keygen -t ed25519
ssh-copy-id vous@votre-serveur # sous Windows, collez ~/.ssh/id_ed25519.pub dans le ~/.ssh/authorized_keys du serveur
Ensuite, sur le serveur, définissez ceci dans /etc/ssh/sshd_config :
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
prohibit-password n'autorise root qu'avec une clé ; mettez no pour tenir root complètement à l'écart de SSH. Avant de redémarrer, vérifiez ce que SSH va réellement utiliser. Les fichiers de /etc/ssh/sshd_config.d/ sont lus aussi, et certaines images cloud en fournissent un qui réactive les mots de passe. Pour la plupart des réglages, la première valeur lue par sshd l'emporte :
sudo sshd -T | grep -Ei "passwordauthentication|kbdinteractive|permitrootlogin"
Redémarrez SSH (sudo systemctl restart ssh, ou sshd dans la famille Red Hat), et gardez votre session actuelle ouverte pendant que vous testez une nouvelle connexion dans une seconde fenêtre. Si la nouvelle connexion échoue, vous pouvez encore réparer depuis l'ancienne.
Réduire le bruit : fail2ban et pare-feu
Les clés rendent les essais inoffensifs. fail2ban rend le log lisible : il surveille les échecs répétés et bloque ces adresses un moment dans le pare-feu. Sous Debian et Ubuntu, sudo apt install fail2ban, puis créez /etc/fail2ban/jail.local :
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
# Sans /var/log/auth.log (Debian récent), lire le journal :
# backend = systemd
Redémarrez-le avec sudo systemctl restart fail2ban et vérifiez-le avec sudo fail2ban-client status sshd.
Si vous êtes seul à avoir besoin de SSH, le meilleur filtre anti-bruit est une règle de pare-feu qui n'autorise le port 22 que depuis vos propres adresses, ou un VPN devant le serveur. Déplacer SSH sur un autre port réduit aussi beaucoup le bruit, mais c'est du camouflage, pas une protection : un scanner le trouvera quand même.
Ce que les adresses ne peuvent pas vous dire
Les adresses d'auth.log sont l'origine des connexions : souvent une sortie Tor, un serveur cloud loué ou la machine piratée de quelqu'un d'autre. Elles n'identifient pas une personne, et les bloquer une par une ne suivra jamais le rythme. Signaler des attaques persistantes au contact abus du réseau (la recherche IP l'affiche) est raisonnable pour un serveur cloud qui vous martèle pendant des jours ; pour quelques échecs de connexion, ça ne vaut pas votre temps.
Sources
Documents officiels utilisés pour vérifier les faits de ce guide.