Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

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 :

ServiceOù lireContenu
Système, SSH, sudo, cron, MariaDB, Postfix, SSSD, PHP-FPMjournalctlDémarrages, erreurs, connexions, authentifications
Nginx/var/log/nginx/*.access.log, *.error.logRequê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.logObtentions et renouvellements de certificats
SSSD/var/log/sssd/Détail de l'authentification au domaine (selon debug_level)

Interroger le journal avec journalctl

bash
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
OptionRô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, --untilUne période (today, yesterday, "1 hour ago", une date)
-bDepuis 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)
-fSuivre 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 :

ini
[Journal]
SystemMaxUse=2G
bash
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 :

text
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.

LigneCe qu'elle signifie
Failed password for invalid user adminUne 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 rootUne 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 sudoersUn 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 :

bash
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 :

text
# 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ètreRôle
DefaultNetstreamDriverCAFileLes autorités utilisées pour vérifier le certificat du serveur central
imfileSurveille 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
bash
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'agentExemple sur srv-glpi
Collecte des journauxJournal 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ésListe des paquets installés, comparée aux failles connues
Réponse activeBlocage 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 :

bash
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.

bash
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> :

xml
<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.

bash
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
bash
# (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.

text
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
  1. 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 pour srv-glpi : qui a ouvert ce flux ?), et que fail2ban et l'authentification par clé sont en place.
  2. Trace normale : une administratrice teste la configuration de Nginx avec sudo. Aucune action.
  3. Grave : connexion directe de root, par mot de passe, depuis 192.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 corriger PermitRootLogin no, PasswordAuthentication no pour les comptes locaux, et le filtrage du port 22.
  4. Un robot cherche un fichier .env (qui contient souvent des mots de passe) ; la réponse 404 montre 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éponse 200 sur la même ligne, en revanche, serait une fuite de secrets à traiter tout de suite.

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Sécuriser et dépanner un serveur de services : nftables, fail2ban et méthodeRevoir le sommaire du cours