Chapitre 1215 minIntermédiaire
Journaux des services Linux : journald, rsyslog et agent Wazuh
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- trouver les journaux d'un service sous Debian 13 ;
- interroger le journal systemd avec journalctl ;
- reconnaître les traces qui annoncent un incident ;
- envoyer les journaux en syslog chiffré vers un serveur central ;
- installer et configurer l'agent Wazuh.
3 exercices corrigés
Les journaux (logs) sont les traces que les services écrivent pour chaque événement : une connexion SSH, une requête web, une erreur de PHP, un sudo, un courriel envoyé. Ils servent à dépanner, à prouver ce qui s'est passé, et à détecter les attaques. Ce chapitre explique où Debian 13 range les journaux, comment les interroger avec journalctl, comment les envoyer en syslog chiffré vers le serveur central de Sorbier avec rsyslog, et comment installer l'agent Wazuh qui les fait analyser par le SIEM. Le rôle de la journalisation dans la sécurité (ce qu'on collecte, la corrélation, la gestion des incidents) est traité dans le cours Cybersécurité des infrastructures.
Où sont les journaux sous Debian 13
Depuis Debian 12, une installation neuve n'installe plus rsyslog : les journaux du système et des services sont gérés par systemd-journald, dans un journal binaire conservé sur le disque (/var/log/journal/) et lu avec journalctl. Les fichiers texte historiques /var/log/syslog et /var/log/auth.log n'existent donc plus, et un tutoriel ancien qui te demande de les lire te fera chercher dans le vide.
Certains services écrivent en plus leurs propres fichiers :
| Service | Où lire | Contenu |
|---|---|---|
Système, SSH, sudo, cron, MariaDB, Postfix, SSSD, PHP-FPM | journalctl | Démarrages, erreurs, connexions, authentifications |
| Nginx | /var/log/nginx/*.access.log, *.error.log | Requêtes, erreurs du serveur web |
| Apache | /var/log/apache2/ | Idem |
| PHP (par pool) | Le fichier de php_admin_value[error_log] | Erreurs des scripts |
| GLPI | /var/log/glpi/ | Erreurs PHP et SQL de l'application, journal des actions automatiques |
| Samba | /var/log/samba/ | Connexions, erreurs d'authentification |
| Certbot | /var/log/letsencrypt/letsencrypt.log | Obtentions et renouvellements de certificats |
| SSSD | /var/log/sssd/ | Détail de l'authentification au domaine (selon debug_level) |
Interroger le journal avec journalctl
journalctl -u nginx --since "1 hour ago" # un service, depuis une heure
journalctl -u ssh -p warning --since today # SSH, avertissements et plus graves
journalctl -p err -b # toutes les erreurs depuis le dernier démarrage
journalctl -t sudo --since "2026-10-21 08:00" # par identifiant (le nom du programme)
journalctl -u ssh -g "Failed password" # SSH : sous Debian 13, les sessions sont tracées par sshd-session
journalctl -u postfix@- -f # suivre en direct
journalctl -u mariadb -o json-pretty -n 1 # une entrée avec tous ses champs
journalctl --disk-usage # place occupée par le journal
| Option | Rôle |
|---|---|
-u <unité> | Les messages d'un service |
-t <identifiant> | Les messages d'un programme (sudo, CRON, postfix/smtp) |
-p <priorité> | Cette priorité et les plus graves : emerg, alert, crit, err, warning, notice, info, debug |
--since, --until | Une période (today, yesterday, "1 hour ago", une date) |
-b | Depuis le dernier démarrage (-b -1 : le démarrage précédent) |
-g <motif> | Seulement les messages qui contiennent ce motif (expression régulière) |
-f | Suivre en direct |
-n <nombre> | Les dernières entrées |
Pour lire le journal sans sudo, un compte doit être membre du groupe systemd-journal (ou adm). La taille du journal est limitée par défaut à 10 % du système de fichiers, et 4 Go au plus ; pour fixer une limite, crée /etc/systemd/journald.conf.d/taille.conf :
[Journal]
SystemMaxUse=2G
sudo systemctl restart systemd-journald
Les traces qui comptent pour la sécurité
Quelques lignes qu'il faut savoir reconnaître, parce qu'elles annoncent souvent un incident :
sshd-session[4123]: Failed password for invalid user admin from 198.51.100.23 port 51514 ssh2
sshd-session[4130]: Accepted publickey for root from 192.168.10.209 port 50122 ssh2: ED25519 SHA256:…
sudo[5210]: adm1-clambert : TTY=pts/0 ; PWD=/home/adm1-clambert ; USER=root ; COMMAND=/usr/bin/systemctl reload nginx
sudo[5288]: jlefevre : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/jlefevre ; USER=root ; COMMAND=/bin/bash
Depuis OpenSSH 9.8, chaque connexion est traitée par le programme sshd-session : c'est ce nom qui apparaît dans le journal de Debian 13, et non plus sshd. Filtre donc par unité (journalctl -u ssh), pas par nom de programme.
| Ligne | Ce qu'elle signifie |
|---|---|
Failed password for invalid user admin | Une tentative sur un compte qui n'existe pas : typique d'une attaque par force brute ou par dictionnaire, menée par un robot |
Accepted publickey for root | Une connexion directe en root : elle devrait être interdite (PermitRootLogin no) ; si elle réussit, c'est un écart de configuration |
sudo … COMMAND=… | Une action d'administration, avec le nom de la personne : la trace normale d'un administrateur |
user NOT in sudoers | Un compte tente d'obtenir les droits d'administration sans y avoir droit : erreur ou tentative d'élévation de privilèges |
Dans les journaux de Nginx, une rafale de réponses 404 sur des chemins comme /wp-login.php, /.env ou /phpmyadmin/ signale un robot qui cherche des failles connues ; des centaines de POST sur la page de connexion en quelques minutes, une attaque sur les mots de passe. Le chapitre 13 montre comment fail2ban bloque automatiquement ces adresses.
Envoyer les journaux vers srv-journaux avec rsyslog
rsyslog reçoit les messages du journal système et les transmet, par le protocole syslog, à un serveur distant. Pour chiffrer le transport en TLS, il faut aussi le module GnuTLS :
sudo apt install rsyslog rsyslog-gnutls
L'installation de rsyslog recrée au passage /var/log/syslog et /var/log/auth.log. Crée /etc/rsyslog.d/90-srv-journaux.conf :
# Autorités de confiance : le magasin du système, qui contient Sorbier-AC
global(DefaultNetstreamDriverCAFile="/etc/ssl/certs/ca-certificates.crt")
# Lire aussi les journaux d'accès et d'erreurs de Nginx
module(load="imfile")
input(type="imfile" File="/var/log/nginx/*.access.log" Tag="nginx-access:" Facility="local6" Severity="info")
input(type="imfile" File="/var/log/nginx/*.error.log" Tag="nginx-error:" Facility="local6" Severity="error")
# Tout transmettre à srv-journaux, en TLS, en vérifiant son certificat
action(
type="omfwd"
target="srv-journaux.ad.sorbier.example"
port="6514"
protocol="tcp"
StreamDriver="gtls"
StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeers="srv-journaux.ad.sorbier.example"
queue.type="LinkedList"
queue.filename="fwd_srv_journaux"
queue.saveOnShutdown="on"
action.resumeRetryCount="-1"
)
| Paramètre | Rôle |
|---|---|
DefaultNetstreamDriverCAFile | Les autorités utilisées pour vérifier le certificat du serveur central |
imfile | Surveille des fichiers texte et transmet chaque nouvelle ligne, avec une étiquette (Tag) |
StreamDriver="gtls", StreamDriverMode="1" | Transport en TLS, obligatoire |
StreamDriverAuthMode="x509/name" | Vérifie que le certificat présenté est valide et porte le nom attendu : un faux serveur ne recevra rien |
queue.*, action.resumeRetryCount="-1" | Si srv-journaux est injoignable, les messages sont mis en file d'attente (sur disque à l'arrêt) puis envoyés au retour, sans perte |
sudo rsyslogd -N1 # vérifie la configuration
sudo systemctl restart rsyslog
logger -p auth.warning "Test de transfert depuis srv-glpi"
Sur srv-journaux, le message de test doit apparaître dans les journaux reçus de srv-glpi. Le serveur central, de son côté, écoute sur le port 6514 avec son propre certificat de Sorbier-AC ; sa configuration, le stockage et la recherche dans les journaux reçus relèvent du cours Supervision.
L'agent Wazuh : faire analyser les journaux par le SIEM
Transmettre les journaux ne suffit pas : personne ne lit des millions de lignes. Wazuh est une plateforme libre de détection (SIEM et XDR) : un agent installé sur chaque serveur collecte les journaux et surveille la machine ; le serveur Wazuh (sur srv-journaux chez Sorbier) analyse ces événements avec ses règles et lève des alertes : force brute sur SSH, modification d'un fichier système, élévation de privilèges, scan de vulnérabilités web. Le cours Wazuh explique comment lire une alerte et écrire ses propres règles.
| Fonction de l'agent | Exemple sur srv-glpi |
|---|---|
| Collecte des journaux | Journal systemd, journaux de Nginx et de GLPI |
| Contrôle d'intégrité des fichiers (FIM) | Alerte si /etc/passwd, /etc/sudoers.d/ ou le code de GLPI change |
| Évaluation de la configuration (SCA) | Contrôle des réglages SSH, des droits, selon des référentiels (CIS) |
| Inventaire et vulnérabilités | Liste des paquets installés, comparée aux failles connues |
| Réponse active | Blocage automatique d'une adresse, si on l'active |
Installer l'agent (version 4.14 en novembre 2026), avec le dépôt officiel de Wazuh :
sudo apt install gnupg curl
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | sudo gpg --no-default-keyring \
--keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import && sudo chmod 644 /usr/share/keyrings/wazuh.gpg
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" \
| sudo tee /etc/apt/sources.list.d/wazuh.list
sudo apt update
sudo WAZUH_MANAGER="srv-journaux.ad.sorbier.example" apt install wazuh-agent
sudo systemctl daemon-reload
sudo systemctl enable --now wazuh-agent
La variable WAZUH_MANAGER inscrit l'adresse du serveur dans la configuration de l'agent, qui s'enregistre auprès de lui (port TCP 1515) puis lui envoie ses événements (port TCP 1514). Ces deux flux, de chaque serveur vers srv-journaux, doivent être autorisés.
La documentation de Wazuh recommande de bloquer les mises à jour automatiques de l'agent, pour qu'il ne devienne jamais plus récent que le serveur, ce qui casserait la communication : on met l'agent à jour volontairement, après le serveur.
echo "wazuh-agent hold" | sudo dpkg --set-selections
Ajouter les journaux des services. La configuration de l'agent est dans /var/ossec/etc/ossec.conf. Vérifie qu'un bloc collecte le journal systemd (sur Debian 13, c'est là que sont SSH et sudo), puis ajoute les fichiers des services, entre les balises <ossec_config> :
<localfile>
<location>journald</location>
<log_format>journald</log_format>
</localfile>
<localfile>
<log_format>apache</log_format>
<location>/var/log/nginx/glpi.access.log</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/nginx/glpi.error.log</location>
</localfile>
Le format apache convient au journal d'accès de Nginx, qui utilise le même format combined. Un bloc journald sans filtre collecte tout le journal systemd.
sudo systemctl restart wazuh-agent
sudo grep -i "connected to the server" /var/ossec/logs/ossec.log | tail -1
Sur le serveur Wazuh, l'agent apparaît dans la liste des agents du tableau de bord, à l'état active ; un agent qui ne communique plus passe à l'état disconnected. L'exploitation des alertes, l'écriture de règles et la réponse aux incidents sont traitées dans Cybersécurité des infrastructures et Réponse à incident.
Exercices
Exercice 1 sur 3 Trouver les tentatives de connexion Réussi À revoir
Écris les commandes qui répondent à ces questions sur srv-glpi : (a) les échecs de connexion SSH depuis ce matin ; (b) les adresses qui en sont à l'origine, avec le nombre d'échecs de chacune, triées ; (c) les commandes passées avec sudo hier.
Voir la réponseMasquer la réponse de l'exercice 1
# (a)
journalctl -u ssh --since today -g "Failed password"
# (b) l'adresse est le 4e champ en partant de la fin : "... from 198.51.100.23 port 51514 ssh2"
journalctl -u ssh --since today -g "Failed password" -o cat \
| awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
# (c)
journalctl -t sudo --since yesterday --until today -g "COMMAND="
-o cat n'affiche que le message, sans la date ni le nom de la machine, ce qui rend la position des champs stable. Sur une Debian 13 sans rsyslog, il n'y a pas de /var/log/auth.log à lire : tout est dans le journal systemd. Sur srv-glpi, qui a rsyslog, le fichier existe aussi, mais la commande journalctl fonctionne partout.
Tu avais trouvé ?
Exercice 2 sur 3 Le transfert qui se tait Réussi À revoir
srv-glpi n'envoie plus aucun journal à srv-journaux depuis le renouvellement du certificat de ce dernier. journalctl -u rsyslog affiche : peer name not authorized - not permitted to talk to it. Names: DNS:journaux.ad.sorbier.example; CN: journaux.ad.sorbier.example. Explique, et dis ce que sont devenus les journaux de la période.
Voir la réponseMasquer la réponse de l'exercice 2
rsyslog vérifie que le certificat du serveur central porte le nom attendu (StreamDriverAuthMode="x509/name" et StreamDriverPermittedPeers="srv-journaux.ad.sorbier.example"). Le nouveau certificat a été demandé pour journaux.ad.sorbier.example, un autre nom : rsyslog refuse, à raison, de transmettre à un serveur dont il ne peut pas vérifier l'identité.
Correction : refaire le certificat de srv-journaux avec tous ses noms dans le SAN (srv-journaux.ad.sorbier.example, et journaux.ad.sorbier.example si cet alias est utilisé), ou, si le nouveau nom est voulu, l'ajouter à StreamDriverPermittedPeers sur tous les serveurs.
Les journaux de la période ne sont pas perdus : la file d'attente (queue.type="LinkedList", action.resumeRetryCount="-1") les garde, sur disque à l'arrêt (queue.saveOnShutdown), et les envoie dès que la connexion est rétablie, dans la limite de la taille de la file. La supervision aurait dû alerter : l'absence de journaux reçus d'un serveur est elle-même un indicateur à surveiller.
Tu avais trouvé ?
Exercice 3 sur 3 Lire des traces Réussi À revoir
Pour chaque ligne, dis ce qu'elle signifie et si elle demande une action.
1. sshd-session[812]: Failed password for invalid user oracle from 203.0.113.99 port 40022 ssh2
2. sudo[911]: adm1-clambert : TTY=pts/0 ; PWD=/etc/nginx ; USER=root ; COMMAND=/usr/sbin/nginx -t
3. sshd-session[1022]: Accepted password for root from 192.168.10.70 port 51888 ssh2
4. 198.51.100.7 - - [21/Oct/2026:03:12:09 +0200] "GET /.env HTTP/1.1" 404 153 "-" "curl/8.5.0"
Voir la réponseMasquer la réponse de l'exercice 3
- Tentative sur un compte inexistant (
oracle) depuis une adresse d'Internet : un robot qui essaie des noms de comptes courants. Action : vérifier que SSH n'est pas exposé à Internet (il ne devrait pas l'être poursrv-glpi: qui a ouvert ce flux ?), et que fail2ban et l'authentification par clé sont en place. - Trace normale : une administratrice teste la configuration de Nginx avec
sudo. Aucune action. - Grave : connexion directe de
root, par mot de passe, depuis192.168.10.70, une adresse du VLAN des postes, pas du réseau d'administration. Trois écarts à la politique (root, mot de passe, mauvais réseau). Action : vérifier immédiatement qui utilisait ce poste et ce qui a été fait (journaux de la session,last, historique), traiter comme un incident potentiel ; puis corrigerPermitRootLogin no,PasswordAuthentication nopour les comptes locaux, et le filtrage du port 22. - Un robot cherche un fichier
.env(qui contient souvent des mots de passe) ; la réponse404montre qu'il n'existe pas dans la racine publique. Aucune action immédiate ; si ces requêtes se multiplient, fail2ban peut bloquer l'adresse. Une réponse200sur la même ligne, en revanche, serait une fuite de secrets à traiter tout de suite.
Tu avais trouvé ?