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 syslog et le compte rsyslog (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 rsyslog n’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
1Le besoin
2Théorie : syslog, catégories, gravités, TCP ou UDP
3L’architecture retenue
4Le serveur de réception (srv-supervision)
5Ajouter une machine Linux (depuis le bastion)
6pfSense
7Interroger les journaux
8Les deux défauts que la centralisation a révélés
9Conservation et purge automatique
10Piè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 :

ChampExemplesUtilité 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ébogagefiltrer l’important
Machine, programme, messagesrv-web-01, sshd, Accepted publickey for ipfixe…répondre à « qui, quoi »
TransportPourContre
UDP (514)simple, tout le monde le parleun message perdu l’est sans que personne ne le sache
TCP (514)livraison garantie, et l’émetteur sait si le serveur ne répond pasun 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 pfSenseRègle
WEB, BDD, USERS → srv-supervisionX subnets → SRV_SUPERVISION : PORTS_SYSLOG (TCP 514), une par onglet
ADMaucune : même VLAN que srv-supervision
pfSense lui-mêmeaucune : 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-mysql dépend de dbconfig-mysql ou de dbconfig-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).

PartieRô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 stopl’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 :

ÉtapeDé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 testun 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 :

ChampValeurPourquoi
Log Message Formatsyslog (RFC 5424…)nom de la machine et heure exacte clairement écrits ; avec l’ancien format BSD, rsyslog risquerait de confondre programme et machine
Local Logginglaisser décoché « Disable writing log files »le désactiver coupe aussi la Login Protection
Enable Remote Logging
Source AddressADMpfSense envoie depuis 10.0.30.1, la seule adresse que srv-supervision accepte en UDP
IP ProtocolIPv4
Remote log servers10.0.30.15:514pfSense n’envoie qu’en UDP (le texte sous la case le précise)
Remote Syslog ContentsEverythingpare-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).

QuestionRequê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 erreursSELECT recu_le, hote, programme, LEFT(message,120) FROM syslog.journaux WHERE gravite <= 3 ORDER BY id DESC LIMIT 20;
Les connexions SSH d’une machineSELECT 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

ConstatCorrectionIncident
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œudH-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’installeurH-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érenceCe qu’elle dit
CNIL, recommandation sur la journalisationconserver 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();"

[email protected].

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 (sur recu_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ègeSymptômeOù c’est documenté
Long fichier collé dans le terminal webconfiguration abîméeH-24
Verrou d’apt pris par une mise à jour automatiqueImpossible d'obtenir le verrouH-32
Vérification trop pressée« port n’écoute pas » alors que le service tourneH-33
Programme trop bavardtable qui grossit de 100 000 lignes par jourH-34
Horloges non synchroniséesTimed out waiting for reply … :123H-35
Tester une règle TCP avec pingéchec trompeurMO-13 §8.4
Fichier de mot de passe créé sur la mauvaise machinela purge ne peut pas se connecterH-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.