Skip to main content

Command Palette

Search for a command to run...

Mise en place d’un pipeline de détection d’intrusions avec Zeek, Suricata et ELK sur Google Cloud

Updated
15 min read
Mise en place d’un pipeline de détection d’intrusions avec Zeek, Suricata et ELK sur Google Cloud

Cet article présente la mise en place d’un environnement de détection, combinant Zeek, Suricata avec la stack ELK (Elasticsearch, Logstash, Kibana). Il permet de mettre en avant la gestion des logs avec ELK, l’analyse réseau avec Zeek et Suricata, puis la visualisation avec Kibana et Elasticsearch. L’implémentation a été faite sur Google Cloud Platform, avec deux VM Ubuntu configurées pour séparer la capture du trafic et la gestion des données.

L’objectif principal est de construire un pipeline de logs, afin de :

  • collecter les événements réseau depuis plusieurs capteurs

  • les normaliser et les transférer vers Logstash via Filebeat

  • puis les visualiser dans Kibana pour faciliter la détection

Composants

  • Zeek: système de détection d’intrusion IDS et d’analyse de trafic réseau. Il permet de générer des logs et fichiers détaillés sur les connexions et les activités observées.

  • Suricata: IDS/IPS qui utilise des règles de détection pour inspecter le trafic et déclencher des alertes

  • ELK: ensemble de trois outils

    • Elasticsearch: pour le stockage de logs, la recherche et l’analyse de ces logs.

    • Logstash: collecte des logs de Zeek et Suricata via Filebeat, transformation de ces logs en format JSON ou CSV puis envoi à Elasticsearch pour stockage.

    • Kibana: pour la visualisation des données et création de dashboard

  • Filebeat: pour la collecte des logs des deux IDS et l’envoi à Logstash

Voici un diagramme montrant l’architecture du projet et les différentes étapes.

Étape 1: Préparation de l’environnement dans GCP

La première étape consiste à configurer l’environnement de lab afin de simuler le réseau, capturer le trafic. On opte pour trois machines sur Google Cloud Platform (GCP):

  • une machine vm1-ubuntu de 23G de disque, pour Zeek et Suricata

  • une machine vm2-ubuntu de 23G de disque, pour ELK qui sera installé via Docker.

Les machines sont installées avec les configurations de bases. Pour le réseau, on choisit une configuration standard de GCP qui utilise VPC en mode Bridge afin d’avoir une réelle intégration réseau. Chaque VM dispose d’une IP interne pour la communication interne au VPC et aussi une IP externe lorsqu’on veut y accéder depuis l’externe. L’IP interne est utilisée pour la communication entre les machines et l’IP externe pour l’accès à Kibana par exemple, après avoir ajouter des règles de pare-feu pour autoriser les ports.

Installation de Zeek sur la vm1

Installer les dépendances pour Zeek:

sudo apt update 
sudo apt install build-essential cmake make gcc g++ flex bison libpcap-dev libssl-dev python3-dev zlib1g-dev swig

Télécharger Zeek depuis le site officiel avec la commande suivante:

wget https://download.zeek.org/zeek-8.0.1.tar.gz

Extraire le fichier

 tar -xvzf zeek-8.0.1.tar.gz

Se déplacer dans le répertoire du fichier extrait puis configurer zeek avec la commande suivante:

cd zeek-8.0.1/
./configure

Il est possible que la commande montre des configurations incomplètes ou ne localisent pas toutes les librairies. Voici l’erreur que j’ai eue personnellement à cette commande.

On a d’abord la librairie ZeroMQ manquante, puis le cache à nettoyer. Pour résoudre cela, il faut installer la librairie avec la commande suivante:

sudo apt-get install libzmq3-dev

Puis vider le cache avec la commande

 make distclean

Sans ces deux réglages il ne serait pas possible de continuer. Une fois le problème résolu, il faut reconfigurer zeek avec la commande :

./configure

Compiler ensuite avec les commandes suivantes:

make
sudo make install

À noter que chacune de ces deux commandes peut prendre un bout de temps à s’exécuter.

Une fois que Zeek est configuré, il faut l’ajouter au PATH du système, afin de pouvoir lancer les commandes zeek depuis n’importe quel répertoire. Il faut donc ajouter le répertoire de zeek au fichier .bashrc ou .zshrc.

nano ~/.bashrc

Ajouter la ligne suivante en incluant le répertoire de zeek, à la fin du fichier. Ici, Zeek a été installé dans le répertoire /usr/local/zeek, les exécutables sont donc dans le répertoire /usr/local/zeek/bin.

export PATH="/usr/local/zeek/bin:$PATH"

Sauvegarder et quitter le fichier pour appliquer les changements avec la commande

source ~/.bashrc

Vous pouvez ensuite vérifier la version et l’emplacement de zeek et les logs avec la commande suivante:

zeek --version
which zeek

Lancer Zeek avec la commande suivante:

zeekctl deploy

Zeek est bien installé, mais l’utilisateur n’a pas les droits d’écrire dans le fichier /usr/local/zeek/spool/. Remplacer USER par le nom d’utilisateur

sudo chown -R [USER]:[USER] /usr/local/zeek/spool
sudo chown -R [USER]:[USER] /usr/local/zeek

En exécutant maintenat zeekctl deploy, on peut lancer zeek.

Zeek démarre mais on voit qu’il s’arrête automatiquement après.

On essaie de vérifier les logs générés dans le fichier /usr/local/zeek/logs.

ls  /usr/local/zeek/logs

On peut donc voir les premiers logs de sorties et d’erreurs de Zeek. Le fichier stderr.log capture les messages d’erreur générés puis le fichier stdout.log capture les messages de sortie de Zeek.

En essayant de lire le fichier de log stderr.log, il y a une petite erreur au niveau de l’interface eth0.

On voit que Zeek n’a pas les permissions pour analyser le trafic sur l’interface eth0. Il faut donc donner les droits de capture avec la commande suivante:

sudo setcap cap_net_raw,cap_net_admin=eip /usr/local/zeek/bin/zeek

En vérifiant aussi avec ip a, on voit que zeek essaie de démarrer sur l’interface eth0, alors que l’interface active sur la machine est l’interface ens4. Il faut donc modifier la configuration de zeek afin qu’elle démarre sur la bonne interface

Pour cela, exécutez les commandes suivantes

sudo nano /usr/local/zeek/etc/node.cfg

Remplacez ensuite eth0 par ens4, ou l’interface de la machine.

Cela permet donc à Zeek de démarrer sur l’interface ens4 qui est celle active. On a donc réglé les deux problèmes au niveau de la permission pour l’analyse du trafic, puis de l’interface. Il faut donc relancer avec la commande zeekctl deploy.

Cette fois, Zeek démarre bien sans erreur.

On peut donc vérifier les fichiers de logs dans /usr/local/zeek/logs avec la commande:

ls /usr/local/zeek/logs

Zeek génère bien les fichiers de logs maintenant en format gzip. On a ici deux répertoires: /usr/local/zeek/logs/current et usr/local/zeek/logs/2025-09-04.

Le répertoire /current représente le répertoire actif en cours d’exécution. Il contient les logs du Zeek qui tourne au moment où il tourne. Au redémarrage de Zeek une autre fois, les fichiers sont déplacés de /current vers un dossier daté comme /2025-09-04, un peu comme un archivage selon la date. Le répertoire /current contient plusieurs fichiers courants:

  • conn.log enregistre les connexions réseaux

  • http.log enregistre les requêtes HTTP incluant les enquêtes et les codes

  • stats.log enregistre les statistiques de capture.

  • dns.log enregistre les requêtes et réponses DNS

  • weird.log enregistre les comportements réseaux suspects

Le répertoire /2025-09-04/ est l’archive d’une journée de logs. Il contient des fichiers compressés en .log.gz déplacés du répertoire /current. On peut les lire sans les extraire, avec la commande zcat.

Vous pouvez voir la liste complète des fichiers sur le site officiel.

Installation de Suricata sur la vm1

Mettre à jour le système

sudo apt update
sudo apt upgrade -y

Installer la dernière version de Suricata avec les commandes suivantes:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:oisf/suricata-stable
sudo apt-get update
sudo apt-get install suricata

Vérifier ensuite avec la commande suivante

suricata -V
suricata --build-info

Au niveau de Suricata, les logs sont générés dans le répertoire /var/log/suricata/.

On y retrouve les fichiers suivants:

  • fast.log contient un résumé des alertes générées

  • eve.json contient les infos détaillées sur les alertes

  • stats.log affiche les statistiques et l’état de Suricata

  • suricata.log contient le journal de Suricata, c’est-à-dire les infos sur le démarrage, l’arrêt, les erreurs etc.

Il faut ensuite configurer Suricata par la suite. Le fichier principal de configuration se trouve dans le répertoire /etc/suricata/suricata.yaml.On doit y déterminer l’interface réseau et l’adresse IP sur laquelle Suricata doit inspecter. Pour cela, vérifiez les informations de votre réseau avec la commande ip a.

Ouvrez ensuite le fichier de configuration, et cherchez la section af-packet.

sudo nano /etc/suricata/suricata.yaml

On va ensuite modifier l’interface eth0 par celle de notre machine.

Télécharger les signatures et les règles Suricata avec la commande suivante:

sudo suricata-update

Démarrer le service Suricata par la suite

sudo systemctl enable suricata
sudo systemctl start suricata

Vous pouvez ensuite vérifier le contenu de ces fichiers.

Installation Docker sur la vm2

Au niveau de la vm2 ubuntu, il faut installer Docker et déployer ELK (Elaticsearch, Logstach puis Kibana).

Pour installer Docker, mettre à jour la VM en premier puis installer les paquets nécessaires:

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Ajouter ensuite le dépôt officel Docker.

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Installer la dernière version de Docker

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Vous pouvez ensuite vérifier l’installation

 sudo docker version
sudo systemctl status docker

Pour simplifier le déploiement de ELK, on installe aussi Docker Compose. Il est utile dans ce cas car ELK comporte trois services principaux. Sans Docker Compose, il faudrait télécharger, configurer puis gérer manuellement les ports, réseaux pour chaque service. Docker Compose permet d’écrire puis gérer le tout dans un seul fichier docker-compose.yml, Mais Docker Compose est déjà présent sur certaines versions de Ubuntu, donc plus besoin d’installer le paquet. Vous pouvez vérifier avec la commande suivante:

docker compose version

Sinon installez Docker Compose

sudo apt install docker compose -y

Déployer ELK via Docker Compose sur la vm2

Créer un répertoire pour ELK

mkdir ELK
cd ELK

Créer le fichier docker-compose.yml

nano docker-compose.yml

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    container_name: elasticsearch
    environment:
      - node.name=elasticsearch
      - discovery.type=single-node
      - xpack.security.enabled=false
      - xpack.security.audit.enabled=true
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - elk

  kibana:
    image: docker.elastic.co/kibana/kibana:8.17.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    networks:
      - elk
    depends_on:
      - elasticsearch

  logstash:
    image: docker.elastic.co/logstash/logstash:8.17.0
    container_name: logstash
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline
    ports:
      - "5044:5044"
    networks:
      - elk
    depends_on:
      - elasticsearch

volumes:
  elasticsearch-data:

networks:
  elk:
    driver: bridge

Voici une petite explication des paramètres utilisés dans le fichier

  • image: définit la version de l’image Docker à utiliser pour créer le conteneur.

  • discovery.type=single-node: configure Elasticsearch en mode single-node, signifiant qu’il fonctionnera comme un nœud unique sans essayer de se connecter à d'autres nœuds.

  • xpack.security.enabled=false: désactive les fonctionnalités de sécurité, telles que l’authentification et l’autorisation, utile ici vu qu’il s’agit d’un test.

  • xpack.security.audit.enabled=true: active l’audit de sécurité afin de suivre les évènements dans Elasticsearch.

  • ES_JAVA_OPTS=-Xms1g -Xmx1g: configure les options de la machine, spécifiant la mémoire initiale et maximale allouée à la machine

  • volumes: elasticsearch-data: volume utilisé pour stocker les données de manière persistante

  • ports: permet d’exposer le service sur un port précis

  • networks: créé un réseau interne dédié aux conteneurs, pour faciliter la communication avec d’autres services comme Logstash et Kibana dans le meme réseau elk.

Pour la suite, lancer ELK

sudo docker compose up -d

Les deux commandes doivent être exécutées après chaque redémarrage de votre poste, afin de redémarrer ELK.

Vous pouvez ensuite vérifier que les services roulent bien et que les ports sont bien ouverts avec la commande suivante:

sudo docker ps

Redémarrer ensuite la machine puis relancez ELK avec la commande suivante

cd ELK/
sudo docker compose start

Pour vérifier Elasticsearch:

curl -X GET http://localhost:9200

On a bien Elasticsearch sur le port 9200, en version 8.17.0.

On peut aussi vérifier depuis la vm1, avec la commande suivante

curl -X GET http://IP_VM2:9200

Kibana étant une interface graphique, on peut aussi y accéder depuis le navigateur. Si vous êtes sur une machine en local, ou dans le même réseau que la VM, vous pouvez y accéder directement via l’adresse suivante:

http://IP_VM2:5601

Dans notre cas ici, la VM est hébergée sur Google Cloud Platform (GCP). Avant d’y accéder depuis l’extérieur, il faut que le pare-feu du réseau VPC autorise le traffic entrant sur le port 5601 de Kibana. On va donc créer une règle de pare feu dans GCP. Vous pouvez y accéder via le lien suivant: https://console.cloud.google.com/net-security/firewall-manager/firewall-policies/list?hl=fr

Lors de la création de la règle, il est important de spécifier les paramètres suivants:

  • le nom: allow-kibana

  • la source: une adresse IP qui sera autorisée. Par exemple 0.0.0.0/0 pour tout le monde, ou l’adresse IP publique de votre machine.

  • la cible: la VM sur laquelle ELK est installée ou toutes les instances du réseau

  • le port et le protocole: tcp:5601

Une fois la règle est créée, Kibana devient accessible à l’adresse suivante:

http://IP_EXTERNE_VM2:5601

Étape 2: Collecte et traitement des logs

Configuration de Logstash pour collecter les donneés - création du pipeline conf sur la vm2

Par la suite, il faut créér le fichier de pipeline de configuration logstash.conf dans le répertoire logstash/pipeline/. C’est un fichier de principal de Logstash qui définit comment les données sont traitées puis transformées. Les paramètes inclus dans le fichier sont disponibles sur le site officiel.

Pour cela, exécuter les commandes suivantes:

cd ELK/
mkdir -p logstash/pipeline
sudo nano logstash/pipeline/logstash.conf

Voici le contenu du fichier logstash.conf.

input {
  beats {
    port => 5044
  }
}

# La section filter est optionnel. On l'utilise si on souhaite transformer, structurer les logs
# Ici, on sépare Zeek et Suricata dans deux index différents
filter {
  if [type] == "zeek" {
    mutate { add_field => { "[@metadata][target_index]" => "zeek-%{+YYYY.MM.dd}" } }
  }
  else if [type] == "suricata" {
    mutate { add_field => { "[@metadata][target_index]" => "suricata-%{+YYYY.MM.dd}" } }
  }
}


output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "%{[@metadata][target_index]}"
  }
  stdout { 
    codec => rubydebug 
  }
}

Redémarrer ensuite le conteneur Logstash avec la commande suivante.

sudo docker restart logstash

Il se peut que le conteneur soit créé avec un nom différent que logstash. Vous pouvez vérifier les conteneurs existants avec la commande suivante:

sudo docker ps -a

Installation de Filebeat sur la vm1

Avec Docker Compose, Zeek et Suricata installés et fonctionnels, on veut pouvoir collecter les logs puis les acheminer vers ELK sur la vm2. Pour cela on installe Filebeat ,qui lit les logs de la vm1 (depuis Zeek et Suricata) et les envoie à Elasticsearch (Logstash) sur la vm2.

Télécharger et installer la clé de signature publique

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

Installer les paquets apt-transport-https

sudo apt-get install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/9.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-9.x.list

Installer Filebeat avec la commande suivante:

sudo apt-get update && sudo apt-get install filebeat

Configurer ensuite Filebat pour démarrer automatiquement au démarrage

sudo systemctl enable filebeat
 sudo systemctl status filebeat

Après l’installation, éditer le fichier de configuration Filebeat /etc/filebeat/filebeat.yml, afin qu’Il collecte les logs et les envoie à la sortie souhaitée (ici ELK ou Logstach).

sudo nano /etc/filebeat/filebeat.yml

Ajouter le bloc de code suivant dans la section Filebeat input

# Input added for Zeek & Suricata on 2025-09-05
- type: filestream
  id: zeek-filestream-id
  enabled: true
  paths:
    - /usr/local/zeek/logs/*/*.log
    - /usr/local/zeek/logs/current/*.log
  tags: ["zeek"]
  fields:
    type: zeek
  fields_under_root: true

- type: filestream
  id: suricata-filestream-id
  enabled: true
  paths:
    - /var/log/suricata/*.log
    - /var/log/suricata/eve.json
  tags: ["suricata"]
  fields:
    type: suricata
  fields_under_root: true

Il faut ensuite configurer la sortie soit vers Elasticsearch directement, soit vers Logstash sur la vm2, toujours dans le même fichier etc/filebeat/filebeat.yml, dans la section Elasticsearch Output ou dans la section Logstash Output. Le choix dépend de ce qu’on veut faire des logs.

  • Envoyer à Elasticsearch est simple et demande moins de configurations. Les logs arrivent directement dans Elasticsearch et peuvent être visualisés dans Kibana. Par contre, il n’y a pas moyen de filtrer ou transformer les logs.

  • Envoyer à Logstash est un peu plus lourd à configurer. Il faut créér le fichier de pipeline et les fichiers de paramètre (ils sont inclus dans l’installation). Mais on peut filtrer, transformer les logs avant de les envoyer à Elasticsearch. C’est plus pratique lorsqu’on veut prétraiter les logs, extraire des champs spécifiques

On opte ici pour l’envoi vers Logstash. Il suffira juste de commenter toute la section Elasticsearch Output.

Dans la section Logstash Output, modifier les paramètres comme hosts, protocol,si vous activez https, puis username et password si l’authentification est activée.

output.logstach:
  hosts: ["IP_VM2:5044"]

Redémarrer ensuite Filebeat

sudo systemctl restart filebeat
sudo systemctl status filebeat
sudo filebeat test output

La commande filebeat test output permet de confirmer si Filebeat, depuis la vm1, arrive bien à joindre Logstash installée sur la vm2.

Une fois que Filebeat depuis la vm1 arrive à bien se connecter à Logstash sur la vm2, on est sûr que ca fonctionne.

Vérification dans logs dans Elasticsearch

On vérifie ici que Logstash sur la vm2, recoit bien les logs de Filebeat depuis la vm1. Pour cela, exécuter la commande suivante sur la vm2, où est installée Logstash:

sudo docker logs -f logstash

On a bien le type de données (type suricata) qu’on avait défini dans Filebeat pour différencier Zeek et Suricata. Filebeat transmet aussi le chemin exact du fichier source, soit /var/log/suricata/eve.json. On a aussi des infos sur l’hôte duquel provient les logs.

On peut ensuite vérifier les index créés dans Elasticsearch car une fois que Logstash reçoit bien les logs, il doit les envoyer à ELK (Elasticsearch)

curl -X GET "http://localhost:9200/_cat/indices?v"

On a bien l’index défini au niveau du fichier de configuration logstash.conf, avec le tag suivi de la date. L’index contient pour le moment 6470 documents pour zeek et 4905 pour Suricata.

On peut ensuite vérifier au niveau de l’Interface dans Kibana à l’adresse suivante:

http://IP_VM2:5601

Dans la section Management, naviguer vers Stack Management. Allez ensuite dans Data Views puis Create Data View. Dans le champ Name, inscrire le nom correspondant aux logs, soit suricata-* pour Suricata, ou zeek-* pour Zeek. Cliquer ensuite sur Create Data View.

Une fois le Data View créé, aller dans la section Discover, sélectionnezr le Data View suricata-* afin de voir les logs. On a bien le champ hostname qui est celui de la vm1 et le champ agent-type qui est filebeat.

Vous pouvez ensuite créer plusieurs Data Views :

  • zeek-* pour les logs Zeek

  • suricata-* pour les alertes Suricata

  • filesbeat-* pour les logs génériques Filebeat

Documentation

More from this blog

Bilal's blog

41 posts

As a newcomer to the cybersecurity industry, I'm on an exciting journey of continuous learning and exploration. Join me as I navigate, sharing insights and lessons learned along the way