CrowdSec et fail2ban avec OPNsense : IDS/IPS collaboratif et protection SSH

Protéger OPNsense avec CrowdSec (IDS/IPS collaboratif) et fail2ban sur les serveurs backend. Plugin os-crowdsec, bouncer firewall, jails SSH/Nginx, intégration complète.

CrowdSec et fail2ban avec OPNsense : IDS/IPS collaboratif et protection SSH

Sur mon infra BOTUM, le firewall OPNsense bloque les attaques au périmètre. Mais le périmètre seul ne suffit pas. Les serveurs derrière le firewall — SSH ouvert, Nginx en reverse proxy, applications web — sont des cibles permanentes pour les bots, les scanners et les attaquants qui cherchent à forcer des accès. C'est pourquoi j'ai mis en place une couche IDS/IPS active avec CrowdSec au niveau d'OPNsense, complétée par fail2ban sur les serveurs en aval — les deux intégrés pour partager l'intelligence sur les menaces.

Ce billet est le cinquième et dernier de la série Stack OPNsense Enterprise. Voir : Billet 1 : Installer OPNsense dans Proxmox, Billet 2 : VLANs & Zero Trust, Billet 3 : WireGuard VPN & SD-WAN LTE, Billet 4 : WiFi & APs avec UniFi/Omada.

Pourquoi combiner CrowdSec et fail2ban ?

Les deux outils sont complémentaires, pas concurrents :

  • CrowdSec : IDS/IPS collaboratif. Il analyse les logs en temps réel, détecte les comportements malveillants, et partage les IPs bloquées avec une communauté mondiale. Le bouncer OPNsense bloque ces IPs au niveau du firewall, avant même que les paquets atteignent vos serveurs. Puissant, mais nécessite un plugin OPNsense et une architecture réseau correcte.
  • fail2ban : protection locale par analyse de logs. Il ban les IPs qui échouent trop souvent (SSH, Nginx, Postfix...) via iptables ou nftables. Simple, battle-tested, efficace pour les services exposés directement.

Ma stratégie : CrowdSec bloque à l'entrée (firewall OPNsense), fail2ban protège localement sur chaque serveur, et les deux se parlent via l'API CrowdSec pour enrichir la base de données de menaces.

Architecture CrowdSec collaborative IDS/IPS avec OPNsense — intelligence partagée sur les menaces

Prérequis

  • OPNsense opérationnel — voir Billet 1
  • OPNsense exposé sur internet (WAN avec IP publique ou DDNS)
  • Serveurs Linux derrière OPNsense (Ubuntu/Debian) avec SSH activé
  • Accès SSH admin sur les serveurs backend
  • Un compte gratuit sur app.crowdsec.net

Installer le plugin CrowdSec sur OPNsense

OPNsense propose le plugin officiel os-crowdsec via son gestionnaire de plugins. Ce plugin installe l'agent CrowdSec et le bouncer firewall directement sur le routeur.

# OPNsense GUI :
# System -> Firmware -> Plugins
# Rechercher : crowdsec
# Trouver : os-crowdsec
# Cliquer le "+" pour installer

# Après installation, recharger la page.
# Nouveau menu : Services -> CrowdSec

Une fois installé, l'interface CrowdSec apparaît dans le menu Services. Vérifier que le service est actif :

# Services -> CrowdSec -> Overview
# CrowdSec daemon : Running
# Bouncer : Active

# Vérification en SSH OPNsense :
# (System -> Shell ou via SSH admin)
cscli version
# CrowdSec version : v1.x.x
cscli machines list
# Liste les machines enrollées
Installation du plugin os-crowdsec dans OPNsense — gestionnaire de plugins

Configurer le bouncer OPNsense (firewall bouncer)

Le bouncer est le composant qui traduit les décisions CrowdSec en règles firewall concrètes. Sur OPNsense, il s'intègre directement avec le moteur pf/nftables.

# Services -> CrowdSec -> Bouncers
# Le bouncer "crowdsec-firewall-bouncer" doit être listé
# Status : Running

# Configuration du bouncer (fichier sur OPNsense) :
# /usr/local/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml

# Paramètres clés :
api_url: http://127.0.0.1:8080/
api_key: <généré automatiquement>
mode: pf   # mode pare-feu OPNsense
blacklists_ipv4: crowdsec_blacklists
blacklists_ipv6: crowdsec6_blacklists

# Les tables pf sont automatiquement créées et alimentées
# par le bouncer avec les IPs malveillantes CrowdSec

Pour vérifier que le bouncer fonctionne et bloque correctement :

# Via SSH OPNsense (System -> Shell) :
cscli bouncers list
# Nom              IP        Type    Décisions  Actif
# opnsense-bouncer  127.0.0.1 firewall  actif      true

# Vérifier les décisions actives :
cscli decisions list
# IP              Raison              Durée    Source
# 185.220.x.x    crowdsecurity/ssh-bf  4h     CrowdSec CTI
# 45.155.x.x     crowdsecurity/http-probing 24h community

Enroll dans la console CrowdSec

La console app.crowdsec.net permet de visualiser les alertes, gérer les décisions et accéder aux listes communautaires de menaces (CTI).

# 1. Créer un compte sur app.crowdsec.net (gratuit)
# 2. Dans la console : Security Engines -> Add
# 3. Copier la commande d'enrollment

# Sur OPNsense (SSH / System -> Shell) :
cscli console enroll <votre-enroll-key>
# Output : Machine enrolled successfully

# 4. Dans la console CrowdSec : approuver le moteur
# Security Engines -> Pending -> Accept

# 5. Vérifier l'enrollment :
cscli console status
# Enrollment : OK
# Last heartbeat : <timestamp récent>

Une fois enrollé, vous avez accès aux blocklists communautaires premium et à l'historique des alertes sur votre firewall OPNsense.

Installer fail2ban sur les serveurs backend

fail2ban s'installe sur chaque serveur Linux derrière OPNsense — là où les services sont réellement exposés (SSH, Nginx, applications web).

# Ubuntu/Debian :
sudo apt update && sudo apt install fail2ban -y

# Vérifier le service :
sudo systemctl status fail2ban
# Active: active (running)

# fail2ban inclut des jails par défaut.
# Ne PAS modifier jail.conf directement — créer jail.local :
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Configuration fail2ban jail SSH et Nginx — terminal Linux sysadmin

Créer des jails custom fail2ban

Les jails définissent quels services surveiller et les règles de bannissement. J'utilise deux jails principaux sur mes serveurs BOTUM : SSH et Nginx.

Jail SSH

# /etc/fail2ban/jail.local

[DEFAULT]
bantime  = 3600          # 1 heure de ban
findtime = 600           # fenêtre de 10 minutes
maxretry = 5             # 5 tentatives max avant ban
backend  = systemd

[sshd]
enabled  = true
port     = ssh           # port SSH générique (ou numéro spécifique)
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 3             # SSH plus strict : 3 tentatives
bantime  = 86400         # 24h de ban pour SSH

Jail Nginx

# /etc/fail2ban/jail.local (suite)

[nginx-http-auth]
enabled  = true
port     = http,https
filter   = nginx-http-auth
logpath  = /var/log/nginx/error.log
maxretry = 5

[nginx-botsearch]
enabled  = true
port     = http,https
filter   = nginx-botsearch
logpath  = /var/log/nginx/access.log
maxretry = 2
bantime  = 86400
# Recharger fail2ban après modification :
sudo systemctl reload fail2ban
# ou
sudo fail2ban-client reload

# Vérifier le statut des jails :
sudo fail2ban-client status
# Jail list: sshd, nginx-http-auth, nginx-botsearch

sudo fail2ban-client status sshd
# Status for the jail: sshd
# Currently banned:  3
# Total banned:      47
# Banned IP list: 192.168.x.x 45.155.x.x ...

Intégration fail2ban → CrowdSec

C'est là que la magie opère : quand fail2ban détecte une IP malveillante, il peut signaler cette décision à CrowdSec, qui la propage au bouncer OPNsense et à la communauté mondiale.

# Installer le plugin CrowdSec pour fail2ban :
# Sur le serveur backend (pas OPNsense) :
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt install crowdsec -y

# Enroller ce serveur dans la console CrowdSec :
sudo cscli console enroll <votre-enroll-key>

# Configurer l'action fail2ban pour notifier CrowdSec :
# /etc/fail2ban/action.d/crowdsec.conf
[Definition]
actionban   = cscli decisions add --ip <ip> --duration 4h --reason "fail2ban-<name>"
actionunban = cscli decisions delete --ip <ip>

# Activer l'action dans jail.local :
# [DEFAULT]
# action = %(action_)s
#          crowdsec
Intégration fail2ban vers CrowdSec — flux de signalement IP malveillantes vers OPNsense bouncer

Avec cette intégration, le flux de protection devient :

  1. Bot tente un brute-force SSH sur le serveur backend
  2. fail2ban détecte après 3 tentatives et ban l'IP localement
  3. fail2ban envoie la décision à CrowdSec via cscli
  4. CrowdSec propage la décision au bouncer OPNsense
  5. OPNsense bloque l'IP au niveau firewall pour tous les services
  6. L'IP est contribuée à la communauté CrowdSec mondiale

Monitoring : logs, dashboard, alertes

Deux niveaux de monitoring sont disponibles : local via CLI et centralisé via la console CrowdSec.

Monitoring local (CLI)

# Sur OPNsense (SSH) :
# Voir les alertes en temps réel :
cscli alerts list
# Voir les décisions actives :
cscli decisions list
# Voir les métriques de l'agent :
cscli metrics

# Sur le serveur backend :
# Logs fail2ban en temps réel :
sudo tail -f /var/log/fail2ban.log
# Bannissements récents :
sudo fail2ban-client status sshd
# Dé-bannir une IP manuellement (si faux positif) :
sudo fail2ban-client set sshd unbanip 192.168.10.50

Console CrowdSec (dashboard web)

# app.crowdsec.net -> Dashboard
# - Carte mondiale des attaques bloquées
# - Timeline des alertes par type (SSH, HTTP, scan...)
# - Liste des machines (OPNsense + serveurs backend)
# - CTI : réputation des IPs avec contexte
# - Blocklists premium (abonnement optionnel)

# Recevoir des alertes Telegram/Slack/Email :
# Console -> Settings -> Notifications
# Configurer webhook ou email
Console CrowdSec app.crowdsec.net — dashboard sécurité avec carte des menaces et alertes

Tests de validation

# 1. Vérifier CrowdSec actif sur OPNsense :
cscli version && cscli machines list

# 2. Simuler une attaque SSH depuis une IP externe :
# (sur un serveur test hors réseau BOTUM)
for i in {1..5}; do ssh invalid_user@<IP-serveur> 2>/dev/null; done
# -> fail2ban doit bannir l'IP de test

# 3. Vérifier le bannissement :
sudo fail2ban-client status sshd
# L'IP de test doit apparaître dans "Banned IP list"

# 4. Vérifier la propagation vers OPNsense :
# SSH OPNsense -> cscli decisions list
# L'IP de test doit apparaître si l'intégration est active

# 5. Test de faux positif (cleanup) :
sudo fail2ban-client set sshd unbanip <votre-IP-test>
cscli decisions delete --ip <votre-IP-test>

Résultat : stack de sécurité complet

En combinant CrowdSec et fail2ban sur l'infra BOTUM, j'obtiens :

  • Blocage proactif au périmètre : CrowdSec bloque les IPs connues malveillantes avant qu'elles atteignent mes serveurs
  • Protection locale adaptative : fail2ban banne les attaquants détectés localement
  • Intelligence partagée : les détections fail2ban alimentent CrowdSec et profitent à toute la communauté
  • Visibilité centralisée : la console CrowdSec agrège toutes les alertes de l'infra
  • Zéro coût : l'ensemble de ce stack est open-source et gratuit (tier communautaire CrowdSec)
📥 Guide PDF complet

Téléchargez ce guide en PDF pour le consulter hors ligne.

⬇ Télécharger le guide (PDF)

Prochaines étapes — Retour vers le Hub

Ce billet conclut la série Stack OPNsense Enterprise. Le stack complet :

→ Retour vers le Hub du Stack OPNsense Enterprise.

🚀 Aller plus loin avec BOTUM

Ce guide couvre les bases. En production, chaque environnement a ses spécificités. Les équipes BOTUM accompagnent les organisations dans le déploiement, la configuration avancée et la sécurisation de leur infrastructure. Si vous avez un projet, parlons-en.

Discuter de votre projet →
Série OPNsense 📋 Voir la série complète →