Mode opératoire — Détection d’intrusion : Wazuh (serveur et agents) et Suricata (sonde réseau sur pfSense)
Document autonome. Partie théorique, puis mise en œuvre telle qu’elle a été réalisée et vérifiée les 02 et 03/11/2026 sur
srv-wazuh(10.0.30.16, Ubuntu Server 24.04, VM 113) et sur le pare-feufw-01(pfSense 2.9.0, 2 Gio) — phase 16 du suivi, tâches 16.2 à 16.10. La méthode vaut pour toute infrastructure qui veut être prévenue d’une attaque, et pas seulement d’une panne. Prérequis : MO-18-Ajouter-une-machine.md (intégrer la nouvelle VM avant d’y installer son rôle ; §4.3 et §5.5 : l’agent Wazuh sur une machine), MO-4-Cles-SSH.md. Contexte et preuves : Documentation-pfSense.md (étapes 59 et 60), dossier de choix.Valeurs masquées. Aucun mot de passe ici : le mot de passe
adminde Wazuh, le mot de passe d’inscription des agents et les mots de passe internes sont dans le gestionnaire de mots de passe (entrées « Wazuh »).Dernière mise à jour : 04/11/2026 (§11.2 : filtrer le bruit des Windows) État au 12/11/2026 : 5 agents + le serveur :
srv-ha,ad-core-01,poste-win11,srv-web-01,srv-web-02(les nouveaux postes Windows reçoivent l’agent par la GPO de la phase 21). Semaine de mesure terminée (bilan du 11/11 : mémoire 2,5 à 2,7 Gio sur 5,8, swap peu actif, disque stable) → extension à toutes les machines décidée (16.7, à faire). Le schéma du §3 montre la cible, pas l’état actuel.
Sommaire
| § | Contenu |
|---|---|
| 1 | Le besoin, et pourquoi Wazuh + Suricata |
| 2 | Théorie : agents, manager, indexeur, niveaux, enrôlement |
| 3 | L’architecture retenue |
| 4 | La machine virtuelle, et son intégration avant tout |
| 5 | Installer le serveur tout-en-un |
| 6 | Exiger un mot de passe d’inscription |
| 7 | Le pare-feu : un flux par zone |
| 8 | Les agents, par script |
| 9 | Suricata sur pfSense |
| 9 bis | Les alertes de Suricata dans Wazuh |
| 10 | Tester la détection |
| 11 | Exploiter : lire les alertes, mesurer, suivre |
| 11 bis | Prévenir par mail |
| 12 | Pièges et checklist |
1 · Le besoin, et pourquoi Wazuh + Suricata
La supervision du lab (Prometheus, Grafana, journaux dans Galera) répond à « est-ce que ça marche ? ». Elle voit une panne, un disque plein, une rafale de mots de passe faux. Elle ne voit pas une attaque qui ne casse rien : un fichier système modifié, un compte créé en douce, un balayage de ports, un exploit qui passe sur le réseau.
| Outil | Où il regarde | Verdict |
|---|---|---|
| Les alertes Grafana existantes | les mesures et les journaux déjà collectés | utiles, mais aveugles à l’intérieur des machines et au trafic |
| CrowdSec | les journaux ; partage d’adresses malveillantes avec une communauté | écarté : doublon de Wazuh sur les journaux, ne voit ni les fichiers ni les comptes, et des adresses sortent du lab |
| Snort (paquet pfSense) | le réseau | écarté : même rôle que Suricata, qui est multi-cœurs et exporte en JSON |
| Wazuh | dans les machines : intégrité des fichiers, comptes, journaux de sécurité, configuration, vulnérabilités ; Linux et Windows | retenu ; libre ; un écran dédié ; lit les alertes de Suricata |
| Suricata | le réseau, sur le pare-feu que tout trafic inter-zones traverse | retenu en complément : ce que Wazuh ne voit pas (les appareils sans agent, les balayages) |
Les quatre conditions de la décision (02/11) sont dans le dossier de choix §4.
2 · Théorie : agents, manager, indexeur, niveaux, enrôlement
| Notion | Ce que c’est |
|---|---|
| Agent | un petit service installé sur chaque machine surveillée (Linux, Windows, macOS). Il lit les journaux, calcule les empreintes des fichiers système, inventorie comptes et logiciels, et envoie tout au serveur |
| Manager | le serveur qui reçoit les événements des agents et les passe dans ses règles : c’est lui qui décide « ceci est une alerte de niveau 10 » |
| Indexeur | une base OpenSearch qui stocke et indexe les alertes pour l’écran ; c’est lui qui pèse en mémoire (Java), pas le nombre d’agents |
| Tableau de bord | l’écran web (port 443) : agents, alertes, audit de configuration, vulnérabilités |
| Niveau | la gravité d’une alerte, de 0 à 15. Repères du lab : fichier modifié = 7, compte créé = 8, force brute = 10. Les mails partent à partir de 10 (§11 bis, en service depuis le 03/11) |
| Enrôlement | l’inscription d’un agent : il se présente sur le port 1515, reçoit une clé, puis envoie ses événements sur le port 1514 (chiffré). Sans mot de passe d’inscription, n’importe quelle machine qui atteint 1515 peut s’inscrire |
| FIM (File Integrity Monitoring) | la surveillance d’intégrité des fichiers : l’agent compare les empreintes à intervalle régulier (règle 550 « Integrity checksum changed ») |
| EVE JSON | le format d’export de Suricata, un événement par ligne : Wazuh sait le lire tel quel |
Principe à retenir : Wazuh regarde dans les machines, Suricata regarde entre les zones. Les deux ensemble couvrent aussi les appareils qui n’auront jamais d’agent (zone VISITEURS).
Ports du serveur (documentation officielle, vérifiés à l’usage pour 1514, 1515 et 443) :
| Port | Usage | Qui s’y connecte |
|---|---|---|
| 1514/tcp | événements des agents | chaque machine équipée |
| 1515/tcp | enrôlement | chaque machine, une fois |
| 443/tcp | tableau de bord | administrateur (Tailscale, Pangolin) |
| 55000/tcp | API du manager | le tableau de bord (local) ; prévu dans le plan d’adressage, pas ouvert dans pfSense |
| 9200/tcp | indexeur | le manager et le tableau de bord (local) |
3 · L’architecture retenue
WEB (10) BDD (20) USERS (40) VISITEURS (50)
srv-ha ─ agent srv-mysql-0x ─ agent poste-win11 ─ agent poste-visiteur ─ agent
│ │ │ │ (10.0.50.200 seul)
└────────────────────┴──── 1514 / 1515 ───┴─────────────────────┘
│ une règle par zone, vers SRV_WAZUH seul, avant les rejets
▼
┌───────────────── ADM (30) · srv-wazuh 10.0.30.16 · 6 Gio fixes ─────────────────┐
│ wazuh-manager (règles, agents) ──► wazuh-indexer (OpenSearch, tas Java 1 Gio) │
│ wazuh-dashboard : https://10.0.30.16 (Tailscale) · wazuh.pangolin.<domaine> │
└──────────────────────────────────────────────────────────────────────────────────┘
▲ syslog 514/udp via srv-supervision (lignes « suricata » seulement, §9 bis)
pfSense fw-01 : Suricata, mode détection, interfaces VISITEURS (vtnet1.50) et USERS (vtnet1.40)
| Choix | Pourquoi |
|---|---|
| Serveur tout-en-un sur une VM dédiée | une seule machine à sauvegarder et à mesurer ; l’installeur officiel fait tout |
| 6 Gio fixes (minimum officiel : 8) | l’hyperviseur partagé est à 81 % ; essai assumé, mesuré une semaine (dette T-17) ; ballon désactivé : un serveur Java dont on reprend la mémoire plante (H-67) |
| Ubuntu Server 24.04 | dans la liste des systèmes supportés par Wazuh ; Debian n’y est pas |
| Zone ADM | serveur d’infrastructure, même VLAN que la supervision : aucune règle pour les agents de l’ADM |
| Mot de passe d’inscription exigé | sans lui, un invité qui atteint 1515 inscrit un faux agent |
| Suricata en détection seule, 2 zones | pfSense n’a que 2 Gio ; le blocage sur cartes virtuelles n’est pas vérifié et un faux positif couperait un service (dette T-18) |
4 · La machine virtuelle, et son intégration avant tout
Contexte : Proxmox, pool du lab. Objectif : une VM intégrée à l’environnement (Termix, supervision, alertes, sauvegarde, adressage) avant d’y installer Wazuh. Si elle casse pendant l’installation, on la voit et on la restaure.
| Élément | Valeur retenue |
|---|---|
| VM | 4 vCPU (2 au minimum), 6144 / 6144 Mio (Hardware → Memory : minimum = maximum, ballon décoché), disque 64 Go |
| Système | Ubuntu Server 24.04, sans interface graphique, OpenSSH coché à l’installation |
| Réseau | vmbr1, étiquette 30, IP fixe 10.0.30.16/24, passerelle et DNS 10.0.30.1 |
| Compte | ipfixe (sudo), mot de passe dans Bitwarden avant tout |
| Agent QEMU | paquet qemu-guest-agent et option cochée dans Proxmox, puis arrêt/démarrage (un reboot ne suffit pas, H-69) |
Deux pièges de l’installeur Ubuntu (H-68) : le champ « Masque de sous-réseau » attend le réseau (
10.0.30.0/24) ; le partitionnement LVM ne donne que la moitié du disque à la racine. Agrandir :
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv && sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv && df -h /
/ à la taille du disque (03/11 : 31 → 61 Go).
Puis les six points du MO-18 : (a) Termix par clé, mot de passe SSH interdit ;
(b) ajouter-machine.sh 10.0.30.16 depuis le bastion ; (c) up{host="srv-wazuh"} = 1 ; (d) « Machine injoignable »
compte une instance de plus ; (e) sauvegarde de la nuit suivante ; (f) adressage, registre, documentation, schéma.
Validation — sudo sshd -T | grep -i passwordauth → passwordauthentication no ; depuis une autre machine,
ssh -o PubkeyAuthentication=no [email protected] → Permission denied (publickey) ; up = 1 dans Prometheus ;
journaux dans la base dans l’heure (03/11 : 39 lignes) ; « Machine injoignable » à 15 instances (capture 146).
5 · Installer le serveur tout-en-un
Contexte : session Termix sur
srv-wazuh, compteipfixe, accès Internet de la zone ADM. Objectif : manager, indexeur et tableau de bord actifs sur la même machine, mot de passeadminrangé.
5.1 Télécharger l’installeur et le lire avant de le lancer. C’est un script qui tourne en root : on regarde au moins son en-tête (version, ce qu’il fait) et sa taille.
curl -sO https://packages.wazuh.com/4.14/wazuh-install.sh && ls -l wazuh-install.sh && head -30 wazuh-install.sh
un fichier d’environ 215 Ko, en-tête « Wazuh installer » version 4.14 (03/11).
5.2 Lancer l’installation tout-en-un (-a = all-in-one). Elle prend plusieurs minutes.
sudo bash wazuh-install.sh -a
La documentation prévoit une option pour ignorer le contrôle matériel si l’installeur refuse de tourner sous 8 Gio. Le 03/11, à 6 Gio, aucun blocage : l’option n’a pas servi (
bash wazuh-install.sh --helpla liste si besoin).
en fin d’installation, l’installeur affiche le compte admin et son mot de passe, et laisse une archive
wazuh-install-files.tar (tous les mots de passe internes).
5.3 Ranger les secrets, tout de suite.
- mot de passe
admin→ Bitwarden (Wazuh - admin), jamais dans un fichier ni dans le chat ; - l’archive hors du dossier de travail, lisible par root seul :
sudo mv wazuh-install-files.tar /root/ && sudo chmod 600 /root/wazuh-install-files.tar && sudo ls -l /root/wazuh-install-files.tar
5.4 Désactiver le dépôt apt (recommandation officielle : une mise à jour non préparée casserait l’accord de version entre le serveur et ses agents ; on met à jour volontairement, serveur d’abord, agents ensuite) :
sudo sed -i 's/^deb /#deb /' /etc/apt/sources.list.d/wazuh.list && sudo apt-get update -qq && grep ^#deb /etc/apt/sources.list.d/wazuh.list
5.5 Le tas Java de l’indexeur. C’est ce qui pèse. L’installeur l’avait déjà réglé à 1 Gio le 03/11 (moins que les 1,5 Gio prévus au cadrage) : gardé tel quel. Vérifier :
grep -E '^-Xm[sx]' /etc/wazuh-indexer/jvm.options
-Xms1024m et -Xmx1024m (valeurs égales : le tas ne grandit pas en cours de route). bootstrap.memory_lock
(mémoire verrouillée, hors swap) : prévu au cadrage, À VÉRIFIER dans /etc/wazuh-indexer/opensearch.yml.
5.6 Vérifier les trois services et la mémoire.
systemctl is-active wazuh-manager wazuh-indexer wazuh-dashboard && free -h
Validation — trois fois active ; le 03/11 juste après l’installation : 2,2 Gio utilisés sur 5,8, java
1,24 Go, swap 265 Mio (à suivre, §11.3). Tableau de bord : https://10.0.30.16, certificat autosigné accepté,
connexion avec admin. Accès externe : ressource Pangolin wazuh.pangolin.<domaine> (cible https 10.0.30.16:443,
contrôle de santé TCP, protégée), même modèle que Grafana (MO-10).
6 · Exiger un mot de passe d’inscription
Contexte : sur
srv-wazuh, avant le premier agent. Objectif : le serveur refuse tout agent qui ne présente pas le mot de passe.
6.1 Le mot de passe : généré, rangé dans Bitwarden (entrée « Wazuh - inscription des agents »), puis écrit dans le fichier attendu par le service d’enrôlement, sans jamais s’afficher :
read -rsp 'Mot de passe d inscription (Bitwarden) : ' MDP; echo; printf '%s\n' "$MDP" | sudo tee /var/ossec/etc/authd.pass >/dev/null; unset MDP; sudo chmod 640 /var/ossec/etc/authd.pass && sudo chown root:wazuh /var/ossec/etc/authd.pass && sudo ls -l /var/ossec/etc/authd.pass
-rw-r----- 1 root wazuh … authd.pass.
6.2 L’option dans ossec.conf (copie de sécurité d’abord) : dans le bloc <auth>, passer <use_password> à
yes.
sudo cp /var/ossec/etc/ossec.conf /var/ossec/etc/ossec.conf.avant-authd && sudo sed -i 's#<use_password>no</use_password>#<use_password>yes</use_password>#' /var/ossec/etc/ossec.conf && sudo systemctl restart wazuh-manager
6.3 Vérifier : lire tout le bloc, pas trois lignes. Le 03/11, un grep -A3 '<auth>' s’arrêtait avant la ligne
use_password et laissait croire que l’option manquait (H-71). Lire le bloc entier :
sudo sed -n '/<auth>/,/<\/auth>/p' /var/ossec/etc/ossec.conf | grep -E 'use_password|port' ; sudo grep -i 'password' /var/ossec/logs/ossec.log | tail -2
Validation — <use_password>yes</use_password> ; journal du manager : « Using password specified on
file ». Un agent lancé sans le bon mot de passe est refusé à l’enrôlement.
7 · Le pare-feu : un flux par zone
Contexte : pfSense, Firewall → Aliases puis Rules. Objectif : chaque zone atteint le seul serveur Wazuh, sur les deux ports, rien d’autre. Même modèle que les journaux (514).
| Objet | Valeur |
|---|---|
Alias SRV_WAZUH (Host) | 10.0.30.16 |
Alias PORTS_WAZUH (Port) | 1514, 1515 |
| Onglet WEB | WEB subnets → SRV_WAZUH : PORTS_WAZUH, TCP, placée avant le rejet |
| Onglet BDD | BDD subnets → SRV_WAZUH : PORTS_WAZUH : seconde exception assumée à « la base n’initie rien » |
| Onglet USERS | USERS subnets → SRV_WAZUH : PORTS_WAZUH |
| Onglet VISITEURS | 10.0.50.200 seul (le poste de test géré) ; jamais VISITEURS subnets |
| Onglet ADM | rien : même VLAN, le trafic ne traverse pas le pare-feu |
La source doit appartenir au VLAN de l’onglet. Une règle VISITEURS avec
USERS subnetsen source (copiée de l’onglet voisin) ne correspond à rien : le paquet tombe sur le rejet, refus immédiat (H-70, même leçon que B-05). Le refus est immédiat et journalisé : c’est le signe qu’une règle au-dessus n’a pas correspondu.
Validation — depuis une machine de chaque zone (Linux : nc -zv 10.0.30.16 1514 puis 1515 ; Windows :
Test-NetConnection 10.0.30.16 -Port 1514) : open / TcpTestSucceeded : True (03/11 : srv-web-01,
srv-mysql-01, poste-visiteur, poste-win11). Captures 147 à 152.
8 · Les agents, par script
Contexte : le pas à pas par machine est le point (b bis) du MO-18 (§4.3 Linux, §5.5 Windows). Ici : ce que font les scripts, et comment vérifier côté serveur.
Script (scripts/securite/) | Où | Ce qu’il fait |
|---|---|---|
ajouter-agent-wazuh.sh <IP> [<IP>…] | bastion srv-docker, compte ipfixe | vérifie la zone de l’adresse (en BDD : rappelle la règle Internet temporaire), lit le nom de la machine, demande le mot de passe d’inscription une fois pour toutes les machines, le transmet par SSH dans un fichier temporaire 600 effacé aussitôt lu, lance l’installeur ; ssh -t pour le sudo de la cible |
installer-wazuh-agent.sh <serveur> <nom> | la machine Linux, root | dépôt officiel signé, agent dans la version du serveur (4.14.9-1), inscription par WAZUH_MANAGER / WAZUH_AGENT_NAME / WAZUH_REGISTRATION_PASSWORD, dépôt désactivé ensuite, attente de status='connected' dans /var/ossec/var/run/wazuh-agentd.state (jusqu’à 60 s) |
installer-wazuh-agent.ps1 | la machine Windows, PowerShell administrateur | MSI 4.14.9-1 téléchargé, empreinte SHA-512 officielle vérifiée (sinon annulé), mot de passe d’inscription saisi en secret, msiexec /q, attente de status='connected' |
Même version que le serveur. Un agent plus récent que le manager est refusé : la version est figée dans les scripts (
wazuh-control infosur le serveur donne la sienne). Mettre à jour le serveur d’abord, puis changer la version dans les scripts.
Le serveur voit-il l’agent ? Sur srv-wazuh :
sudo /var/ossec/bin/agent_control -l
Validation — une ligne ID: 00x, Name: <machine>, IP: any, Active par machine. Le 03/11 : srv-ha (001),
ad-core-01 (002), poste-win11 (003), une machine de chaque type avant d’étendre. Dans le tableau de bord,
Agents : état Active, premiers résultats d’audit de configuration en quelques minutes.
Deux corrections au premier essai : le script Linux n’attendait que 10 s et annonçait un échec alors que l’agent était inscrit (H-72) ; sous Windows, le fichier
.sha512était reçu comme un binaire,Trimimpossible (H-73).
9 · Suricata sur pfSense
Contexte : pfSense 2.9.0, 2 Gio de RAM. Objectif : une sonde réseau en détection seule sur les zones VISITEURS et USERS, règles ET Open à jour, export EVE JSON pour Wazuh.
9.1 Avant tout : sauvegarde de la configuration (Diagnostics → Backup & Restore), et relevé de la mémoire libre
du pare-feu dans Prometheus (node_memory_MemFree_bytes de fw-01) : 03/11, 1 477 Mo avant Suricata.
9.2 Installer : System → Package Manager → Available Packages, suricata, Install.
9.3 Les réglages communs (Services → Suricata → Global Settings) :
| Réglage | Valeur | Capture |
|---|---|---|
| Jeux de règles | ETOpen coché seul (ETPro, Snort, Feodo, ABUSE.ch non) | 154 |
| Update Interval | 12 HOURS, heure de départ laissée avec ses minutes aléatoires ; Live Rule Swap décoché | 155 |
| Keep Suricata Settings After Deinstall | coché | 155 |
Puis Updates → Update : Result: success, jeu ET Open daté (capture 159).
9.4 Une interface (Interfaces → Add) :
| Réglage | Valeur | Capture |
|---|---|---|
| Enable, Interface | coché, VISITEURS (vtnet1.50), description parlante | 156 |
| Logging | journal HTTP (défaut) ; TLS, file-store, packet log, stats, verbose : non | 156, 157 |
| EVE Output | EVE JSON Log coché, type FILE, EVE Log Alerts coché, charge utile BOTH | 157 |
| Block Offenders | décoché (détection seule) | 158 |
| Categories | 7 catégories ET Open : attack_response, dos, exploit, malware, scan, shellcode, web_server | 160a-c |
Save, puis sur la liste des interfaces : démarrer (icône ▶). état vert, Blocking Mode DISABLED (capture 161).
Le moteur met ≈ 50 s à charger ses 23 000 règles. Un test lancé avant la ligne
Engine started.dusuricata.logne donne rien (H-76). Attendre, ou lire le journal : Logs View → suricata.log.
9.5 La seconde interface : icône Duplicate sur VISITEURS, changer l’interface en USERS (vtnet1.40) et la description, Save, démarrer (capture 163).
9.6 Relever la mémoire après chaque interface (même mesure qu’en 9.1, plus ps sur pfSense) :
| avant | VISITEURS | VISITEURS + USERS | |
|---|---|---|---|
| mémoire libre | 1 477 Mo | 827 Mo | 674 Mo |
processus suricata | — | 396 Mo | 396 + 368 Mo |
| swap | 0 | 0 | 0 |
Validation — deux interfaces vertes en DISABLED ; 22996 rules successfully loaded (4 règles ja3
refusées : empreinte TLS non activée, sans effet) ; mémoire libre > 600 Mo, swap 0. Décision d’Axel (03/11) : on
s’arrête là (option A) : ≈ 370 à 400 Mo par interface, les 3 autres zones ne tiennent pas. Option B pour plus
tard : une seule instance sur le trunk vtnet1 pour les 5 zones. Un peu de RAM en plus sur pfSense est possible ;
au-delà de 2 Gio de plus, on passe à B.
9 bis · Les alertes de Suricata dans Wazuh
Contexte : Suricata tourne sur pfSense, qui n’a pas d’agent Wazuh. Objectif : ses alertes dans Wazuh, et les plus graves par mail, sans rien installer sur le pare-feu.
Suricata (pfSense) ── « Send Alerts to System Log », format court, local1
│ pfSense envoie tout son journal à srv-supervision (UDP 514, déjà en place)
▼
srv-supervision ──► base des journaux (programme = suricata, 6 mois)
│ rsyslog renvoie SEULEMENT les lignes « suricata »
▼
srv-wazuh 10.0.30.16:514/udp (réception syslog, depuis 10.0.30.15 seul)
│ décodeur local « suricata-fast » + règles 100200 (niveau 6) / 100201 (niveau 10)
▼
syslog_output niveau ≥ 10 ──► base des journaux ──► règle Grafana « Intrusion détectée (Wazuh) » ──► mail
Pourquoi pas le JSON (EVE) : le journal de pfSense coupe ses messages à 480 octets (c’est écrit sous l’option), une alerte JSON en fait plus de 1 000. On envoie le format court, et on apprend à Wazuh à le lire.
1. Suricata écrit ses alertes dans le journal de pfSense : Services → Suricata → Interfaces → crayon de chaque
interface → Logging Settings → Send Alerts to System Log, Facility LOCAL1, Priority NOTICE → Save ;
puis ⟳ redémarrer chaque interface et attendre Engine started (≈ 50 s). Sans redémarrage, rien ne change (H-78).
2. srv-supervision renvoie les seules lignes « suricata » à Wazuh : dans /etc/rsyslog.d/31-reception-pfsense.conf
(copie d’abord), juste après la ligne if ($fromhost-ip != "10.0.30.1") then stop :
if ($programname == "suricata") then {
action(type="omfwd" name="suricata_vers_wazuh" target="10.0.30.16" port="514" protocol="udp")
}
sudo rsyslogd -N1 && sudo systemctl restart rsyslog
End of config validation run. Bye. Les lignes continuent aussi d’aller dans la base (programme = suricata).
3. Wazuh écoute en syslog, depuis srv-supervision seul : bloc ajouté à ossec.conf (copie d’abord) :
<ossec_config>
<remote>
<connection>syslog</connection>
<port>514</port>
<protocol>udp</protocol>
<allowed-ips>10.0.30.15</allowed-ips>
<local_ip>10.0.30.16</local_ip>
</remote>
</ossec_config>
local_ip évite le conflit avec le rsyslog local, qui tient 127.0.0.1:514 (§11 bis).
4. Le décodeur et les règles : contenu de scripts/securite/suricata-local_decoder.xml ajouté à
/var/ossec/etc/decoders/local_decoder.xml, et de suricata-local_rules.xml à /var/ossec/etc/rules/local_rules.xml
(copies d’abord, propriétaire wazuh:wazuh). Tester avant de redémarrer :
echo 'Nov 3 18:49:16 SIO2527-pfSense-axel.sio.internal suricata[18722]: [1:2100498:7] GPL ATTACK_RESPONSE id check returned root [Classification: Potentially Bad Traffic] [Priority: 2] {TCP} 10.0.50.200:37422 -> 3.137.48.32:80' | sudo /var/ossec/bin/wazuh-logtest
Phase 2 : name: 'suricata-fast', priority: '2', srcip: '10.0.50.200' ; Phase 3 : id: '100201', level: '10'.
Puis sudo systemctl restart wazuh-manager et sudo ss -ulnp | grep ':514' → 10.0.30.16:514 tenu par wazuh-remoted.
| Priorité Suricata | Règle Wazuh | Niveau | Effet |
|---|---|---|---|
| 3 (basse) | 100200 | 6 | tableau Wazuh |
| 1 ou 2 (haute, moyenne) | 100201 | 10 | tableau Wazuh et mail (§11 bis) |
Validation — depuis poste-visiteur : curl -s http://httpbin.org/anything --data "uid=0(root) gid=0(root)".
dans alerts.json, une alerte 100201 niveau 10 en une seconde ; puis un mail [FIRING] Intrusion détectée (Wazuh)
avec la machine fw-01 (Suricata) (03/11 : alerte à 18:51:45, mail à 18:54:16 ; capture 171).
10 · Tester la détection
Principe : chaque test est une attaque simulée, réversible, lancée depuis une machine du lab, et prouvée par l’alerte lue à la source. Lancer les actions par l’agent QEMU (
qm guest exec) ou en session Termix, après avoir relu l’invite (utilisateur@machine) : un test lancé sur la mauvaise machine ne prouve rien (H-57).
10.1 Wazuh. Sur srv-wazuh, suivre les alertes en direct (fichier JSON, une alerte par ligne) :
sudo tail -f /var/ossec/logs/alerts/alerts.json | grep -oE '"timestamp":"[^"]+"|"name":"[^"]+"|"level":[0-9]+|"description":"[^"]+"'
| Test | Action | Attendu |
|---|---|---|
| A · fichier système modifié | sur srv-ha : echo "# test detection Wazuh $(date +%F_%T)" | sudo tee -a /etc/hosts.allow ; forcer la vérification : sudo /var/ossec/bin/agent_control -r -u 001 (sur le serveur) ; retirer la ligne ensuite | règle 550 « Integrity checksum changed », niveau 7, fichier /etc/hosts.allow |
| B · compte créé | sur poste-win11 (administrateur) : net user testwazuh <mot de passe de test> /add, puis net user testwazuh /delete | 60109 « User account enabled or created », 60111 « User account disabled or deleted », niveau 8 |
| C · force brute SSH | depuis le bastion : 10 fois ssh -o BatchMode=yes -o ConnectTimeout=3 [email protected] true (aucun mot de passe envoyé) | 5710 × 10 (niveau 5), puis 5712 « sshd: brute force trying to get access », niveau 10 |
le 03/11 : 3 attaques, 3 détections en 2 à 3 s (capture 153 ; heures du fichier en UTC = Paris − 1 h).
net user … /addpose une question si le mot de passe dépasse 14 caractères et attend une réponse : un mot de passe de test de 14 caractères au plus, ou l’option/y(H-74). Le compte est supprimé aussitôt : ce test crée deux alertes, et ne laisse rien.
10.2 Suricata. La règle GPL ATTACK_RESPONSE id check returned root (sid 2100498) se déclenche sur tout paquet
contenant uid=0(root). Le site de test habituel testmynids.org a expiré (H-75) : on envoie la phrase à un
service d’écho, qui la renvoie.
Depuis poste-visiteur :
curl -s http://httpbin.org/anything --data "uid=0(root) gid=0(root) groups=0(root)"
Depuis poste-win11 (PowerShell) :
(Invoke-WebRequest http://httpbin.org/anything -Method Post -Body 'uid=0(root) gid=0(root) groups=0(root)').StatusCode
Lire sur pfSense : Services → Suricata → Alerts, interface choisie ; ou en shell, tail /var/log/suricata/suricata_<interface>*/alerts.log.
Validation — en 2 s : [1:2019284:3] ET ATTACK_RESPONSE Output of id command from HTTP server et
[1:2100498:7] GPL ATTACK_RESPONSE id check returned root, avec l’adresse source de la zone testée (captures 162 et
164). Depuis le poste visiteur, une troisième alerte : la commande, notée dans le journal du poste, est partie vers
srv-supervision:514 et Suricata l’a reconnue dans ce flux aussi.
11 · Exploiter : lire les alertes, mesurer, suivre
11.1 Où lire.
| Besoin | Où |
|---|---|
| état des agents | sudo /var/ossec/bin/agent_control -l ; tableau Agents |
| les alertes brutes | /var/ossec/logs/alerts/alerts.json (JSON) et alerts.log (texte) sur srv-wazuh |
| enquêter | tableau de bord : Threat Hunting, filtre par agent et par niveau ; File Integrity Monitoring ; Configuration Assessment |
| les alertes de Suricata | pfSense Services → Suricata → Alerts ; dans Wazuh, règles 100200 et 100201 (§9 bis) ; dans la base des journaux, programme = suricata |
| les alertes graves, par mail | §11 bis : niveau ≥ 10 et créations de comptes |
| les alertes graves, à l’écran | tableau « Lab BTS — Production » : bandeau « Alertes en cours » en haut ; section Journaux et sécurité : « Intrusions Wazuh (24 h) » et « Dernières intrusions détectées par Wazuh » |
| le journal du manager | /var/ossec/logs/ossec.log |
11.2 Le bruit, et comment le faire taire. Les Windows produisent en continu des alertes de niveau 3 sans intérêt :
comptes machine (NOM$) qui ouvrent et ferment des sessions, comptes virtuels sshd_<numéro> qu’OpenSSH crée à chaque
connexion sur le port 22, compte Système au démarrage d’un service. Le 04/11 : 14 067 alertes en une journée, 96 % de
niveau 3. On ne supprime rien à la source (le journal Windows reste complet) : on ajoute des règles locales de
niveau 0, qui disent à Wazuh « tu as vu, mais ce n’est pas une alerte ».
- Compter avant de filtrer (qui fait le bruit ?) : sur
srv-wazuh, compter par règle et par compte dans/var/ossec/logs/alerts/alerts.json(champsrule.id,data.win.eventdata.targetUserName,logonType). - Copier le fichier des règles locales :
sudo cp -p /var/ossec/etc/rules/local_rules.xml /var/ossec/etc/rules/local_rules.xml.avant-bruit
- Ajouter à la fin le contenu de
scripts/securite/bruit-windows-local_rules.xml(règles 100210 à 100213 : chaque règle part d’une règle Windows existante par<if_sid>et n’agit que si le compte correspond). - Valider la configuration avant de redémarrer :
sudo /var/ossec/bin/wazuh-analysisd -t
aucune ligne ERROR ; puis :
sudo systemctl restart wazuh-manager
- Mesurer : même comptage sur les 15 minutes d’avant et d’après. Le 04/11 : 173 → 43 alertes ; plus aucune
alerte
sshd_ni compte machine ; restent les comptes humains (Administrateur,admin).
Ne jamais filtrer les échecs (60122) ni les comptes humains : c’est précisément ce qu’on veut voir. Un filtre trop large rend Wazuh aveugle sans aucun message d’erreur.
Le compte Système s’écrit
Systèmeen français : le « è » fait deux octets dans le journal, une expressionSyst.mene le trouve pas, il fautSyst.{1,2}me(H-80).
11.3 La semaine de mesure (03 → 10/11). À relever chaque jour, ou en fin de semaine dans le tableau de production :
free -h && df -h /var/ossec && systemctl is-active wazuh-indexer
| Mesure | 03/11 | 10/11 |
|---|---|---|
| mémoire utilisée (sur 5,8 Gio) | 2,3 Gio | À COMPLÉTER |
| swap | 265 Mio après l’installation, 631 Mio en fin de journée | À COMPLÉTER |
/var/ossec | À COMPLÉTER | À COMPLÉTER |
Décision du 10/11 : étendre à tout le lab (16.7) si le swap n’explose pas et que l’indexeur reste actif ; sinon repli (CrowdSec + Suricata, ou Wazuh sans indexeur).
11.4 Ce qui reste à faire (tâche 16.7, décidée le 11/11 après la semaine de mesure) : agents sur toutes les autres machines (nœuds Galera avec la règle Internet temporaire). pfSense n’a pas d’agent : ses alertes Suricata arrivent par syslog (§9 bis).
11 bis · Prévenir par mail
Contexte : Wazuh détecte, mais rien ne prévient l’administrateur. Objectif : un mail pour toute alerte de niveau ≥ 10 et pour toute création de compte, par le circuit de mails déjà en place (MO-17 §11).
Le principe : Wazuh envoie ses alertes graves en syslog au rsyslog de sa propre machine ; celui-ci les transmet à
srv-supervision avec le reste du journal ; une règle Grafana sur la base des journaux envoie le mail.
wazuh-analysisd ── alerte niveau ≥ 10, ou règle 60109 / 5902 (création de compte)
│ wazuh-csyslogd (syslog_output)
▼
rsyslog de srv-wazuh, 127.0.0.1:514 (UDP, local seulement)
│ envoi déjà en place de tout le journal (ajouter-machine.sh), TCP 514
▼
srv-supervision ──► base des journaux (Galera, conservée 6 mois)
│
▼
règle Grafana « Intrusion détectée (Wazuh) », critique ──► circuit de mails existant
Pourquoi pas Grafana directement sur l’indexeur ? Il n’écoute que sur
127.0.0.1:9200(installation tout-en-un) ; l’ouvrir demanderait de refaire ses certificats. Le syslog réutilise un chemin qui existe et garde les alertes 6 mois.
1. rsyslog local, sur 127.0.0.1 seulement (session srv-wazuh) :
printf 'module(load="imudp")\ninput(type="imudp" address="127.0.0.1" port="514")\n' | sudo tee /etc/rsyslog.d/10-wazuh-local.conf && sudo rsyslogd -N1 && sudo systemctl restart rsyslog && sudo ss -ulnp | grep ':514'
End of config validation run. Bye., puis 127.0.0.1:514 tenu par rsyslogd.
2. Les alertes de niveau ≥ 10 vers ce rsyslog (copie de la configuration d’abord) :
sudo cp /var/ossec/etc/ossec.conf /var/ossec/etc/ossec.conf.avant-syslog && printf '\n<ossec_config>\n <syslog_output>\n <level>10</level>\n <server>127.0.0.1</server>\n <port>514</port>\n </syslog_output>\n</ossec_config>\n' | sudo tee -a /var/ossec/etc/ossec.conf
3. Plus les créations de comptes (60109 Windows, 5902 Linux, niveau 8) : un second bloc, même méthode
(copie ossec.conf.avant-comptes), avec <rule_id>60109,5902</rule_id> à la place de <level>. Les deux blocs sont
dans scripts/securite/ossec-syslog-output.xml. Puis :
sudo /var/ossec/bin/wazuh-csyslogd -t && sudo systemctl restart wazuh-manager && sleep 15 && sudo /var/ossec/bin/wazuh-control status | grep -E 'csyslogd|analysisd'
wazuh-csyslogd is running... et wazuh-analysisd is running... (le message « This option is deprecated » de
wazuh-control enable client-syslog est sans gravité : le module est actif par défaut).
4. La règle Grafana « Intrusion détectée (Wazuh) », source mysql (compte en lecture seule), dossier Lab BTS,
groupe critiques, attente 1 min, absence de données = Normal :
SELECT CASE WHEN message LIKE '%Location: (%'
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(message, 'Location: (', -1), ')', 1) ELSE 'srv-wazuh' END AS agent,
TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(message, 'Rule: ', -1), ';', 1)) AS regle, COUNT(*) AS value
FROM journaux WHERE hote = 'srv-wazuh' AND programme = 'ossec'
AND recu_le > UTC_TIMESTAMP() - INTERVAL 15 MINUTE GROUP BY 1, 2
Condition : value > 0. Résumé : {{ $labels.agent }} : {{ $labels.regle }}.
15 minutes, pas 5 (H-77) : la fenêtre doit être plus longue que l’envoi groupé du chemin
critique(5 min), sinon une seconde intrusion « se résout » avant que son mail ne parte.
Validation — une force brute SSH (10 connexions d’un compte inexistant) → mail [FIRING] « Intrusion détectée (Wazuh) … srv-ha 5712 » en moins de 2 minutes (03/11 : 1 min 29 s) ; un compte créé sous Windows et sous Linux → les deux dans un mail [FIRING] (03/11 : [FIRING:3] à 18:33:15). Preuves : captures 167 et 168.
12 · Pièges et checklist
| Piège | Symptôme | Où c’est documenté |
|---|---|---|
| Installeur Ubuntu : « masque » = réseau ; LVM à moitié | has host bits set ; / à 31 Go sur 64 | H-68 |
| Option QEMU Guest Agent non cochée dans Proxmox | A dependency job for qemu-guest-agent.service failed, adresse absente dans Proxmox | H-69 |
| Source d’une règle hors du VLAN de l’onglet | refus immédiat sur 1514/1515 depuis la zone | H-70 |
grep -A3 pour vérifier un bloc XML | on croit l’option absente | H-71 |
| Script qui n’attend pas l’enrôlement | « échec » alors que l’agent est inscrit | H-72 |
Fichier .sha512 lu comme un binaire sous PowerShell | [System.Byte] ne contient pas de méthode nommée « Trim » | H-73 |
net user /add avec un mot de passe long | la commande attend une réponse, rien ne se passe | H-74 |
Site de test testmynids.org disparu | aucune alerte, page « domaine à vendre » | H-75 |
Test lancé avant Engine started. | aucune alerte Suricata | H-76 |
| Fenêtre de la règle de mail plus courte que l’envoi groupé | mail [RESOLVED] sans [FIRING] | H-77 |
| Option Suricata modifiée sans redémarrer l’interface | rien dans le journal de pfSense | H-78 |
| Format court de Suricata non reconnu par Wazuh | No decoder matched, règle 1002 niveau 2 | H-79 |
Filtre de bruit écrit avec un . pour un caractère accentué | les alertes du compte Système continuent | H-80 |
| Ballon activé sur la VM Wazuh | Java plante quand Proxmox reprend la mémoire | H-67 |
| Agent plus récent que le serveur | enrôlement refusé | §8 : version figée |
| Port 1515 ouvert à toute la zone VISITEURS | un invité peut inscrire un faux agent | §7 : poste géré seul |
VM 6144/6144 Mio sans ballon, 64 Go, Ubuntu 24.04, racine agrandie, agent QEMU (option + arrêt/démarrage)
MO-18 fait en entier AVANT Wazuh : Termix par clé, mot de passe SSH interdit, up=1, journaux, alertes, sauvegarde, adressage
wazuh-install.sh lu (en-tête, taille) avant sudo bash … -a ; 3 services active
Mot de passe admin dans Bitwarden ; wazuh-install-files.tar dans /root en 600 ; dépôt apt désactivé
jvm.options : -Xms = -Xmx (1 Gio) ; free -h relevé
authd.pass 640 root:wazuh ; <use_password>yes</use_password> ; « Using password specified on file »
Alias SRV_WAZUH et PORTS_WAZUH ; une règle par zone avant les rejets ; VISITEURS = 10.0.50.200 seul ; nc -zv depuis chaque zone
Scripts dans la version du serveur ; agent_control -l : Active pour chaque machine
Suricata : config pfSense sauvegardée avant ; ETOpen, 12 h ; EVE JSON FILE ; Block Offenders décoché ; 7 catégories ; mémoire relevée avant/après
3 tests Wazuh (550, 60109/60111, 5712) et 1 test Suricata par zone (2100498) : alertes lues, captures datées
Semaine de mesure notée (mémoire, swap, /var/ossec) ; décision du 10/11 écrite dans le suivi
Alertes Suricata → Wazuh (§9 bis) : redémarrage de Suricata, wazuh-logtest avant redémarrage de Wazuh, test de bout en bout jusqu'au mail
Reste (16.7, décidée le 11/11) : agents sur toutes les autres machines
La règle à retenir en une phrase : Wazuh regarde dans les machines, Suricata regarde entre les zones ; un mot de passe d’inscription, une règle par zone vers le seul serveur, la même version partout, et chaque détection prouvée par une attaque simulée avant de faire confiance à l’écran.
