Il y a quelques semaines, j’ai eu un doute sur des connexions SSH suspectes sur l’un de mes serveurs. Finalement, il n’y avait aucun problème, mais par souci d’amélioration continue, je me suis dit :
Et si je pouvais recevoir des alertes en temps réel quand une connexion SSH est établie sur un de mes serveurs ?
Mes contraintes
Comme toujours, c’est important de regarder le contexte pour voir si ça vaut le coup de construire soi-même ce genre de système, j’ai donc établi mes contraintes :
- pas de dépendance externe
- rapide à mettre en place
- être prévenu peu importe le moment et le lieu où je me trouve
Le principe
SSH passe par PAM (Pluggable Authentication Modules).
PAM permet d’exécuter un script à chaque ouverture de session.
L’idée est donc simple :
- Un script bash déclenché à chaque login SSH
- Il envoie un message via un webhook (Discord ou Slack)
- Je suis notifié en temps réel
Mise en place
Le script d’alerte SSH
Créer le script qui va envoyer un message via Discord (une alternative pour Slack est disponible plus bas) :
sudo vim /usr/local/bin/ssh-session-alert.sh
mettre le contenu suivant :
#!/bin/bash
[ "$PAM_TYPE" != "open_session" ] && exit 0
WEBHOOK_URL="https://discord.com/api/webhooks/XXX/YYY" # à remplacer
CONTENT="SSH login user=$PAM_USER ip=${PAM_RHOST:-local} host=$(hostname) date=$(date '+%F %T')"
JSON=$(printf '{"content":"%s"}' "$CONTENT")
/usr/bin/curl \
--silent \
--fail \
-H "Content-Type: application/json" \
-X POST \
-d "$JSON" \
"$WEBHOOK_URL" \
>> /tmp/ssh-alerting-error.log 2>&1
Il faut bien penser à :
- Remplacer l’URL de Webhook Discord par votre URL de webhook
- Rendre le script exécutable :
sudo chmod +x /usr/local/bin/ssh-session-alert.sh
Brancher le script à SSH via PAM
Éditer le fichier PAM de SSH :
sudo vim /etc/pam.d/sshd
Ajouter à la fin du fichier :
session optional pam_exec.so /usr/local/bin/ssh-session-alert.sh
À partir de là, chaque nouvelle session SSH déclenchera le script, avec pour résultat :
SSH login user=qlerebours ip=x.y.z.a host=my-server date=2026-02-02 14:32:10
Version Slack du curl
Slack attend un payload légèrement différent.
Voici la version Slack du curl, à utiliser à la place de celui de Discord si besoin :
JSON=$(printf '{"text":"%s"}' "$CONTENT")
/usr/bin/curl
--silent
--fail
-H "Content-Type: application/json"
-X POST
-d "$JSON"
"$WEBHOOK_URL"
>> /tmp/ssh-alerting-error.log 2>&1
Le reste du script reste strictement identique.
Tips pour débugger si ça ne marche pas
- Vérifier que le script est bien exécuté
- Ajouter au tout début du script
echo "SSH LOGIN $(date) user=$PAM_USER rhost=$PAM_RHOST" >> /tmp/ssh-test.log - Puis tenter une connexion SSH et vérifier que
/tmp/ssh-test.loga été rempli
- Ajouter au tout début du script
- Vérifier les erreurs du curl, si le script s’exécute, mais que rien n’arrive sur Discord / Slack :
- Aller vérifier le fichier :
cat /tmp/ssh-alerting-error.log
- Aller vérifier le fichier :
- Tester le script manuellement
/usr/local/bin/ssh-session-alert.sh
Si ça marche en manuel mais pas via SSH, le problème vient quasi toujours du contexte PAM.
Pourquoi j’aime bien cette solution
- Facile à mettre en place
- Zéro dépendance externe
- Suffisamment efficace pour détecter rapidement un comportement suspect
Ce n’est pas un système de sécurité complet, évidemment.
Mais comme souvent, avoir un signal simple et immédiat vaut mieux qu’une solution parfaite jamais mise en place.
À propos de Quentin Lerebours
Entrepreneur mais avant tout développeur, j'ai choisi de rester polyvalent afin de travailler avec une vision d'ensemble cohérente des projets. Développement, Commerce, Entrepreneuriat et Gestion de projet font donc partie intégrante de mon quotidien — et si c'était à refaire, je referais pareil !