Cahier des charges
Présentation du projet ExfilGuardian, contexte, problématique et réponse technique
Contexte et problématique
L'exfiltration de données est aujourd'hui l'une des menaces les plus silencieuses et les plus coûteuses pour les organisations. Elle ne consiste pas à faire tomber un système, mais à en siphonner discrètement les informations sensibles : propriété intellectuelle, données personnelles, identifiants, communications internes. Sa particularité est de se dissimuler dans des protocoles parfaitement légitimes : une requête DNS banale peut transporter des mégaoctets de données encodées, un flux HTTP apparemment normal peut exfiltrer une base de données entière, et un simple upload vers un service de partage autorisé peut suffire à faire sortir des documents sensibles du périmètre.
Les outils de sécurité réseau existants répondent bien à d'autres types de menaces (intrusions, malwares, dénis de service), mais l'exfiltration les met en échec pour une raison simple : elle ressemble à du trafic normal. Les approches par signatures seules ne suffisent pas, car les techniques d'exfiltration évoluent en permanence pour contourner les règles connues. Les approches purement comportementales génèrent trop de faux positifs sans la contextualisation apportée par l'analyse protocolaire.
ExfilGuardian part du constat qu'aucune technique de détection prise isolément n'est suffisante. La réponse efficace est une approche en profondeur, où plusieurs couches d'analyse indépendantes se renforcent mutuellement.
Ce qu'est ExfilGuardian
ExfilGuardian est un système de détection d'exfiltration de données en temps réel, conçu selon une architecture distribuée et multi-plateforme. Un driver kernel intercepte le trafic réseau et le contexte (processus, fichiers, DNS) sur chaque machine, un agent local collecte cette télémétrie et la transmet à un serveur central d'analyse via gRPC. Le serveur analyse simultanément les flux selon quatre angles complémentaires (DPI, signatures, comportemental, corrélation) et produit des alertes enrichies consultables via une application desktop native ou une API REST.
La première cible était Windows, qui représente la majorité des postes de travail en entreprise et donc le vecteur d'exfiltration principal. Grâce au découplage driver/serveur (contrat Protobuf partagé), le support a été étendu sans modifier le serveur, l'analyse ni l'interface : Linux est livré et validé (driver eBPF/aya) et macOS est livré en agent passif (capture réseau via libpcap, sans driver kernel).
Ce n'est pas un firewall. Ce n'est pas un DLP. ExfilGuardian ne classe pas le contenu des fichiers, ne lit pas les données personnelles qui transitent, et ne tente pas de déchiffrer le trafic TLS. Il détecte des techniques d'exfiltration, c'est-à-dire la façon dont les données sont dissimulées ou extraites via le trafic réseau. Cela inclut aussi bien les canaux couverts (tunnel DNS, ICMP) que les abus de services légitimes (uploads massifs vers des plateformes de partage, exfiltration HTTP/HTTPS vers des destinations inhabituelles). Le système ne se limite pas aux techniques « exotiques » : il surveille l'ensemble des vecteurs de sortie de données.
En phase initiale, ExfilGuardian fonctionne en mode observation pure : il alerte, l'opérateur décide. Un mode réponse actif est envisagé pour les futures versions.
L'outil se destine aux équipes SOC, aux ingénieurs réseau et aux auditeurs de sécurité qui ont besoin d'une visibilité fine sur ce qui sort de leur réseau, avec la possibilité d'adapter les règles de détection à leur contexte spécifique.
Architecture distribuée
Le système est conçu en trois composants distincts qui communiquent via gRPC/Protobuf sécurisé par mTLS :
Le driver kernel (WFP)
Le driver est un module kernel Windows écrit en Rust (#![no_std]), compilé en .sys via les crates WDK. Il s'enregistre comme callout sur la couche FWPM_LAYER_DATAGRAM_DATA_V4 du Windows Filtering Platform (WFP) pour intercepter les paquets réseau au niveau kernel.
Le driver utilise un modèle d'IRP inversé : l'agent envoie un IRP pending via DeviceIoControl, et le driver le complète lorsqu'un paquet arrive. Ce modèle évite le polling et minimise les transitions kernel/userland.
Mécanismes de protection intégrés :
- Anti-kill :
ObRegisterCallbackssupprime le droitPROCESS_TERMINATEsur le processus agent - Protection registre :
CmRegisterCallbackExbloque les modifications aux clésSOFTWARE\EXFILGUARDIAN - DKOM bypass : positionnement du bit Force Integrity (0x20) sur
LDR_DATA_TABLE_ENTRY.Flagspour contourner les restrictions deObRegisterCallbackssur les drivers non signés en développement
L'agent
L'agent est un service Windows (windows-service) qui tourne en userland. Il communique avec le driver via DeviceIoControl pour recevoir les paquets interceptés. Ses responsabilités :
- Pré-filtrage heuristique : 8 vérifications rapides (volume sortant, intervalles réguliers, processus inhabituels, nouvelles destinations, ports non-standard, fréquence DNS, ICMP large, TLS vers IP brute) qui posent des flags de priorité sur les flux
- File d'attente SQLite WAL : zéro perte de paquets quand le serveur est injoignable. Les paquets s'accumulent localement et sont retransmis à la reconnexion
- Streaming gRPC : transmission continue des paquets au serveur via
tonicavec reconnexion automatique
Le serveur central
Le serveur expose deux interfaces :
- gRPC (port 50051) : réception des flux d'agents via
tonic, sécurisé par mTLS - REST (port 8080) : API de consultation via
axum, dashboard, enrollment des agents
Le pipeline d'analyse traite chaque flux reçu à travers quatre couches de détection indépendantes.
Les fonctionnalités
F1. Filtrage kernel WFP (Ring 0)
Le driver s'inscrit comme callout WFP sur FWPM_LAYER_DATAGRAM_DATA_V4 pour intercepter les paquets réseau directement dans le kernel. Cette interception au niveau le plus bas garantit que même un processus malveillant ne peut contourner la capture en se branchant sur des couches supérieures.
| Aspect | Détail |
|---|---|
| Couche | Ring 0 (kernel) |
| API | Windows Filtering Platform (WFP) |
| Communication | IRP inversé vers l'agent (zero polling) |
| Langage | Rust #![no_std] via crates WDK |
| Artefact | exfil_guardian.sys + .inf + .cat |
F2. Agent de télémétrie local (Ring 3)
L'agent tourne comme service Windows (windows-service) et assure la liaison entre le driver kernel et le serveur cloud. Il reçoit les paquets du driver via DeviceIoControl, les pré-filtre avec 8 heuristiques rapides, et les transmet au serveur en streaming gRPC continu.
| Aspect | Détail |
|---|---|
| Couche | Ring 3 (userland) |
| Exécution | Service Windows auto-start |
| Pré-filtrage | 8 heuristiques (volume, intervalles, processus, DNS, ICMP, TLS...) |
| Reconnexion | Automatique avec backoff exponentiel |
F3. File d'attente zéro perte (SQLite WAL)
Quand le serveur est injoignable (panne réseau, maintenance), l'agent ne perd aucun paquet. Les données sont accumulées localement dans une base SQLite en mode WAL (Write-Ahead Logging), qui garantit :
- Concurrence : lectures et écritures simultanées sans blocage
- Durabilité : les données survivent à un crash de l'agent
- Retransmission : à la reconnexion, les paquets en file sont envoyés par ordre chronologique
F4. Transport gRPC / Protobuf sur HTTP/2
La communication agent vers serveur utilise gRPC avec sérialisation Protobuf sur HTTP/2. Le RPC StreamPackets est un appel client-streaming : l'agent ouvre une connexion persistante et envoie un flux continu de NetworkPacket. Le serveur ne répond qu'à la fermeture du stream.
| Aspect | Détail |
|---|---|
| Framework | Tonic (Rust gRPC) |
| Sérialisation | Protobuf binaire (compact vs JSON) |
| Transport | HTTP/2 multiplexé |
| RPC | StreamPackets(stream NetworkPacket) returns (StreamResponse) |
F5. Authentification dynamique mTLS
Chaque agent présente un certificat client unique, signé par l'autorité de certification (CA) du serveur. Les certificats sont générés dynamiquement lors de l'enrollment :
- Le serveur génère une CA ECDSA P-256 au démarrage (si absente)
- À chaque enrollment, un certificat client unique est créé et signé par la CA
- Le CN du certificat inclut les 6 premiers caractères du token pour identification
- L'agent stocke son certificat et l'utilise pour toutes les connexions gRPC
La CA et les certificats serveur sont générés via rcgen. La vérification mutuelle garantit qu'aucun agent non autorisé ne peut se connecter.
F6. Déploiement zero-touch
L'enrollment suit un workflow inspiré de Teleport : l'administrateur génère un token single-use sur le serveur, qui produit une commande PowerShell one-liner. L'exécution de cette commande sur la machine cible :
- Crée les répertoires d'installation
- Écrit les certificats mTLS (embarqués dans le script)
- Télécharge le driver, l'agent et les fichiers d'installation depuis
/static - Installe le certificat de signature du driver
- Installe le driver via
pnputil - Configure le registre (URL du serveur)
- Crée et démarre les services Windows (driver + agent)
L'opérateur n'a qu'une seule commande à copier-coller dans un PowerShell élevé.
F7. Protection anti-kill (ObRegisterCallbacks)
Le driver enregistre un callback OB_OPERATION_HANDLE sur le processus agent via ObRegisterCallbacks. Ce callback intercepte toutes les demandes d'ouverture de handle sur le processus agent et supprime les droits PROCESS_TERMINATE et PROCESS_SUSPEND_RESUME. Résultat : même un administrateur ne peut pas terminer l'agent via taskkill, le Gestionnaire des tâches, ou un malware.
F8. Protection du registre (CmRegisterCallbackEx)
Le driver enregistre un callback via CmRegisterCallbackEx qui intercepte toutes les opérations sur les clés HKLM\SOFTWARE\EXFILGUARDIAN. Les tentatives de suppression ou modification des paramètres de configuration de l'agent (URL du serveur, chemin du driver, état du service) sont bloquées avec STATUS_ACCESS_DENIED. La protection couvre les opérations RegNtPreDeleteKey, RegNtPreSetValueKey, RegNtPreDeleteValueKey et RegNtPreRenameKey.
F9. Contournement DKOM et ouverture sécurisée
En développement, les drivers ne sont pas signés par Microsoft, ce qui empêche ObRegisterCallbacks de fonctionner (il exige LDRP_IMAGE_INTEGRITY_FORCED). Le driver contourne cette restriction en positionnant le bit Force Integrity (0x20) sur LDR_DATA_TABLE_ENTRY.Flags via Direct Kernel Object Manipulation (DKOM).
La fonction find_and_set_flag parcourt la liste doublement chaînée des modules kernel (PsLoadedModuleList) pour trouver l'entrée du driver, puis modifie le champ Flags directement en mémoire kernel. Cette technique n'est utilisée qu'en développement ; en production, le driver sera signé par un certificat EV.
F10. Backend cloud-native asynchrone
Le serveur utilise un runtime Tokio multi-threadé avec deux serveurs concurrents :
| Composant | Framework | Port | Rôle |
|---|---|---|---|
| gRPC | Tonic | 50051 | Ingestion des paquets agents |
| REST | Axum | 8080 | Dashboard, alertes, métriques, enrollment |
Les deux serveurs sont lancés via tokio::select! et partagent le même ServerPipeline. La configuration est chargée depuis config.yaml avec des valeurs par défaut sensibles.
Endpoints REST :
| Méthode | Chemin | Description |
|---|---|---|
GET | /api/status | Santé du serveur et version |
GET | /api/v1/alerts | Liste des alertes actives |
GET | /api/v1/metrics | Métriques du pipeline (paquets, flux, détections) |
POST | /api/v1/agent/tokens | Génération d'un token d'enrollment |
GET | /api/v1/enroll/windows | Script PowerShell de déploiement |
GET | /static/* | Fichiers statiques (binaires agent/driver) |
F11. Analyse multi-couches (DPI / Signatures / Comportemental / Corrélation)
Le pipeline d'analyse traite chaque flux à travers quatre couches indépendantes, puis corrèle les résultats pour produire des alertes avec un score de confiance bayésien.
Voir la section Couches de détection pour le détail complet.
F12. Écosystème 100% Rust
L'ensemble du projet est écrit en Rust, du driver kernel (#![no_std]) au serveur cloud. Ce choix élimine les bugs de memory safety (buffer overflows, use-after-free, data races) dans un composant qui traite des données réseau potentiellement malveillantes. L'uniformité du langage simplifie le tooling, la CI, le recrutement et le partage de types entre les crates.
F13. Support multi-plateforme
L'architecture du projet est multi-plateforme, et ce n'est plus un objectif mais une réalité livrée. Le crate exfil-analysis et le serveur compilent sur toutes les plateformes ; la séparation entre le driver (spécifique à l'OS) et le reste de la stack a permis d'ajouter de nouveaux endpoints sans modifier l'agent, le serveur ni l'analyse :
- Windows — driver WFP (
#![no_std], WDK) : capture réseau kernel complète + processus + ETW (DNS, fichiers) + auto-défense. - Linux — driver eBPF/aya (classifiers
tc, ring buffers, kernels ≥ 5.8) : capture réseau + processus + SHA-256 des binaires. Livré et validé sur VM. - macOS — agent passif (capture réseau via libpcap, sans driver kernel) : volontairement plus léger, il prouve la portabilité du contrat de télémétrie (le serveur l'ingère tel quel).
F14. Application desktop (Electron + Next.js)
L'application desktop est l'interface principale de consultation pour les opérateurs SOC. Elle est connectée au vrai backend REST (NEXT_PUBLIC_API_URL) — il n'y a plus de mode mock : en cas de serveur injoignable, elle passe en simple dégradé hors-ligne (listes vides + bandeau « offline » piloté par /api/status). Les types TypeScript du frontend sont alignés 1:1 sur les types Rust du backend (sérialisation serde JSON), garantissant la cohérence entre les données affichées et les données réelles du pipeline d'analyse.
Stack technique : Electron 40 + Next.js 16 (App Router + Turbopack) + React 19 + Tailwind CSS v4 + Zustand (state client) + TanStack Query (state serveur) + Recharts (graphiques) + Biome (linter).
La communication avec le serveur Rust passe par un bridge IPC sécurisé (contextBridge) avec isolation du contexte (contextIsolation: true, nodeIntegration: false, sandbox: true). La connexion HTTP vers l'API REST utilise un client dédié avec détection automatique de l'état (serveur connecté / hors-ligne). En production, l'auth (Better Auth) tourne en mode serveur (standalone).
F14.1 Dashboard — Vue synthétique temps réel
Le tableau de bord est la page d'accueil de l'application. Il agrège les métriques du pipeline d'analyse en temps réel.
| Composant | Données affichées | Source backend |
|---|---|---|
| Stats Cards (4x) | Packets Received, Active Alerts, Flows Processed, Active Flows | GET /metrics → MetricsDto |
| Pipeline Chart | Graphique temps réel des paquets/seconde et détections/seconde (60 points, fenêtre glissante) | Deltas calculés entre deux ticks MetricsDto |
| Threat Distribution | Répartition des alertes par sévérité (Critical/High/Medium/Low) avec barres proportionnelles | GET /alerts → comptage par severity |
| Recent Alerts | 10 dernières alertes avec CategoryBadge, SeverityBadge, StatusBadge, résumé tronqué, IPs source/destination | GET /alerts → Alert[] |
| Detection Modules | État des 5 modules (DNS, HTTP, TLS, ICMP, Behavioral) avec compteur d'alertes par groupe | Groupement dynamique des alertes par ThreatCategory |
Un bandeau « offline » s'affiche lorsque le serveur est injoignable (les listes sont alors vides, aucune donnée simulée).
F14.2 Alertes — Système de gestion SOC
La page d'alertes est le cœur de l'application. Les alertes correspondent aux Alert du backend, produites par la couche de corrélation avec un score de confiance bayésien.
Liste d'alertes (/threats) :
- Filtrage multi-critères : par sévérité (Critical/High/Medium/Low) et par statut (New, Investigating, Confirmed, False Positive, Resolved)
- Chaque carte affiche : catégorie de menace (16 catégories groupées en 5 familles colorées), sévérité, statut, résumé, IPs, nombre de détections, barre de confiance
- Clic → navigation vers la page de détail
Détail d'alerte (/threats/[id]) :
| Section | Contenu |
|---|---|
| Header | Catégorie (badge coloré par famille), sévérité, barre de confiance 0-100%, sélecteur de statut (dropdown pour mise à jour) |
| Summary | Description textuelle de l'alerte générée par le moteur de corrélation |
| Detection Timeline | Timeline verticale chronologique des Detection[] : timestamp, détecteur (DPI/DNS Analyzer, Signature/SIG-001, Behavioral/Beaconing), confiance individuelle |
| Context | Sources IPs, Destinations IPs, Agents concernés, Processus, Flow IDs référencés, date de création |
| Indicators (IOCs) | Tags cliquables pour chaque indicateur : Domain, IP, JA3 Hash, Signature ID, Process, Entropy, Z-Score, Beacon Interval, Data Volume |
| Recommendation | Action recommandée par le moteur (Monitor, Investigate, Block IP, Isolate Agent, Revoke Certificate) avec boutons d'action |
| Whitelist Actions | Boutons "Whitelist IP" et "Whitelist Domain" pré-remplissant le formulaire d'exclusion |
Les 16 catégories de menaces sont organisées en 5 familles visuelles :
- DNS (bleu) : DnsTunneling, DnsExfiltration, DgaDomain, DnsFlood
- HTTP (vert) : HttpExfiltration, HttpCovertChannel
- TLS (violet) : TlsMaliciousFingerprint, TlsCertAnomaly, TlsToRawIp
- ICMP (orange) : IcmpCovertChannel, IcmpLargePayload
- Behavioral (jaune) : C2Beaconing, DataExfiltrationVolume, UnusualProcessNetwork, SuspiciousNewDestination, BaselineDeviation
Le lifecycle d'une alerte suit 5 statuts : New → Investigating → Confirmed / False Positive → Resolved.
F14.3 Flows — Table des flux réseau
La page Flows affiche les FlowRecord bruts, l'unité de donnée fondamentale du pipeline. Les alertes y font référence via flow_ids.
Table des flows (/flows) :
- Colonnes : Process, Source:Port, Destination:Port, Protocol (badge Tcp/Udp/Icmp), Packets, Bytes, Duration, Pre-filter Flags
- Les flags de pré-filtrage (HighOutboundVolume, RegularIntervals, UnusualProcess, NewDestination, UnusualPort, HighDnsFrequency, LargeIcmpPayload, TlsToRawIp) sont affichés comme chips colorées
- Clic → page de détail du flow
Détail d'un flow (/flows/[id]) :
- Métadonnées complètes du 5-tuple (source, destination, ports, protocole, processus)
- Statistiques de trafic : packets, bytes total, outbound/inbound, ratio sortant, intervalle moyen, écart-type
- Flags protocolaires (DNS/TLS/ICMP) et flags de pré-filtrage
- Alertes liées référençant ce flow
F14.4 Analysis — Visualisation du pipeline
La page Analysis offre une vue analytique du moteur de détection.
| Composant | Description |
|---|---|
| Pipeline Diagram | Schéma visuel du pipeline : FlowRecord → [DPI + Signatures + Behavioral] (parallèle) → Correlation → Alert, avec compteurs live depuis MetricsDto (flows processed, signature rules, detections generated, active alerts) |
| Correlation Graph | Graphique 24h montrant le nombre d'alertes et de détections par heure |
| Detection Modules | 5 modules (DNS, HTTP, TLS, ICMP, Behavioral) avec compteurs de détections et d'alertes dérivés dynamiquement des alertes actives |
| Signatures List | Liste des règles de signatures YAML avec ID, nom, catégorie, état (enabled/disabled), nombre de hits |
| Behavioral Stats | Détail par sous-type behavioral (C2 Beaconing, Volume Anomaly, Baseline Deviation, Unusual Process, New Destination) avec compteur et confiance moyenne |
F14.5 Settings — Configuration alignée sur le backend
La page Settings est divisée en 4 onglets. L'onglet Detection est bindé sur le ServerAnalysisConfig (miroir de analysis/src/config.rs) :
Onglet General : démarrage automatique, notifications desktop, mode sombre (paramètres locaux).
Onglet Detection (configuration serveur) :
| Section | Paramètres |
|---|---|
| DPI | dns_enabled, dns_entropy_threshold (slider 1-5), dns_subdomain_length_threshold, tls_enabled, icmp_enabled, icmp_payload_threshold |
| Signatures | enabled, rules_dir (lecture seule), reload_interval_s |
| Behavioral | enabled, zscore_threshold (slider 1-5), cusum_threshold (slider 1-10), beaconing_enabled, beacon_regularity_threshold (slider 0.05-0.5) |
| Correlation | enabled, window_s, alert_threshold (slider 0.1-1.0), critical_threshold (slider 0.5-1.0) |
Chaque section est pliable. Les sliders offrent un contrôle fin sur les seuils de détection.
Onglet Storage : rétention (jours), espace maximum (Go), format d'export (JSON/CSV/PCAP).
Onglet Exclusions : gestion des entrées de whitelist (CRUD). Types supportés : IP, domaine, processus, JA3 hash, flow. Chaque entrée inclut un motif, une raison, une date d'expiration optionnelle, et un filtrage par catégorie de menace. Les boutons "Whitelist IP" et "Whitelist Domain" depuis le détail d'alerte pré-remplissent le formulaire.
F14.6 Administration — Gestion du parc
L'interface d'administration est accessible aux utilisateurs avec le rôle admin :
| Page | Fonction |
|---|---|
| Agents | Table des agents déployés avec hostname, IP, OS, version, statut (online/offline/degraded), état du driver, date d'enrollment. Détail en sheet latérale |
| Users | Gestion des utilisateurs : table, invitation par email, attribution de rôle (admin/member/viewer) |
| Enrollment | Génération de tokens d'enrollment single-use, script PowerShell de déploiement zero-touch, historique des enrollments |
F14.7 Gestion des données — Vrai backend, dégradé hors-ligne
L'application est connectée au vrai backend — il n'y a pas de mode mock :
- Connecté : les données proviennent de l'API REST du serveur via TanStack Query (polling toutes les 1-5 secondes selon le type de données).
- Hors-ligne : si le serveur est injoignable, les hooks renvoient des listes vides et un bandeau « offline » s'affiche (aucune donnée simulée).
La détection de l'état est automatique : un hook useServerStatus poll /api/status. Le state management utilise Zustand pour l'état local (métriques temps réel, configuration) et TanStack Query pour l'état serveur (alertes, flows, signatures, whitelist), qui retombe simplement sur des données vides en cas de ConnectionError.
Les couches de détection
1. Inspection profonde (DPI)
L'analyse DPI décode les protocoles applicatifs et détecte les anomalies protocolaires :
DNS : trois types de détection.
- Tunneling (iodine, dnscat2) : entropie de Shannon élevée des sous-domaines, patterns d'encodage base64/hex, profondeur de sous-domaines anormale
- Exfiltration : données encodées dans les labels DNS, volume anormal de requêtes TXT/NULL
- DGA (Domain Generation Algorithm) : score composite basé sur l'entropie, le ratio consonnes/voyelles, la longueur du domaine et la présence de chiffres
TLS : détection d'anomalies dans les connexions chiffrées.
- JA3 fingerprinting : hash du ClientHello comparé à une base de signatures connues (Cobalt Strike, Meterpreter, Trickbot, Emotet)
- Anomalies de certificats : auto-signés, mismatch SNI/CN, validité trop courte (< 7 jours)
- TLS vers IP brute : connexion TLS sans résolution DNS préalable (indicateur de C2)
ICMP : détection de canaux couverts.
- Payloads anormalement volumineux (> 64 octets)
- Fréquence de requêtes ICMP suspecte
- Combinaison des deux indicateurs pour une confiance renforcée
HTTP (en clair) : inspection L7 des flux HTTP non chiffrés.
- Exfiltration : volume sortant anormal (
HttpExfiltration, High) - Canal caché : User-Agent d'outil offensif ou URI anormalement longue (
HttpCovertChannel, Medium)
Transparence. DGA, tunneling DNS, DNS flood, TLS→IP brute, ICMP et HTTP sont
opérationnels. En revanche, les empreintes JA3, les anomalies de
certificat TLS et CUSUM sont écrits et testés mais pas encore branchés
sur le flux (il manque d'acheminer un TlsMetadata du handshake jusqu'au
pipeline) — c'est une dette technique assumée.
2. Signatures (règles YAML)
Le moteur de signatures évalue chaque flux contre des règles YAML hot-reloadables. 16 règles sont fournies par défaut, réparties sur 5 répertoires (dns/, flow/, icmp/, tls/, http/) — dont, en plus des règles ci-dessous :
| ID | Nom | Sévérité | Protocole | Catégorie |
|---|---|---|---|---|
DNS-DGA-001 | Domain Generation Algorithm Detection | Critical | DNS | DgaDomain |
DNS-EXFIL-001 | DNS Exfiltration - Large Payload | High | DNS | DnsExfiltration |
DNS-EXFIL-002 | DNS Exfiltration - Encoded Data Pattern | Medium | DNS | DnsExfiltration |
DNS-TUN-001 | DNS Tunneling - High Entropy Subdomain | High | DNS | DnsTunneling |
DNS-TUN-002 | DNS Tunneling - Excessive TXT Queries | Medium | DNS | DnsTunneling |
HTTP-HDR-001 | Suspicious Custom Headers | Medium | HTTP | HttpCovertChannel |
HTTP-EXFIL-001 | HTTP Large Upload to Unknown Host | High | HTTP | HttpExfiltration |
HTTP-EXFIL-002 | HTTP Chunked Upload Exfiltration | Medium | HTTP | HttpCovertChannel |
TLS-CERT-001 | Self-Signed Certificate to External Host | Medium | TLS | TlsCertAnomaly |
TLS-CERT-002 | TLS SNI Mismatch | High | TLS | TlsCertAnomaly |
Les règles supportent 12 opérateurs (eq, neq, gt, gte, lt, lte, contains, not_contains, regex, exists, in, not_in) et peuvent cibler 23 champs du flux (métriques réseau, contexte processus, flags protocolaires). 16 catégories de menaces sont supportées.
Le rechargement à chaud (hot-reload) est supporté : modifier un fichier YAML est pris en compte sans redémarrer le serveur. La détection de doublons d'ID prévient les conflits entre règles.
3. Analyse comportementale
L'analyse comportementale modélise le trafic normal puis détecte les écarts :
Baseline. Pendant une période d'apprentissage (15 jours par défaut), le système accumule des statistiques par agent via l'algorithme de Welford (moyenne et écart-type incrémentaux, sans stocker tous les échantillons) :
- Débit moyen, taille de paquets, volume sortant
- Distribution protocolaire (ratios DNS, ICMP, TLS)
- Processus et destinations connus
Détection d'anomalies. Après apprentissage, trois méthodes complémentaires :
- Z-score : détecte les déviations soudaines (seuil configurable, défaut : 3σ)
- CUSUM (Cumulative Sum) : détecte les augmentations graduelles qu'un Z-score instantané manquerait
- EMA (Exponential Moving Average) : détecte les anomalies de volume (alerte quand le débit dépasse 3× la moyenne mobile)
Beaconing C2. Détection des communications régulières caractéristiques des implants :
- Calcul du coefficient de variation (CV) des intervalles de connexion
- CV < 0.15 avec au moins 20 connexions = beaconing probable
- Confiance proportionnelle : CV de 0.05 donne une confiance plus élevée que 0.14
4. Corrélation et scoring
La couche de corrélation est le cerveau du système. Elle regroupe les détections des trois couches précédentes et calcule un score de confiance final :
Fenêtre temporelle. Les détections sont conservées dans une fenêtre glissante (5 minutes par défaut). Les corrélations se font par destination IP et par couple agent + catégorie de menace.
Scoring bayésien. Les confiances sont combinées via la formule P(A∪B) = 1 - (1-P(A)) × (1-P(B)), avec :
- Décroissance temporelle : les détections anciennes perdent du poids (demi-vie de 5 minutes)
- Bonus de diversité : +10% par détecteur distinct (DPI + signatures + comportemental = +20%)
- Escalade de sévérité : quand la confiance dépasse 0.9, la sévérité monte d'un cran
Seuils d'alerte :
- Confiance ≥ 0.6 : alerte standard
- Confiance ≥ 0.85 : alerte critique
- Confiance ≥ 0.85 + sévérité High : recommandation de blocage automatique
Les choix techniques et leurs justifications
Pourquoi tout en Rust ?
Le projet initial envisageait du C pour la capture. Ce choix a été abandonné : mélanger C et Rust annule les garanties de memory safety de Rust aux frontières FFI. Le driver kernel est écrit en Rust #![no_std] via les crates WDK, qui fournissent des abstractions sûres au-dessus des APIs kernel Windows. L'agent et le serveur sont en Rust standard. Cette uniformité élimine une catégorie entière de bugs (buffer overflows, use-after-free, data races) dans un composant qui traite des données réseau potentiellement malveillantes.
Pourquoi Windows en priorité ?
La décision de cibler Windows en priorité est un choix stratégique. Les postes de travail en entreprise, là où résident les données sensibles et où les attaquants opèrent, sont massivement sous Windows. Un système anti-exfiltration qui ne couvre pas Windows ne couvre pas le vecteur d'exfiltration principal. Le Windows Filtering Platform (WFP) fournit un mécanisme robuste et documenté pour l'interception réseau au niveau kernel, avec un modèle de callouts qui permet une intégration propre sans patcher le système. Le portage vers Linux (eBPF/aya) et macOS (agent passif libpcap) a ensuite été livré sans toucher au serveur — la preuve concrète que le contrat de télémétrie est portable.
Pourquoi une architecture distribuée ?
Un monolithe qui capture, analyse et affiche sur la même machine ne passe pas à l'échelle. L'architecture distribuée permet :
- Déploiement sur N machines avec un seul serveur d'analyse
- Pré-filtrage local qui réduit le trafic réseau entre agent et serveur
- Résilience : la file SQLite WAL de l'agent garantit zéro perte même si le serveur tombe
- Séparation des privilèges : le driver tourne en kernel, l'agent en SYSTEM, le serveur peut tourner sur une machine dédiée
Pourquoi gRPC/Protobuf ?
Le protocole entre agent et serveur doit supporter du streaming continu à haut débit avec un overhead minimal. gRPC avec Protobuf offre :
- Sérialisation binaire compacte (vs JSON texte)
- Streaming bidirectionnel natif
- Support mTLS intégré dans
tonic - Génération automatique du code client/serveur depuis le
.proto
Pourquoi Electron + Next.js pour le desktop ?
L'application desktop devait être multi-plateforme et offrir une interface riche avec des graphiques temps réel. Electron permet de cibler les trois plateformes avec une seule base de code. Next.js avec React fournit les patterns de développement UI modernes. Ce choix permet à l'équipe de développer l'interface web et l'application native en parallèle avec le même code.
Pourquoi des règles YAML hot-reloadables ?
Durcir les règles de détection dans le code source est un anti-pattern dans le domaine de la sécurité. Les menaces évoluent, les contextes changent, les faux positifs doivent être ajustés. Externaliser les règles dans des fichiers YAML lisibles par un humain permet à un opérateur de les modifier sans recompiler. Le hot-reload garantit qu'une modification est prise en compte en quelques secondes sans interruption de service.
Ce que le projet produit
À terme, ExfilGuardian est un ensemble de livrables complémentaires :
Le driver kernel (.sys) s'installe sur chaque machine Windows à protéger. Il intercepte le trafic réseau via WFP et le transmet à l'agent local.
L'agent est un service système qui tourne en arrière-plan. Il pré-filtre les paquets, les met en file d'attente et les streame au serveur. Un installeur automatise le déploiement (registre + service Windows).
Le serveur d'analyse reçoit les flux de tous les agents, les analyse via le pipeline de détection (DPI + signatures + comportemental + corrélation) et expose les alertes via une API REST.
L'application desktop est l'interface principale. Elle présente un tableau de bord synthétique, un flux d'alertes filtrable et une vue de configuration. Elle communique avec le serveur via l'API REST.
Le site de documentation est intégré au projet. Il documente l'architecture, les conventions, les guides de démarrage et les références techniques.
Organisation du projet
Le projet est structuré en monorepo avec un workspace Cargo :
exfil-guardian/
├── driver/ # Kernel WDM, workspace séparé (nightly + WDK)
├── agent/ # Service système, gRPC client
├── server/ # Serveur d'analyse, gRPC + REST
├── analysis/ # Coeur analytique : DPI, signatures, behavioral, corrélation
├── installer/ # Installeur Windows
├── proto/ # Définitions Protobuf
├── certs/ # Générateur de certificats mTLS
├── signatures/ # Règles de détection YAML
├── desktop/ # Application Electron + Next.js
└── docs-site/ # Documentation FumadocsLe driver est un workspace Cargo séparé car il nécessite le toolchain nightly et le WDK, incompatible avec les crates userland. Les cinq autres crates Rust (agent, server, analysis, installer, certs) partagent un workspace commun avec des dépendances centralisées.
Le développement suit une approche industrielle : dépôt Git centralisé sur GitHub, branche principale protégée (Trunk), toute modification passant par une pull request. Le pipeline CI/CD automatise la vérification : formatage, clippy, tests, build Windows pour les composants agent/serveur.
Confidentialité et éthique d'usage
ExfilGuardian fait de l'inspection profonde de paquets. C'est une capacité puissante qui impose des responsabilités claires.
Le système n'est pas un DLP. Il ne lit pas le contenu des fichiers, ne déchiffre pas le trafic TLS, ne classe pas les données selon leur sensibilité. Ce qu'il fait, c'est extraire des caractéristiques statistiques (l'entropie d'un nom de domaine, la taille d'un champ, la fréquence de connexion vers un endpoint) pour en déduire un comportement. Le payload brut des paquets n'est jamais persisté. Les alertes stockées contiennent uniquement des métadonnées réseau : adresses IP, protocole, score, timestamp.
Sur le plan légal, cet outil est conçu pour être déployé par les administrateurs d'un réseau sur leur propre infrastructure. Dans un contexte d'entreprise, la surveillance du trafic réseau est soumise à des obligations d'information vis-à-vis des utilisateurs. Le RGPD et le Code du travail s'appliquent. L'outil s'inscrit dans un usage conforme à ces obligations.