Licence pro ASS&RProductionLecture : 7 min

Protéger le serveur SIEM et faire expliquer ses alertes par une IA locale

Le serveur SIEM est la machine la plus sensible du réseau : je l'ai protégé, puis j'ai branché sur Wazuh un modèle de langage local qui explique chaque alerte critique en français.

Contexte
Production · PME, serveur SIEM Wazuh sous Ubuntu 22.04 (Hyper-V)
Période
Juin 2026
Mon rôle
Conception, scripts et déploiement en autonomie
Outils
Wazuh · ClamAV · Lynis · n8n · Ollama · Veeam B&R

En bref

Le problème

Le SIEM de la PME n'avait ni antivirus, ni audit de durcissement, ni sauvegarde, et ses alertes brutes, en anglais, se lisaient mal en plein incident.

Ce que j'ai fait

J'ai ajouté ClamAV, un audit Lynis hebdomadaire et une sauvegarde Veeam, puis un pipeline local n8n et Ollama qui explique les alertes de niveau 10 ou plus.

Le résultat

Un indice Lynis de 64 sur 100 au premier audit, suivi chaque semaine, 14 jours de sauvegardes, alertes critiques résumées en 3 lignes et une action, sans IA externe.

3lignesen français pour expliquer chaque alerte critique, puis une action
0alerte envoyée à un service d'IA externe : l'analyse reste sur le serveur
≥ 10niveau d'alerte Wazuh qui déclenche l'e-mail rédigé par l'IA
14joursde rétention des sauvegardes de la VM

Contexte

Second volet du projet SOC Wazuh, mené dans la foulée en juin 2026, pour l'entreprise, une PME de distribution d'une vingtaine de personnes. Le serveur SIEM n'était pas protégé : compromis, il livre tous les journaux de sécurité et permet d'effacer des traces ; perdu, il emporte règles, intégrations et historique.

Ses alertes étaient denses : identifiants de règles, journaux en anglais, à décoder en plein incident. Deux contraintes : rien à acheter, et aucune alerte envoyée à un service d'IA externe.

E-mail de notification Wazuh affichant la règle 5763, l'adresse IP source interne et huit lignes de journaux sshd d'échecs d'authentification ; expéditeur et destinataire masqués.
Fig. 1Avant : notification Wazuh native d'une force brute SSH (règle 5763, niveau 10), une liste de journaux bruts sans explication ni action recommandée.

Ce que j'ai fait

  1. Un antivirus pour le serveur lui-mêmeClamAV analyse chaque nuit les répertoires sensibles et écrit au format qu'attend le décodeur de Wazuh. Un fichier de test EICAR a bien levé l'alerte « ClamAV: Virus detected ».
  2. Mesurer le durcissementLynis audite le serveur chaque dimanche : un premier indice de 64 sur 100, sur 275 tests, celui d'un Ubuntu jamais durci, sert de référence. Une dérive de configuration se voit comme une baisse du score.
  3. Sauvegarder le SIEML'agent Linux de Veeam ne pouvait pas prendre de snapshot : job natif par l'intégration Hyper-V, avec suivi des blocs modifiés et 14 jours de rétention.
  4. Faire expliquer les alertesÀ partir du niveau 10, Wazuh appelle n8n, qui interroge le modèle llama3.2:3b sur le serveur : trois lignes en français au plus, puis une action concrète.
  5. Encadrer le modèleSur les descriptions de règles au jargon dense, il complétait par des formules plausibles, jusqu'à inventer une règle de conformité. Prompt durci, température abaissée, et rejet de toute traduction plus longue que 2,2 fois l'original.
Voir les détails techniques

ClamAV. Le moteur clamd reste en mémoire, freshclam met à jour les signatures plusieurs fois par jour. À 3 h, un script lancé par cron analyse les répertoires utilisateurs, les scripts installés à la main, /tmp, le répertoire de Wazuh et /root. Le décodeur fourni avec Wazuh (0075-clamav_decoders.xml) ne reconnaît une ligne que si elle porte le nom de programme clamd : le script écrit exactement ce préfixe, faute de quoi le fichier remonterait sans qu'aucune détection ne se déclenche.

Wazuh · ossec.conf

<localfile>
  <log_format>syslog</log_format>
  <location>/var/log/clamav/daily-scan.log</location>
</localfile>

Bash · validation de bout en bout

# 1. Fichier de test EICAR, inoffensif, reconnu par tous les antivirus
#    (chaîne omise ici : elle ferait réagir l'antivirus de votre poste)
echo '<chaîne de test EICAR>' > /tmp/eicar-test.txt

# 2. Lancer l'analyse comme le fait cron
sudo /opt/clamav-scan.sh

# 3. Vérifier que Wazuh a produit l'alerte
sudo grep "52502" /var/ossec/logs/alerts/alerts.json | tail -1 | python3 -m json.tool

Règle 52502, niveau 8 sur 15, sur l'agent 000 (le serveur lui-même) ; trois alertes de ce type indexées pendant la validation, puis aucun fichier de test resté dans /tmp.

Terminal Linux : résultat JSON de requête sur l'indexer avec plusieurs alertes « ClamAV: Virus detected », création puis suppression du fichier de test EICAR et vérification finale.
Fig. 2Test EICAR sur le serveur SIEM : ClamAV détecte le fichier de test, l'alerte « ClamAV: Virus detected » est indexée dans Wazuh, puis aucun fichier résiduel ne reste dans /tmp.

Lynis. Pare-feu et ClamAV bien repérés. Parmi les avertissements, une synchronisation de l'heure en retard, corrigée par un redémarrage du service et confirmée au scan suivant. Wazuh lit la sortie de Lynis, et le bilan quotidien affiche l'indice dans un bandeau coloré selon son niveau.

cron · /etc/cron.d/lynis-weekly

# Dimanche, 4 h
0 4 * * 0 root lynis audit system --cronjob > /dev/null 2>&1

L'agent Linux de Veeam ne peut pas prendre de snapshot

Problème

Le module noyau nécessaire aux snapshots de volume ne se chargeait pas sur la version du noyau en place, malgré le paquet installé.

Résolution

Sauvegarder de l'intérieur impose un module dans le système invité ; Veeam sait traiter Hyper-V de l'extérieur. Job natif par l'hyperviseur, sans rien installer dans Ubuntu, Changed Block Tracking activé : première sauvegarde complète sans erreur ni avertissement.

L'entreprise utilisait déjà Veeam Backup & Replication pour ses VM Windows, un outil vu en BTS dans un projet de sauvegarde et de restauration de VM. Effet de bord : la connexion SSH de Veeam au serveur a déclenché une alerte Wazuh de connexion réussie. Les connexions SSH sont bien surveillées, et un outil légitime produit lui aussi des alertes.

Console Veeam Backup & Replication : job Hyper-V du serveur SIEM en succès, durée 05:40, 136,5 Go traités, 5,5 Go transférés, aucune erreur ni avertissement.
Fig. 3Sauvegarde Veeam du serveur SIEM par l'intégration Hyper-V : job réussi en 5 min 40 s, 136,5 Go traités et suivi des blocs modifiés (CBT) activé.

Pipeline IA. Ollama exécute le modèle sur place ; llama3.2:3b, environ 2 Go, tourne sur le processeur, la VM n'ayant pas de carte graphique. n8n, un orchestrateur low-code, reçoit l'alerte en JSON (niveau, machine, règle, horodatage, adresse source), interroge le modèle et compose l'e-mail : détails techniques, explication et action recommandée.

Wazuh · ossec.conf (chemin du webhook masqué)

<integration>
  <name>custom-n8n</name>
  <hook_url>http://localhost:5678/webhook/<chemin></hook_url>
  <level>10</level>
  <alert_format>json</alert_format>
</integration>

Les alertes reçues en Syslog ne partent pas

Problème

Les alertes des agents arrivaient dans n8n, pas celles des sources Syslog. Par défaut, ce mécanisme d'intégration ignore l'agent 000, le manager lui-même, auquel tout le Syslog est rattaché.

Résolution

Un second bloc d'intégration qui cible l'identifiant de la règle au lieu de l'agent. La méthode vaut pour toute nouvelle source Syslog.

Avant et après la réécriture du rapport quotidien : la première version lisait un fichier local incomplet et ignorait les erreurs JSON ; la seconde interroge l'indexer Wazuh, la même source que le tableau de bord. Première version Fichier local ne contient qu'une partie des alertes Script du rapport lecture ligne par ligne Bloc except erreurs JSON ignorées en silence Rapport du matin 358 alertes ≥ 8 0 de niveau 11–12 Après réécriture Indexer Wazuh source de vérité (OpenSearch) Script réécrit une seule fonction de requête Agrégations côté serveur (volume Suricata) Rapport du matin volumes conformes au tableau de bord
Fig. 4Le calcul était juste, la source était incomplète : le bilan interroge désormais l'indexer, la même source que le tableau de bord.

Bilan quotidien. Volumes par gravité, machines les plus actives, types d'alertes fréquents, une fiche par type d'alerte critique. La version erronée annonçait 358 alertes de niveau 8 ou plus ; une requête directe à l'indexer donnait le chiffre du tableau de bord. La réécriture garde la présentation, avec une fonction de requête partagée par toutes les sections. Au passage : ordre chronologique corrigé, repli pour l'adresse source des alertes Syslog, agrégation côté serveur pour le volume Suricata, qui plafonnait à la taille maximale d'une requête. J'ai ajouté une corrélation : une adresse IP vue par plusieurs sources en 24 heures est un signal plus fort qu'une détection isolée.

Traductions. Une description portant sur un paquet réseau hors séquence est revenue avec une règle de conformité inventée. Le prompt durci impose une traduction littérale, sans information absente du texte source ; sur les cas observés, le contrôle de longueur trahissait bien les hallucinations. Les signatures techniques, comme « ET SCAN Potential SSH Scan », restent en anglais, comme dans l'usage de la profession.

L'incident

184 alertes critiques simulées, aucune dans le bilan du matin

Problème

Chaque matin à 9 h, un script envoie le bilan des 24 heures. La veille, j'avais simulé 184 alertes de niveau 12 ou plus ; le bilan n'en comptait aucune de niveau 11 ou 12.

Résolution

Le script lisait un fichier local incomplet, et un bloc except avalait en silence les erreurs JSON. Je l'ai réécrit pour interroger l'indexer de Wazuh, la même source que le tableau de bord.

Résultats

Pipeline d'enrichissement : Wazuh envoie les alertes de niveau 10 ou plus à n8n, qui interroge le modèle local Ollama puis envoie un e-mail en français à l'équipe IT. Avant le projet, l'e-mail natif était brut et en anglais. Serveur SIEM · traitement local, aucune IA externe Wazuh alerte de niveau ≥ 10 n8n reçoit l'alerte en JSON Ollama · llama3.2:3b modèle local, CPU seul webhook prompt Avant ce projet e-mail brut, en anglais E-mail en français via Microsoft 365 3 lignes, 1 action Équipe IT lit, décide, agit
Fig. 5À partir du niveau 10, l'alerte passe par n8n et le modèle local avant d'arriver dans la boîte de l'équipe. Aucune action automatique : la décision reste humaine.

Une alerte critique arrive désormais en français : ce qui s'est passé, en trois lignes, et l'action à faire tout de suite. L'analyse reste sur le serveur ; l'e-mail final passe par la messagerie Microsoft 365 de l'entreprise.

Ce pipeline enrichit l'alerte, il ne répond pas : rien n'est bloqué ni isolé automatiquement. Le temps de réponse du modèle sur processeur n'a pas été mesuré. Pour une vue d'ensemble rapide, une page HTML de synthèse est régénérée chaque minute.

E-mail « [ALERTE 10/15] » (nom de la machine masqué) : machine impactée, description, niveau d'alerte, puis une section « Analyse IA » expliquant la tentative de force brute SSH et l'action recommandée ; expéditeur et destinataire masqués.
Fig. 6Après : la même alerte enrichie par le modèle local (Ollama et n8n), avec une explication en français et une action immédiate à mener.

Ce que j'améliorerais

  • Isoler l'enrichissement : sur un prochain déploiement, je placerais l'orchestrateur et le modèle sur une VM séparée, avec un compte limité à la lecture des alertes ; chaque service ajouté au SIEM est une surface d'attaque de plus. Et je lirais chaque script d'installation avant de l'exécuter, plutôt que curl | sh.
  • Mesurer après chaque correction : appliquer les suggestions de Lynis par lots et noter le score après chaque lot.
  • Prouver la sauvegarde par la restauration : restaurer la VM sur un réseau isolé d'Hyper-V et chronométrer l'opération.

Compétences

  • Durcissement d'un serveur Linux
  • Wazuh et OpenSearch
  • IA locale avec garde-fous
  • Automatisation avec n8n
  • Débogage à partir d'une source de vérité
  • Sauvegarde Veeam

Pour aller plus loin