Le monitoring Linux a longtemps reposé sur les mêmes outils : des agents en userspace qui lisent /proc, parsent des logs et exposent des métriques via des endpoints HTTP. Cette approche fonctionne, mais elle a des limites structurelles. L'agent ne voit que ce que le noyau veut bien exposer via ses interfaces standards. Il ne peut pas observer les appels système en temps réel, tracer les paquets réseau à l'intérieur du kernel, ni détecter un comportement suspect avant qu'il ne laisse une trace dans un fichier de log.
eBPF change la donne. Cette technologie permet d'exécuter du code directement dans le noyau Linux, sans modifier le kernel ni charger de modules custom. En 2026, eBPF est passé du statut d'outil de niche pour développeurs kernel à celui de fondation pour toute une génération d'outils de sécurité et d'observabilité. Falco l'utilise pour la détection d'intrusion runtime. Cilium l'utilise pour le networking Kubernetes. bpftrace l'utilise pour le profiling système. Et ces outils ne font que commencer.
Cet article explique le fonctionnement d'eBPF, détaille les trois outils majeurs de l'écosystème, et montre comment les mettre en production pour transformer l'observabilité de vos serveurs Linux.
eBPF en 30 secondes : l'essentiel
eBPF (extended Berkeley Packet Filter) est une machine virtuelle intégrée au noyau Linux. Elle permet d'attacher des programmes à des points d'ancrage (hooks) dans le kernel : appels système, fonctions réseau, tracepoints, kprobes. Ces programmes s'exécutent dans un sandbox vérifié par le kernel avant chargement, ce qui garantit qu'ils ne peuvent pas crasher le système ni accéder à de la mémoire arbitraire.
Architecture fondamentale
Un programme eBPF suit un cycle précis. Le développeur écrit le programme (en C restreint ou avec des frameworks comme libbpf). Le compilateur le transforme en bytecode eBPF. Le vérificateur du kernel analyse le bytecode pour garantir sa sûreté : pas de boucles infinies, pas d'accès mémoire hors limites, pas d'instructions dangereuses. Si la vérification passe, le programme est attaché au hook demandé et s'exécute à chaque événement correspondant.
Programme eBPF (C restreint)
|
v
Compilation (clang/LLVM)
|
v
Bytecode eBPF (.o)
|
v
Vérificateur kernel ----> Rejet si non sûr
|
v
Chargement + Attach au hook
|
v
Exécution dans le kernel
|
v
Maps eBPF (partage données kernel <-> userspace)
Les maps : le pont kernel/userspace
Les maps eBPF sont des structures de données partagées entre le programme kernel et l'espace utilisateur. Hash maps, arrays, ring buffers, LRU caches : le choix de la structure dépend du cas d'usage. Un programme eBPF attaché aux appels système peut incrémenter un compteur dans une map à chaque open(), et un démon en userspace lit cette map périodiquement pour exposer la métrique. Zéro copie de données, zéro context switch : les performances sont proches du natif.
Les hooks disponibles
La puissance d'eBPF vient de la diversité de ses points d'ancrage.
- kprobes / kretprobes : s'attachent à n'importe quelle fonction du kernel. Utiles pour tracer les appels internes.
- tracepoints : points d'instrumentation stables définis par le kernel. Plus fiables que les kprobes entre versions.
- XDP (eXpress Data Path) : exécution au niveau du driver réseau, avant même la pile TCP/IP. Idéal pour le filtrage à haute performance.
- TC (Traffic Control) : hook réseau au niveau du scheduler de paquets. Utilisé par Cilium pour le routing.
- LSM (Linux Security Modules) : hooks de sécurité pour le contrôle d'accès mandatory. Utilisé par Tetragon.
- uprobes : s'attachent aux fonctions en userspace. Permettent de tracer des applications sans les modifier.
Falco : la détection d'intrusion runtime
Falco est un moteur de détection de menaces runtime créé par Sysdig et désormais projet gradué de la CNCF. Son principe est simple : observer les appels système en temps réel via eBPF et les comparer à un jeu de règles pour détecter les comportements suspects. Un conteneur qui lance un shell interactif, un processus qui lit /etc/shadow, une connexion sortante inattendue : Falco voit tout et alerte immédiatement.
Contrairement à auditd qui écrit dans des fichiers de log que vous analysez après coup, Falco opère en temps réel avec une latence de quelques microsecondes. Et contrairement aux IDS réseau comme Suricata, Falco observe les comportements système, pas seulement le trafic réseau.
Installation et configuration
Falco se déploie soit directement sur l'hôte, soit comme DaemonSet Kubernetes. La version eBPF est recommandée par rapport au module kernel (plus portable, plus sûre).
# Installation sur Debian/Ubuntu via le dépôt officiel
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
https://download.falco.org/packages/deb stable main" | \
sudo tee /etc/apt/sources.list.d/falcosecurity.list
sudo apt update && sudo apt install -y falco
# Vérifier que le driver eBPF est chargé
sudo falco --version
# Falco version: 0.40.x (driver: ebpf)
# /etc/falco/falco.yaml - Configuration essentielle
engine:
kind: ebpf
ebpf:
buf_size_preset: 4 # Taille du ring buffer (4 = 8 MB)
rules_files:
- /etc/falco/falco_rules.yaml # Règles par défaut
- /etc/falco/falco_rules.local.yaml # Règles custom (prioritaires)
outputs:
rate: 0 # Pas de rate limiting
max_burst: 1000 # Burst maximum
stdout_output:
enabled: true
http_output:
enabled: true
url: "http://localhost:2801/" # Falcosidekick pour forwarding
Règles custom pour la détection
Les règles Falco utilisent un DSL déclaratif qui filtre les événements syscall. Chaque règle définit une condition (quand alerter), une sortie formatée (quoi logger) et une priorité.
# /etc/falco/falco_rules.local.yaml
# Détecter l'exécution d'un shell dans un conteneur
- rule: Shell interactif dans un conteneur
desc: Un shell interactif a été lancé dans un conteneur
condition: >
spawned_process and container and
proc.name in (bash, sh, zsh, dash) and
proc.tty != 0
output: >
Shell interactif détecté (container=%container.name
image=%container.image.repository command=%proc.cmdline
user=%user.name pid=%proc.pid)
priority: WARNING
tags: [container, shell, mitre_execution]
# Détecter la lecture de fichiers sensibles
- rule: Lecture de fichiers credentials
desc: Un processus lit des fichiers contenant des credentials
condition: >
open_read and fd.name in (/etc/shadow, /etc/gshadow,
/root/.ssh/authorized_keys, /root/.bash_history) and
not proc.name in (sshd, passwd, su, sudo, login)
output: >
Lecture de fichier sensible (file=%fd.name command=%proc.cmdline
user=%user.name container=%container.name)
priority: CRITICAL
tags: [filesystem, credentials, mitre_credential_access]
# Détecter les connexions sortantes suspectes
- rule: Connexion sortante depuis un conteneur web
desc: Un conteneur web initie une connexion sortante inattendue
condition: >
outbound and container and
container.image.repository contains "nginx" and
not fd.sport in (80, 443, 8080)
output: >
Connexion sortante suspecte (container=%container.name
image=%container.image.repository connection=%fd.name
command=%proc.cmdline)
priority: ERROR
tags: [network, container, mitre_command_and_control]
Intégration Kubernetes
En environnement Kubernetes, Falco se déploie comme DaemonSet pour couvrir chaque noeud. L'intégration avec Falcosidekick permet de router les alertes vers Slack, PagerDuty, Elasticsearch ou n'importe quel webhook.
# Déploiement via Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/..." \
--set falcosidekick.config.elasticsearch.hostPort="http://elastic:9200"
uname -r. Sur les noyaux plus anciens, le module kernel est nécessaire mais moins recommandé pour la production.Cilium : networking et sécurité eBPF-native
Si Falco observe les syscalls, Cilium contrôle le réseau. Cilium est un CNI (Container Network Interface) Kubernetes qui remplace iptables par des programmes eBPF pour tout le networking : routage, load balancing, network policies, observabilité. Les performances sont significativement meilleures qu'avec les solutions basées sur iptables car eBPF évite les traversals de chaînes de règles linéaires.
Network policies L3/L4/L7
Les NetworkPolicies Kubernetes standard opèrent aux couches 3 et 4 (IP et port). Cilium va plus loin avec des CiliumNetworkPolicies qui filtrent au niveau L7 : méthode HTTP, path, headers, contenu gRPC. Cela permet de définir des politiques comme "le service orders peut faire des GET sur /api/products mais pas des DELETE".
# CiliumNetworkPolicy - Filtrage L7 HTTP
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-access-control
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v2/products.*"
- method: "POST"
path: "/api/v2/orders"
- fromEndpoints:
- matchLabels:
app: monitoring
toPorts:
- ports:
- port: "9090"
protocol: TCP
rules:
http:
- method: "GET"
path: "/metrics"
Cette granularité est essentielle pour implémenter une architecture Zero Trust au sein d'un cluster Kubernetes. Chaque service n'accède qu'aux endpoints spécifiques dont il a besoin.
Hubble : l'observabilité réseau
Hubble est le composant d'observabilité de Cilium. Il capture les flux réseau en temps réel avec une visibilité L3/L4/L7, sans overhead significatif grâce à eBPF. L'interface CLI et l'UI web permettent de visualiser les dépendances inter-services, de débugger les problèmes de connectivité et de détecter les flux non autorisés.
# Installer le CLI Hubble
export HUBBLE_VERSION=$(curl -s \
https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --remote-name-all \
https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
tar xzf hubble-linux-amd64.tar.gz
sudo mv hubble /usr/local/bin/
# Observer les flux en temps réel
hubble observe --namespace production --protocol http
# Filtrer les flux refusés (dropped)
hubble observe --verdict DROPPED --namespace production
# Exporter les flux vers Prometheus
# Hubble expose des métriques sur :9965/metrics par défaut
Service mesh sans sidecar
Cilium propose un service mesh eBPF-native qui élimine le besoin de sidecars (contrairement à Istio/Envoy). Le mTLS, le load balancing L7 et le retry sont gérés directement dans le kernel par des programmes eBPF. L'avantage est double : réduction de la consommation mémoire (pas de proxy par pod) et latence réduite (pas de hop supplémentaire). Pour les clusters Docker et Kubernetes en production, c'est un gain opérationnel considérable.
Outils complémentaires : bpftrace, Tetragon, Pixie
Au-delà de Falco et Cilium, l'écosystème eBPF comprend plusieurs outils spécialisés qui couvrent des besoins spécifiques.
bpftrace : le couteau suisse du tracing
bpftrace est un langage de tracing de haut niveau pour eBPF, inspiré de DTrace et SystemTap. Il permet d'écrire des one-liners pour observer n'importe quel aspect du système en temps réel. C'est l'outil idéal pour le debugging ad-hoc et l'investigation de performances.
# Compter les appels système par processus
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter {
@syscalls[comm] = count();
}'
# Histogramme de latence des lectures disque
sudo bpftrace -e 'tracepoint:block:block_rq_issue {
@start[args->dev, args->sector] = nsecs;
}
tracepoint:block:block_rq_complete /@start[args->dev, args->sector]/ {
@usecs = hist((nsecs - @start[args->dev, args->sector]) / 1000);
delete(@start[args->dev, args->sector]);
}'
# Tracer les connexions TCP avec PID et destination
sudo bpftrace -e 'tracepoint:sock:inet_sock_set_state
/args->newstate == 1/ {
printf("%-8d %-16s %s:%d\n", pid, comm,
ntop(args->daddr), args->dport);
}'
# Top 10 des fichiers les plus ouverts
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat {
@files[str(args->filename)] = count();
}
END { print(@files, 10); }'
Tetragon : enforcement et runtime security
Tetragon, également développé par Isovalent (les créateurs de Cilium), va plus loin que Falco. Là où Falco détecte et alerte, Tetragon peut bloquer les actions malveillantes en temps réel grâce aux hooks LSM eBPF. Il peut empêcher un processus d'exécuter un binaire, bloquer un accès fichier ou tuer un processus qui viole une politique, le tout directement dans le kernel sans passer par le userspace.
# TracingPolicy Tetragon - Bloquer l'exécution de miners
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: block-crypto-miners
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
args:
- index: 0
type: "linux_binprm"
selectors:
- matchBinaries:
- operator: "In"
values:
- "/usr/bin/xmrig"
- "/tmp/minerd"
matchActions:
- action: Sigkill
Pixie : observabilité auto-instrumentée
Pixie (projet CNCF) utilise eBPF pour capturer automatiquement les requêtes HTTP, les queries SQL, les appels gRPC et les métriques système sans aucune instrumentation du code applicatif. Pas de SDK, pas de sidecar, pas de modification des déploiements. Pixie s'installe sur le cluster et commence immédiatement à collecter les données d'observabilité. C'est particulièrement utile pour les applications legacy ou les environnements où l'ajout d'instrumentation OpenTelemetry n'est pas possible.
Monitoring kernel avec eBPF : métriques custom
Au-delà des outils packagés, eBPF permet de créer des métriques kernel sur mesure, impossibles à obtenir avec les exporteurs classiques. Voici les cas d'usage les plus pertinents en production.
Latence I/O et scheduling
Les outils classiques comme iostat donnent des moyennes. eBPF donne des distributions. La différence est cruciale : une latence moyenne de 5 ms peut masquer un P99 à 200 ms. Les BCC tools (BPF Compiler Collection) fournissent des scripts prêts à l'emploi pour mesurer ces distributions.
# Distribution de latence I/O par disque (BCC tools)
sudo biolatency -D 10 1
# Affiche un histogramme de latence par device sur 10 secondes
# Latence de scheduling (temps entre wakeup et exécution)
sudo runqlat 10 1
# Montre combien de temps les processus attendent dans la run queue
# Retransmissions TCP (symptôme de congestion ou perte)
sudo tcpretrans
# Affiche chaque retransmission avec source, destination, état
# Latence des requêtes DNS
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_sendmsg
/comm == "systemd-resolve"/ {
@start[tid] = nsecs;
}
tracepoint:syscalls:sys_exit_recvmsg
/comm == "systemd-resolve" && @start[tid]/ {
@dns_latency_us = hist((nsecs - @start[tid]) / 1000);
delete(@start[tid]);
}'
Exemples bpftrace one-liners pour la production
Ces commandes sont directement utilisables en investigation. Chacune répond à une question précise qu'un stack Prometheus/Grafana classique ne couvre pas nativement.
# Qui consomme la bande passante réseau ? (par processus)
sudo bpftrace -e 'tracepoint:net:net_dev_xmit {
@bytes[comm] = sum(args->len);
}'
# Quels fichiers sont écrits le plus souvent ? (détection I/O storm)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_write {
@writes[comm, pid] = count();
}'
# Temps passé dans les page faults (signe de memory pressure)
sudo bpftrace -e 'software:page-faults:1 {
@faults[comm] = count();
}'
# Délai entre l'arrivée d'un paquet et sa consommation par l'app
sudo bpftrace -e 'tracepoint:net:netif_receive_skb {
@qlen[comm] = hist(args->len);
}'
apt install bpfcc-tools) incluent plus de 80 scripts prêts à l'emploi : biosnoop, execsnoop, opensnoop, tcplife. Commencez par ceux-là avant d'écrire vos propres programmes bpftrace.eBPF vs agents traditionnels : comparatif
La question n'est pas de remplacer Prometheus ou auditd, mais de comprendre ce qu'eBPF apporte en complément et où il surpasse les approches classiques.
| Critère | Agents classiques (node_exporter, auditd) | eBPF (Falco, Cilium, bpftrace) |
|---|---|---|
| Point d'observation | Userspace (lecture /proc, /sys, logs) | Kernel (hooks directs dans le noyau) |
| Latence de détection | Secondes à minutes (polling) | Microsecondes (événementiel) |
| Overhead CPU | 1-3% (scraping périodique) | 0.1-1% (exécution à la demande) |
| Visibilité réseau | Métriques agrégées (bytes in/out) | Par paquet, par flux, L3-L7 |
| Détection runtime | Analyse de logs post-mortem | Temps réel sur les syscalls |
| Filtrage réseau | iptables (linéaire, lent à scale) | eBPF/XDP (O(1), hardware offload) |
| Instrumentation app | SDK requis (OpenTelemetry, etc.) | Automatique via uprobes (Pixie) |
| Courbe d'apprentissage | Faible (configuration déclarative) | Moyenne à élevée (concepts kernel) |
| Maturité écosystème | Très mature, documentation abondante | Mature pour Falco/Cilium, en évolution pour le reste |
En pratique, la meilleure approche est hybride. Gardez Prometheus et node_exporter pour les métriques système standard et l'historique long terme. Ajoutez Falco pour la détection runtime. Utilisez Cilium pour le networking si vous êtes sur Kubernetes. Et sortez bpftrace quand vous avez besoin de répondre à une question précise sur le comportement du kernel.
Mise en production : bonnes pratiques et pièges
Déployer des outils eBPF en production nécessite de la rigueur. Voici les leçons apprises sur des déploiements réels.
1. Vérifier la compatibilité kernel
Tous les kernels ne supportent pas toutes les fonctionnalités eBPF. Le minimum viable pour Falco et Cilium est le kernel 5.8. Pour Tetragon et les hooks LSM, visez le 5.15+. Le kernel 6.x apporte CO-RE (Compile Once, Run Everywhere), qui élimine la dépendance aux headers kernel.
# Vérifier la version du kernel
uname -r
# Vérifier les features eBPF disponibles
sudo bpftool feature probe kernel
# Vérifier que BTF (BPF Type Format) est activé (requis pour CO-RE)
ls /sys/kernel/btf/vmlinux && echo "BTF OK" || echo "BTF manquant"
2. Déployer en mode audit d'abord
Comme pour les règles de sécurité serveur, ne bloquez jamais rien au premier déploiement. Falco en mode alerte uniquement. Cilium en mode log-only pour les network policies. Tetragon en mode observe sans Sigkill. Collectez les données pendant au moins deux semaines pour comprendre les flux normaux avant d'activer l'enforcement.
3. Gérer les faux positifs
Les règles Falco par défaut génèrent du bruit. Un cron qui exécute un script bash dans un conteneur déclenche l'alerte "shell in container". La solution est de maintenir des listes d'exceptions contextuelles et de tuner les règles progressivement. Ne désactivez jamais une règle entière : ajoutez des exceptions précises.
# Exception pour un cron légitime
- rule: Shell interactif dans un conteneur
append: true
condition: and not (container.image.repository = "registry.internal/cron-jobs")
4. Monitorer les programmes eBPF eux-mêmes
Les programmes eBPF consomment des ressources : mémoire pour les maps, CPU pour l'exécution. Surveillez le nombre de programmes chargés, la taille des maps et les événements perdus (dropped events dans le ring buffer).
# Lister les programmes eBPF chargés
sudo bpftool prog list
# Voir les maps et leur consommation mémoire
sudo bpftool map list
# Statistiques d'exécution des programmes
sudo bpftool prog show id <ID> --json | jq '.run_cnt, .run_time_ns'
5. Prévoir la capacité du ring buffer
Si le système génère plus d'événements que le ring buffer ne peut en contenir, des événements sont perdus. Sur un serveur à fort trafic, augmentez la taille du buffer et mettez en place une métrique de suivi des événements perdus. Pour Falco, le paramètre buf_size_preset contrôle cette taille.
6. Sécuriser les outils eBPF
Les programmes eBPF s'exécutent avec des privilèges élevés. Restreignez l'accès aux commandes bpftool et bpftrace aux seuls administrateurs. En environnement Kubernetes, les pods Falco et Cilium tournent en mode privilégié : isolez-les dans des namespaces dédiés avec des RBAC stricts.
Conclusion
eBPF a fondamentalement changé ce qu'il est possible d'observer et de contrôler sur un système Linux. Les outils construits sur cette technologie (Falco, Cilium, Tetragon, bpftrace) offrent une visibilité et une réactivité que les agents userspace traditionnels ne peuvent pas atteindre. La détection en temps réel des comportements suspects, le filtrage réseau au niveau du kernel et le tracing applicatif sans instrumentation sont désormais accessibles à tout administrateur système prêt à investir dans l'apprentissage.
La courbe d'apprentissage est réelle. eBPF demande de comprendre les concepts kernel, les hooks, les maps et le fonctionnement du vérificateur. Mais les outils de haut niveau comme Falco et Cilium abstraient la majeure partie de cette complexité. Vous n'avez pas besoin d'écrire des programmes eBPF pour en bénéficier.
Commencez par Falco pour la sécurité runtime. Ajoutez bpftrace pour le debugging de performance. Migrez vers Cilium quand votre infrastructure Kubernetes le justifie. Et surtout, déployez en mode audit avant d'activer le moindre blocage. L'observabilité Linux n'a jamais été aussi puissante : il serait dommage de ne pas en profiter.
Commentaires