Suricata : Integration dans VyOS via conteneur Podman

📘 Introduction

Ce document dĂ©crit la mise en place d’un conteneur Suricata sur un routeur VyOS afin d’analyser le trafic rĂ©seau en mode IDS/IPS.
L’objectif est d’obtenir une inspection des paquets transitant à travers le routeur, tout en gardant une configuration persistante dans /config.

Setup entiĂšrement automatisĂ© maintenant via Ansible, playbook public ici si ça t’intĂ©resse de reproduire : github.com/jbsky/vyos-deploy.


đŸ§© Architecture gĂ©nĂ©rale

  • VyOS joue le rĂŽle de routeur principal.
  • Suricata est dĂ©ployĂ© dans un conteneur Podman gĂ©rĂ© nativement par VyOS, Ă  partir de mon image durcie jbsky/suricata-hardened (FROM scratch, non-root, capabilities rĂ©duites au strict minimum) plutĂŽt que l’image gĂ©nĂ©rique jasonish/suricata utilisĂ©e au dĂ©part.
  • La configuration et les rĂšgles de Suricata sont stockĂ©es dans le rĂ©pertoire persistant /config.
  • Le trafic rĂ©seau est redirigĂ© vers Suricata via nftables (mangle + NFQUEUE) pour inspection.
flowchart LR
    A["Internet"] -->|"eth1 (WAN)"| B["VyOS routeur"]
    B -->|"mark 10 (mangle)"| C["NFQUEUE 0-3"]
    C --> D["Suricata inline (container)"]
    D -->|"NF_ACCEPT / NF_DROP"| B
    B -->|"eth0"| E["Reseau local"]

⚙ Configuration VyOS

Conteneur Suricata (état actuel, config.boot) :

set container name suricata allow-host-networks
set container name suricata arguments '-q 0 -q 1 -q 2 -q 3 --runmode workers'
set container name suricata capability 'net-admin'
set container name suricata capability 'sys-nice'
set container name suricata image 'docker.io/jbsky/suricata-hardened:8.0.5'
set container name suricata memory '2048'
set container name suricata restart 'on-failure'
set container name suricata volume config destination '/etc/suricata'
set container name suricata volume config source '/config/containers/suricata/etc'
set container name suricata volume logs destination '/var/log/suricata'
set container name suricata volume logs source '/var/log/suricata'
set container name suricata volume rules destination '/var/lib/suricata/rules'
set container name suricata volume rules source '/config/containers/suricata/rules'
set container name suricata volume run destination '/var/run/suricata'
set container name suricata volume run source '/config/containers/suricata/run'

Ce qui a changé par rapport à la premiÚre version : image passée sur mon build durci et pinnée par tag (8.0.5 au lieu de latest), mémoire redescendue à 2 Go (le build durci est nettement plus léger, 6 Go ne servaient à rien), ajout de restart on-failure, et un nouveau volume run qui expose le socket unix de contrÎle (suricata-command.socket) pour recharger les rÚgles à chaud avec suricatasc sans redémarrer le container.

allow-host-networks : permet au conteneur d’accĂ©der au rĂ©seau du routeur — obligatoire en mode NFQUEUE, qui a besoin du network namespace de l’hĂŽte.

arguments : dĂ©finit les files NFQUEUE utilisĂ©es (-q 0 -q 1 -q 2 -q 3) et le mode de travail (–runmode workers).

capabilities : seules net-admin et sys-nice sont nĂ©cessaires (dĂ©tail des choix d’architecture NFQUEUE et de l’image durcie dans l’article dĂ©diĂ©).

volumes : montent les répertoires persistants du systÚme VyOS dans le conteneur.

📩 Organisation des fichiers

/config/
├── containers/
│   └── suricata/
│       ├── etc/          ← Configuration Suricata (suricata.yaml, classification.config, etc.)
│       ├── rules/        ← Règles IDS (Emerging Threats, etc.)
│       └── run/          ← Socket unix de controle (suricata-command.socket)
├── scripts/
│   └── suricata-update.sh  ← Script de mise à jour des règles
└── ...

🔁 Redirection du trafic avec nftables

Le script /config/scripts/vyos-preconfig-bootup.script contient les rĂšgles suivantes (version finale, aprĂšs pas mal d’itĂ©rations) :

# Marquer seulement le trafic entrant depuis le WAN
iptables -t mangle -A FORWARD -i eth1 -j MARK --set-mark 10

# Marquer seulement le trafic sortant vers le WAN
iptables -t mangle -A FORWARD -o eth1 -j MARK --set-mark 10

# Rediriger vers Suricata via NFQUEUE
iptables -t mangle -A POSTROUTING -m mark --mark 10 -j NFQUEUE \
  --queue-balance 0:3 \
  --queue-cpu-fanout \
  --queue-bypass

DiffĂ©rence avec la toute premiĂšre version : au dĂ©part je marquais tout le trafic FORWARD, peu importe l’interface. Ça marchait, mais ça inspectait aussi du trafic inter-VLAN qui n’avait rien Ă  voir avec l’extĂ©rieur. Restreint maintenant explicitement Ă  eth1 (le WAN) dans les deux sens, ce qui limite l’inspection au trafic qui traverse vraiment la frontiĂšre internet.

Sous le capot, VyOS traduit tout ça en rĂšgles nftables (table ip mangle), iptables n’est qu’une couche de compatibilitĂ© en surface.

Explications :

Le trafic WAN entrant et sortant est marqué (mark 10).

Les paquets marqués sont envoyés à Suricata via NFQUEUE.

–queue-balance 0:3 : rĂ©partit la charge sur 4 files de traitement.

–queue-bypass : laisse passer le trafic si Suricata n’est pas actif (pas de coupure rĂ©seau, y compris pendant un redĂ©marrage pour mise Ă  jour des rĂšgles).

🧠 Mode d’analyse Suricata

Dans le fichier /config/containers/suricata/etc/suricata.yaml, le paramÚtre suivant est activé :

host-mode: router

Cela indique que Suricata doit analyser le trafic forwardĂ© (celui qui transite Ă  travers le routeur) et non le trafic local (input/output de VyOS lui-mĂȘme).

🔄 Mise à jour automatique des rùgles

Une tùche planifiée VyOS déclenche la mise à jour quotidienne :

set system task-scheduler task update-suricata-rules executable path '/config/scripts/suricata-update.sh'
set system task-scheduler task update-suricata-rules interval '1d'

Le mĂ©canisme exact du script (container Ă©phĂ©mĂšre, contournement des file capabilities, bug de dĂ©tection de version) est dĂ©taillĂ© dans l’article dĂ©diĂ© Ă  la gestion des rĂšgles.

📡 DĂ©ploiement et synchronisation

Toute cette configuration (config, rĂšgles, script de mise Ă  jour) est maintenant versionnĂ©e et dĂ©ployĂ©e via Ansible plutĂŽt qu’à coups de rsync manuel. Le playbook cible un groupe Ansible vyos (pas un hostname en dur) et est rĂ©utilisable tel quel : github.com/jbsky/vyos-deploy.

ansible-playbook suricata-deploy.yaml -i inventories/production --tags config
ansible-playbook suricata-deploy.yaml -i inventories/production --tags script
ansible-playbook suricata-deploy.yaml -i inventories/production --tags check

Ça permet de :

Versionner la config dans Git plutît qu’un dump rsync ponctuel.

Redéployer proprement sur une autre instance VyOS.

VĂ©rifier l’état du container aprĂšs coup (show container) plutĂŽt que de deviner.

⚠ Points Ă  surveiller

Performance et choix d’architecture (NFQUEUE vs AF_PACKET, allow-host-networks) sont dĂ©taillĂ©s dans l’article NFQUEUE dĂ©diĂ© — en pratique toujours pas de diffĂ©rence notable, je plafonne Ă  1 Gb avec iperf3.

Logs : /var/log/suricata peut croßtre rapidement, logrotate configuré en conséquence :

/var/log/suricata/*.log /var/log/suricata/*.json
{
    daily
    maxsize 100M
    rotate 10
    missingok
    nocompress
    copytruncate
}

Mise Ă  jour du container : l’image Ă©tant pinnĂ©e par tag (8.0.5), plus de surprise de type "latest a changĂ© sous mes pieds" — la mise Ă  jour d’image est un choix explicite, pas un effet de bord d’un pull.

đŸ§© RĂ©fĂ©rences utiles

Documentation VyOS – Containers

Suricata Documentation

NFQUEUE & Suricata Inline Setup

🏁 Conclusion

Cette intĂ©gration permet Ă  VyOS de fonctionner comme un routeur IDS/IPS complet grĂące Ă  Suricata, avec une architecture modulaire, persistante et maintenant entiĂšrement automatisĂ©e via Ansible. Les dĂ©buts manuels (image gĂ©nĂ©rique, marquage de trafic trop large, mises Ă  jour de rĂšgles Ă  la main) ont progressivement laissĂ© place Ă  un setup reproductible, avec une image durcie et pinnĂ©e, et un playbook public que n’importe qui peut reprendre.


Liens

Code source : vyos-deploy (Suricata + stack proxy Squid/c-icap/ClamAV)
Image Docker : suricata-hardened

Articles connexes :
Suricata hardened : image Docker durcie pour NFQUEUE (architecture, image durcie)
IPS : stratégie de détection et gestion des rules Suricata (politique de rÚgles, mécanisme de mise à jour)