Mode opératoire — Centraliser les journaux des machines Linux et de pfSense dans une base MariaDB, avec rsyslog
Document autonome. Partie théorique, puis mise en œuvre telle qu’elle a été réalisée et vérifiée le 21/10/2026 dans le lab pfSense de l’école (phase 14 du suivi, tâche 14.5). La méthode vaut pour tout parc Linux et tout pare-feu qui sait envoyer en syslog. Prérequis : l’accès au cluster par HAProxy local, la base
sysloget le comptersyslog(MO-14-HAProxy-local-Galera.md). Les machines Windows sont traitées dans MO-16-Fluent-Bit-Windows.md. Contexte : Documentation-pfSense.md (étape 48).Valeurs masquées. Le mot de passe du compte
rsyslogn’apparaît nulle part :<mot-de-passe-rsyslog>, placé sur le serveur au dernier moment.Dernière mise à jour : 01/11/2026 (§9 : conservation de 6 mois et purge automatique)
Sommaire
| § | Contenu |
|---|---|
| 1 | Le besoin |
| 2 | Théorie : syslog, catégories, gravités, TCP ou UDP |
| 3 | L’architecture retenue |
| 4 | Le serveur de réception (srv-supervision) |
| 5 | Ajouter une machine Linux (depuis le bastion) |
| 6 | pfSense |
| 7 | Interroger les journaux |
| 8 | Les deux défauts que la centralisation a révélés |
| 9 | Conservation et purge automatique |
| 10 | Pièges et checklist |
1 · Le besoin
Chaque machine écrit ses journaux chez elle. Pour savoir « qui s’est connecté sur quoi, depuis quand, et qu’est-ce qui a échoué ? », il faudrait se connecter à chacune. Une machine piratée peut aussi effacer ses propres journaux. On veut une copie de tous les journaux, au même endroit, hors de portée des machines surveillées, conservée une durée maîtrisée : 6 mois pour les deux tables depuis le 01/11 (fourchette de la CNIL, 6 mois à 1 an ; voir §9).
2 · Théorie : syslog, catégories, gravités, TCP ou UDP
syslog est le format standard des journaux sous Linux et sur les équipements réseau. Chaque message porte :
| Champ | Exemples | Utilité ici |
|---|---|---|
| Catégorie (facility) | auth, authpriv (connexions, sudo), daemon, user, local0… | le tri : auth/authpriv vont dans une table à part, conservée plus longtemps |
| Gravité (severity) | 0 urgence … 3 erreur, 4 avertissement, 5 notice, 6 info, 7 débogage | filtrer l’important |
| Machine, programme, message | srv-web-01, sshd, Accepted publickey for ipfixe… | répondre à « qui, quoi » |
| Transport | Pour | Contre |
|---|---|---|
| UDP (514) | simple, tout le monde le parle | un message perdu l’est sans que personne ne le sache |
| TCP (514) | livraison garantie, et l’émetteur sait si le serveur ne répond pas | un peu plus lourd |
rsyslog est le service syslog de Debian. Il sait recevoir, trier, envoyer à une autre machine et écrire dans MariaDB (module ommysql),
avec une file d’attente sur disque si la destination ne répond pas.
Principe à retenir — chaque machine garde ses journaux et en envoie une copie. La copie centrale est celle qu’un intrus ne peut pas effacer, et la seule qui permet de comparer les machines entre elles.
3 · L’architecture retenue
10 Linux ── rsyslog ── TCP 514 ──┐
pfSense ─── syslogd ── UDP 514 ──┤ srv-supervision (10.0.30.15)
Windows ─── Fluent Bit ─ TCP 514 ┴──► rsyslog ──► HAProxy local ──► Galera
tri 127.0.0.1:3306 syslog.journaux (6 mois)
+ file d'attente disque syslog.journaux_auth (6 mois)
| Pare-feu pfSense | Règle |
|---|---|
WEB, BDD, USERS → srv-supervision | X subnets → SRV_SUPERVISION : PORTS_SYSLOG (TCP 514), une par onglet |
| ADM | aucune : même VLAN que srv-supervision |
| pfSense lui-même | aucune : le trafic part du pare-feu |
4 · Le serveur de réception (srv-supervision)
4.1 Installer
sudo apt-get install -y --no-install-recommends rsyslog rsyslog-mysql dbconfig-no-thanks
dbconfig-no-thanks:rsyslog-mysqldépend dedbconfig-mysqlou dedbconfig-no-thanks. Le premier voudrait créer lui-même la base et poserait des questions ; le second lui dit « la base est prête, n’y touche pas ».
systemctl is-active rsyslog; ls /usr/lib/x86_64-linux-gnu/rsyslog/ | grep -E "ommysql|imtcp"
active, imtcp.so, ommysql.so.
4.2 Les deux fichiers de réception
Copies de référence : 30-reception-galera.conf (TCP, machines Linux et Windows) et
31-reception-pfsense.conf (UDP, pfSense seul).
| Partie | Rôle |
|---|---|
input(type="imtcp" port="514" address="10.0.30.15" ruleset="distant") | écoute TCP sur l’adresse de la machine ; les messages reçus suivent leurs propres règles et ne vont pas dans /var/log/ local |
input(type="imudp" … ruleset="pfsense") + if ($fromhost-ip != "10.0.30.1") then stop | l’UDP n’est accepté que de pfSense |
if ($syslogfacility-text == "auth" or … "authpriv") | le tri vers journaux_auth |
template(… option.sql="on") | transforme le message en INSERT ; protège les apostrophes ; machine et programme coupés à 64 caractères (taille des colonnes) |
action(type="ommysql" server="127.0.0.1" … queue.type="LinkedList" queue.filename=… queue.maxDiskSpace="1g" queue.saveOnShutdown="on" action.resumeRetryCount="-1") | écriture par le HAProxy local, file d’attente sur disque de 1 Go, réessai sans fin : aucun journal perdu si la base ne répond pas |
4.3 Installer les fichiers et placer le mot de passe
Le fichier est transféré, pas collé (un long collage dans un terminal web arrive abîmé, incident H-24). Depuis le PC :
scp "<dossier>\annexes\scripts\supervision\srv-supervision\30-reception-galera.conf" ipfixe@10.0.30.15:/tmp/
Sur srv-supervision, droits 600 (le fichier contiendra un mot de passe) :
sudo install -m 600 -o root -g root /tmp/30-reception-galera.conf /etc/rsyslog.d/30-reception-galera.conf && rm /tmp/30-reception-galera.conf
Le mot de passe est demandé sans écho et ne passe pas par l’historique :
read -rsp "Mot de passe rsyslog : " P; echo; sudo sed -i "s|<mot-de-passe-rsyslog>|$P|g" /etc/rsyslog.d/30-reception-galera.conf; unset P; sudo grep -c "<mot-de-passe-rsyslog>" /etc/rsyslog.d/30-reception-galera.conf
0 (plus d’emplacement vide). Même chose pour 31-reception-pfsense.conf.
4.4 Valider, puis redémarrer
sudo rsyslogd -N1 && sudo systemctl restart rsyslog && sleep 2 && sudo ss -lntup | grep ':514'
End of config validation run. Bye., puis tcp … 10.0.30.15:514 et udp … 10.0.30.15:514.
Validation
logger -T -n 10.0.30.15 -P 514 "test : journal ordinaire"; logger -T -n 10.0.30.15 -P 514 -p auth.info "test : journal d'authentification"
mariadb -h 127.0.0.1 -u grafana_lecture -p -e "SELECT hote, programme, message FROM syslog.journaux ORDER BY id DESC LIMIT 1; SELECT hote, programme, message FROM syslog.journaux_auth ORDER BY id DESC LIMIT 1;"
chaque message dans sa table, l’apostrophe intacte.
5 · Ajouter une machine Linux (depuis le bastion)
C’est la même commande que pour les mesures (MO-13 §8) : ajouter-machine.sh lance aussi
installer-rsyslog-client.sh, qui sur la machine :
| Étape | Détail |
|---|---|
installe rsyslog s’il manque | --no-install-recommends (4 paquets, 2,3 Mo) ; attend jusqu’à 5 min si une autre installation tourne (H-32) ; s’arrête avec un message clair si le paquet manque et qu’il n’y a pas d’Internet |
crée /etc/rsyslog.d/90-vers-supervision.conf | *.* action(type="omfwd" target="10.0.30.15" port="514" protocol="tcp" …) avec une file d’attente de 200 Mo |
| règle l’heure sur pfSense | /etc/systemd/timesyncd.conf.d/pfsense.conf : NTP=<passerelle> (voir §8) |
| envoie deux messages de test | un ordinaire, un auth.info |
Sur srv-docker (scripts déposés dans ~/supervision) :
cd ~/supervision && bash ajouter-machine.sh 10.0.10.11 ipfixe
OK : journaux envoyes a srv-supervision (10.0.30.15:514) puis Ses journaux partent vers srv-supervision.
« OK » veut dire « parti », pas « arrivé ». La preuve est dans la base (§7) — surtout pour les zones séparées par le pare-feu.
Zone BDD (pas d’Internet) : si rsyslog manque, ouvrir la règle BDD « TEMPORAIRE », lancer le script, refermer, vérifier ferme
(timeout 5 bash -c '</dev/tcp/deb.debian.org/80' && echo ouvert || echo ferme). Procédure détaillée : MO-13 §8.4.
6 · pfSense
Status → System Logs → Settings :
| Champ | Valeur | Pourquoi |
|---|---|---|
| Log Message Format | syslog (RFC 5424…) | nom de la machine et heure exacte clairement écrits ; avec l’ancien format BSD, rsyslog risquerait de confondre programme et machine |
| Local Logging | laisser décoché « Disable writing log files » | le désactiver coupe aussi la Login Protection |
| Enable Remote Logging | ||
| Source Address | ADM | pfSense envoie depuis 10.0.30.1, la seule adresse que srv-supervision accepte en UDP |
| IP Protocol | IPv4 | |
| Remote log servers | 10.0.30.15:514 | pfSense n’envoie qu’en UDP (le texte sous la case le précise) |
| Remote Syslog Contents | Everything | pare-feu, interface web, DHCP, DNS… ; à réduire si le volume l’exige |
Save.
Validation — une minute plus tard :
mariadb -h 127.0.0.1 -u grafana_lecture -p -e "SELECT hote, programme, COUNT(*) AS nb FROM syslog.journaux WHERE recu_le > NOW() - INTERVAL 5 MINUTE GROUP BY hote, programme ORDER BY nb DESC LIMIT 10;"
SIO2527-pfSense-axel.sio.internal avec filterlog (pare-feu) et nginx (interface web).
91a-pfsense-journaux-format-rfc5424.png · 91b-pfsense-journaux-envoi-distant.png
7 · Interroger les journaux
Toujours depuis srv-supervision, avec le compte en lecture seule grafana_lecture (mot de passe demandé par -p).
| Question | Requête |
|---|---|
| Qui envoie quoi ? | SELECT 'journaux' t, hote, COUNT(*) FROM syslog.journaux GROUP BY hote UNION ALL SELECT 'auth', hote, COUNT(*) FROM syslog.journaux_auth GROUP BY hote ORDER BY t, hote; |
| Qu’est-ce qui est le plus bavard (5 dernières minutes) ? | SELECT hote, programme, COUNT(*) nb FROM syslog.journaux WHERE recu_le > NOW() - INTERVAL 5 MINUTE GROUP BY hote, programme ORDER BY nb DESC LIMIT 10; |
| Les dernières erreurs | SELECT recu_le, hote, programme, LEFT(message,120) FROM syslog.journaux WHERE gravite <= 3 ORDER BY id DESC LIMIT 20; |
| Les connexions SSH d’une machine | SELECT recu_le, LEFT(message,120) FROM syslog.journaux_auth WHERE hote='srv-web-01' AND programme='sshd' ORDER BY id DESC LIMIT 20; |
(Les deux dernières requêtes sont des exemples de lecture standard, non encore utilisés dans le lab : À VÉRIFIER au premier usage.)
Pour supprimer des lignes (bruit, essais), il faut le compte d’administration sur un nœud (sudo mariadb) : aucun compte de srv-supervision n’en a le droit.
8 · Les deux défauts que la centralisation a révélés
| Constat | Correction | Incident |
|---|---|---|
| Une machine envoie des dizaines de milliers de lignes « info » : le blackbox exporter (5 lignes par sonde réussie) | --log.level=warn dans /etc/default/prometheus-blackbox-exporter ; lignes effacées depuis un nœud | H-34 |
systemd-timesyncd échoue en boucle sur WEB et BDD : Timed out … debian.pool.ntp.org — les horloges n’avaient jamais été synchronisées (zones fermées) | heure demandée à pfSense : printf '[Time]\nNTP=%s\n' "$(ip route | awk '/^default/ {print $3; exit}')" dans /etc/systemd/timesyncd.conf.d/pfsense.conf ; intégré à l’installeur | H-35 |
Des journaux n’ont de valeur que si les horloges concordent : sans cela, « depuis quand ? » n’a plus de réponse.
9 · Conservation et purge automatique
Contexte — sans purge, la base grossit sans fin (≈ 60 Mo par jour mesurés sur 48 h, fin octobre). Objectif — garder les journaux 6 mois, puis les supprimer chaque nuit, sans gêner le cluster.
9.1 La durée, et pourquoi
| Référence | Ce qu’elle dit |
|---|---|
| CNIL, recommandation sur la journalisation | conserver les traces de 6 mois à 1 an |
| ANSSI, guide de journalisation (§3.4.5, R24 à R26) | fixer et appliquer une politique de conservation |
Décision d’Axel : 6 mois pour journaux et journaux_auth.
9.2 Le compte de purge (sur un nœud Galera)
Le compte rsyslog ne sait qu’écrire ; grafana_lecture ne sait que lire. La purge a son propre compte, limité à
ce qu’elle fait : lire et supprimer dans syslog.
CREATE USER 'purge_journaux'@'10.0.30.15' IDENTIFIED BY '<mot-de-passe>';
GRANT SELECT, DELETE ON syslog.* TO 'purge_journaux'@'10.0.30.15';
Mot de passe généré, rangé dans Bitwarden. Le compte est répliqué sur les trois nœuds.
9.3 Le fichier de connexion (sur srv-supervision)
Lire l’invite avant de taper : ce fichier va sur
srv-supervision, pas sur le nœud où l’on vient de créer le compte (H-63).
sudo install -m 600 -o root -g root /dev/null /etc/purge-journaux.cnf
Contenu (modèle : scripts/supervision/purge-journaux.cnf.exemple) : [client], user=purge_journaux,
password="<mot-de-passe>", host=127.0.0.1, port=3306 (HAProxy local). Le mot de passe est saisi par read -rsp
puis écrit dans le fichier : il n’apparaît dans aucune commande ni dans l’historique.
sudo mariadb --defaults-extra-file=/etc/purge-journaux.cnf -N -e "SELECT CURRENT_USER();"
9.4 Le script et le minuteur
purger-journaux.sh (dans scripts/supervision/) supprime ce qui a plus de JOURS jours (180 par défaut) par
paquets de 5 000 lignes, en boucle, avec une seconde de pause entre deux paquets :
DELETE FROM syslog.journaux WHERE recu_le < UTC_TIMESTAMP() - INTERVAL 180 DAY LIMIT 5000; SELECT ROW_COUNT();
Pourquoi par paquets : dans Galera, une transaction est certifiée et appliquée sur les trois nœuds d’un bloc. Une suppression de plusieurs centaines de milliers de lignes ferait une transaction énorme qui bloquerait la réplication. Des petits paquets passent l’un après l’autre. L’index
idx_recu(surrecu_le, MO-14) évite de parcourir toute la table.
sudo install -m 750 -o root -g root purger-journaux.sh /usr/local/sbin/purger-journaux.sh
sudo install -m 644 purger-journaux.service purger-journaux.timer /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now purger-journaux.timer
Le minuteur se déclenche chaque nuit à 04:30 (après les sauvegardes de 02:00) ; Persistent=true rattrape un
passage manqué si la machine était éteinte.
Validation
sudo SIMULATION=1 /usr/local/sbin/purger-journaux.sh
0 lignes de plus de 180 jours pour chaque table (rien n’a encore 6 mois).
sudo SIMULATION=1 JOURS=10 /usr/local/sbin/purger-journaux.sh
des lignes comptées, rien supprimé (01/11 : 98 179 et 37 511).
systemctl list-timers purger-journaux.timer
le prochain passage affiché (01/11 : lundi 02/11 à 04:30).
Validé aussi le 01/11 : une suppression faite dans une transaction puis annulée (ROLLBACK) rend toutes les lignes ;
exécution manuelle du service sans erreur.
10 · Pièges et checklist
| Piège | Symptôme | Où c’est documenté |
|---|---|---|
| Long fichier collé dans le terminal web | configuration abîmée | H-24 |
| Verrou d’apt pris par une mise à jour automatique | Impossible d'obtenir le verrou | H-32 |
| Vérification trop pressée | « port n’écoute pas » alors que le service tourne | H-33 |
| Programme trop bavard | table qui grossit de 100 000 lignes par jour | H-34 |
| Horloges non synchronisées | Timed out waiting for reply … :123 | H-35 |
Tester une règle TCP avec ping | échec trompeur | MO-13 §8.4 |
| Fichier de mot de passe créé sur la mauvaise machine | la purge ne peut pas se connecter | H-63 |
srv-supervision : rsyslog + rsyslog-mysql + dbconfig-no-thanks ; fichiers 30/31 en 600 ; mot de passe placé (grep = 0)
rsyslogd -N1 OK ; écoute TCP et UDP sur 10.0.30.15:514 ; test logger dans les deux tables
Chaque Linux : ajouter-machine.sh depuis le bastion → « OK : journaux envoyes »
Zone BDD : fenêtre Internet ouverte seulement si un paquet manque, refermée, test « ferme »
pfSense : RFC 5424, Remote Logging vers 10.0.30.15:514, source ADM
Comptage par machine en base : toutes présentes, aucune démesurée
Horloges : timedatectl → synchronized: yes partout
Purge : compte purge_journaux (SELECT, DELETE) ; /etc/purge-journaux.cnf 600 sur srv-supervision
SIMULATION=1 → 0 ligne ; timer purger-journaux actif, prochain passage 04:30
La règle à retenir en une phrase : chaque machine envoie une copie en TCP, srv-supervision trie et range dans le cluster, et c’est le comptage en base —
pas le message « OK » — qui prouve que ça marche.
