Pilotage, empreinte et donnees de securite¶
Ce document fixe la cible du produit : un plan de controle qui pilote vraiment le bord, une empreinte client exploitable, des evenements de securite structures, des drains vers un SOC, un bus pour tenir la charge, et une couverture L4 en plus du HTTP.
Etat au 20 octobre 2026 : l'operateur applique desormais les interrupteurs du bloc
security et retire les objets quand on les eteint (verifie en production sur
EdgeSite toggle-test). Le reste de ce document est la feuille de route, avec
l'effort estime et les pieges.
1. Ce que font les acteurs, et ce qu'il faut en reprendre¶
Cloudflare (WAF, Bot Management, Security Analytics)¶
- Regles par phase (rulesets) : chaque requete traverse des phases ordonnees, et chaque regle peut journaliser sans bloquer. C'est la bonne abstraction : une politique est une suite d'etapes, pas un interrupteur.
- Bot score 1-99 attache a chaque requete, calcule sur des signaux heuristiques (empreinte TLS/HTTP, coherence, comportement). Le score est fourni au client comme un fait, pas comme un verdict.
- Turnstile : preuve de travail invisible, sans interaction, avec un jeton signe verifie au bord. C'est exactement notre modele, en mieux fini.
- Under Attack Mode : un seul bouton qui durcit tout le site (challenge sur tout, cache reduit). Utile, et trompeusement difficile a bien faire.
- Security Analytics : agregats par dimension (regle, action, pays, AS, user agent, empreinte) avec echantillons de requetes. C'est ce qui manque le plus a notre console.
- Logpush : export par destination (S3, Splunk, Datadog, webhook) avec champs selectionnables, batching et reprise. Notre modele de drain doit s'en inspirer.
- Rate limiting par expression plutot que par compteur global.
A reprendre : phases ordonnees, score comme fait, analyse par dimension, drains par destination avec choix des champs, mode crise. A eviter : le score opaque non explicable. Un client doit pouvoir demander pourquoi une requete a ete bloquee et obtenir une reponse.
DataDome¶
- Empreinte d'appareil cote navigateur : canvas, WebGL, polices, fuseau, coherence entre signaux, plus un cookie signe. Ce que le reseau ne voit pas.
- Signaux tiers : reputation d'adresse, d'AS, de plage hebergeur, d'empreinte deja vue sur d'autres clients. L'effet reseau est leur vraie douve.
- Decision en quelques millisecondes au bord, avec un cache de reputation.
- Challenge progressif : invisible, puis interaction, puis CAPTCHA selon la confiance. Jamais un mur binaire.
- Protection de compte (credential stuffing, prise de compte) separee de la protection de site.
- Console orientee enquete : une requete bloquee s'ouvre sur son contexte (empreinte, historique de l'adresse, regles declenchees).
A reprendre : challenge progressif, contexte d'enquete, separation site/compte. A eviter : l'empreinte navigateur invasive sans consentement. En Europe, un empreillage de fingerprinting doit etre documente et minimise.
Bunny Shield¶
- Positionnement prix : DDoS + WAF + detection de bots pour quelques dollars par site, sans engagement. C'est le concurrent a battre sur le milieu de gamme.
- Regles de bord scriptables (petits scripts par evenement) plutot qu'un langage de politique complet.
- Simplicite radicale : un interrupteur par fonction, pas de matrice.
- Reseau tres large, tarif tres bas : ils gagnent par l'echelle, pas par la finesse.
A reprendre : la grille tarifaire par site et non par requete, la simplicite de prise en main. A eviter : leur finesse de politique, insuffisante pour un infogerant.
Les autres, en une ligne chacun¶
- Akamai : politique par application, protection des API par schema, detection comportementale. Reference sur les grandes surfaces.
- Imperva : classification des API, protection des identifiants, tres fort sur l'audit de conformite.
- Fastly : calcul au bord (Compute@Edge) et journaux en flux. C'est le modele a suivre pour les drains : le client branche ce qu'il veut.
- AWS WAF/Shield : regles managees, labels de regles (une regle pose une etiquette, une autre decide sur l'etiquette). Les labels sont une excellente idee, plus souple que des priorites numeriques.
- Sucuri : simplicite et nettoyage de site compromis. Utile a connaitre pour l'argumentaire, pas pour l'architecture.
CrowdSec, pour la structure¶
- Scenario : un ensemble de regles qui, sur une fenetre, produit une alerte.
- Decision : la sanction attachee a une alerte (type, portee, valeur, duree, origine). Une alerte peut porter plusieurs decisions.
- Portee :
Ip,Range,Country,AS,User,Session. - LAPI : le point central qui recoit les alertes et sert les decisions aux bouncers, avec listes communautaires et abonnements.
- Bouncer : le composant qui applique (pare-feu, serveur web, proxy).
- Console : enquete, historique, duree de blocage, faux positifs.
C'est le bon decoupage : evenement, alerte, decision, application. Notre console melange encore les trois. Le document de schema en section 7 corrige cela.
2. L'operateur comme plan de controle¶
Ce qui marche aujourd'hui¶
- CRD
EdgeSiteetBlocklistSource, reconciliation idempotente, reprise toutes les cinq minutes. - Bloc
spec.security:waf,sensitiveFiles,challenge,blocklists,allowlists. Chaque interrupteur cree ou retire un objet reel. - Suppression effective a l'extinction (verifie :
AuthorizationPolicyetWasmPluginretires, puis recreees au rallumage). - Lecture de l'etat frais depuis l'API, sans cache, pour ne jamais decider sur une vue perimee.
- Conditions
Readyavec message lisible et compteur d'objets.
Ce qui manque pour en faire un outil de pilotage¶
- Finaliseur de suppression : supprimer un
EdgeSitedoit retirer ses objets (aujourd'hui ils survivent, orphelins, si les ownerReferences ne suffisent pas). - Detection de derive : comparer l'objet desire a l'objet reel et corriger. Aujourd'hui on applique sans verifier, donc une modification manuelle passe.
- Statut par fonction :
status.features[]avecapplied,reason,since. La console afficherait la verite du terrain, pas l'intention. - Validation a l'admission (CEL) : refuser un domaine malforme, un port interdit, un nom d'amont vide, une difficulte de challenge hors bornes.
- Valeurs par defaut dans le CRD : un manifeste minimal doit produire un site sur. Aujourd'hui les defauts sont dans le code Go, invisibles pour le client.
- Plan avant application (dry-run) : rendre le diff entre l'etat desire et l'etat reel, pour que la console montre ce qui va changer avant de le faire.
- Evenements Kubernetes : chaque application, chaque retrait, chaque echec
doit produire un evenement lisible (
kubectl describe). - Metriques de reconciliation : duree, nombre, echecs par type, age de la derniere reussite. Sans cela, l'operateur est une boite noire.
- Derive de version :
status.observedGenerationcompare ageneration, et conditionStalledsi la reconciliation echoue en boucle. - Haute disponibilite : election de leader (deja fournie par controller-runtime), deux replicas, PodDisruptionBudget.
- Rollout par vagues : appliquer un changement de configuration a 1 %, 10 %, 100 % des noeuds de bord, avec retour arriere automatique sur erreur.
- Webhook de conversion : le jour ou
v1beta1arrive, il faut pouvoir lire les anciens objets sans casser les clients.
3. Liste exhaustive des propositions¶
Effort : S (moins d'une journee), M (deux a cinq jours), L (une a trois semaines).
A. Boucle de controle (operateur)¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| A1 | Finaliseur de suppression | S | Ne plus laisser d'objets orphelins |
| A2 | status.features[] par fonction |
S | La console dit ce qui est pose, pas ce qui est demande |
| A3 | Detection de derive et correction | M | Un objet modifie a la main doit revenir |
| A4 | Validation CEL dans le CRD | S | Refuser tot, pas au milieu de la reconciliation |
| A5 | Defauts declares dans le CRD | S | Un manifeste minimal doit suffire |
| A6 | Dry-run et diff lisible | M | Montrer ce qui va changer avant de le faire |
| A7 | Evenements Kubernetes | S | Diagnostic sans lire les journaux |
| A8 | Metriques Prometheus de reconciliation | S | Voir l'operateur travailler |
| A9 | Deux replicas et PDB | M | Plus de point unique |
| A10 | Rollout par vagues avec retour arriere | L | Changer la politique sans couper un client |
| A11 | Signature des manifestes (cosign) | M | Prouver que l'image executee est la bonne |
| A12 | Revision d'historique (status.history) |
M | Savoir qui a change quoi, quand |
B. Politique et decision¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| B1 | Phases ordonnees a la Cloudflare | M | Remplacer les priorites numeriques par un pipeline lisible |
| B2 | Etiquettes de regles (labels) | S | Une regle pose une etiquette, une autre decide |
| B3 | Score expose comme un fait, pas un verdict | S | Expliquer une decision |
| B4 | Challenge progressif (invisible, interaction, CAPTCHA) | M | Moins de friction qu'un mur |
| B5 | Protection de compte (credential stuffing) | L | Le cas d'usage le plus demande en e-commerce |
| B6 | Limitation de debit par expression | M | Par route, par utilisateur, par empreinte |
| B7 | Mode crise global (un bouton, tout durcit) | S | Repondre a une attaque en dix secondes |
| B8 | Politique par route et par methode | M | Le WAF actuel ne distingue pas /api de /blog |
| B9 | Simulateur de regles (rejouer un journal) | M | Tester une politique sur le trafic passe |
| B10 | Explication de decision (x-exoledge-reason) |
S | Le client voit la regle qui a tranche |
C. Empreinte et identification¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| C1 | JA4 dans chaque evenement HTTP | S | Voir la vraie nature du client |
| C2 | JA4H (empreinte HTTP normalisee) | M | Distinguer un navigateur d'un script qui l'imite |
| C3 | JA4S cote serveur (empreinte de notre reponse) | S | Detecter les clients qui ne suivent pas le protocole |
| C4 | JA4T/JA4TS par eBPF (pile TCP) | L | Detecter les systemes d'exploitation annonces a tort |
| C5 | JA4X sur les certificats clients (mTLS) | M | Identifier un partenaire par son certificat |
| C6 | Reputation d'empreinte partagee entre organisations | M | Une empreinte vue sur vingt sites est un bot |
| C7 | Empreinte navigateur (canvas, WebGL) cote challenge | L | Le seul signal que le reseau ne voit pas |
| C8 | Coherence UA / empreinte / ordre des en-tetes | M | Le meilleur detecteur de scripts deguises |
D. Journalisation et drains¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| D1 | Drain OTLP par organisation (gRPC et HTTP) | M | Brancher un SOC sans lui imposer notre format |
| D2 | Choix des champs exportes | S | Ne pas envoyer d'adresses IP a un tiers sans raison |
| D3 | Tampon disque et reprise apres coupure | M | Un SOC injoignable ne doit rien perdre |
| D4 | Echantillonnage reglable par drain | S | Tenir la charge sans tout jeter |
| D5 | Evenement de test a la demande | S | Prouver au client que le drain marche |
| D6 | Metriques par drain (envoye, en echec, en attente) | S | Voir la sante du tuyau |
| D7 | Redaction (IP tronquee, en-tetes sensibles) | S | Minimisation avant export |
| D8 | Archivage froid en Parquet | M | Garder un an sans garder un an de base |
E. Bus et fiabilite¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| E1 | Bus Iggy derriere une interface | M | Decoupler bord et consommateurs |
| E2 | Sujets security.events, decisions, audit |
S | Trois volumes, trois retentions |
| E3 | Cle d'idempotence (UUID v7) | S | Rejouer sans doubler |
| E4 | Groupes de consommateurs et offsets | M | Plusieurs lecteurs independants |
| E5 | Repli HTTP si le bus tombe | S | Le bord ne s'arrete jamais |
| E6 | Comparaison mesuree Iggy / NATS / Redpanda | M | Ne pas choisir sur une promesse |
F. L4 et protocoles¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| F1 | Ecouteurs TCP dans EdgeSite |
M | Bases de donnees, SSH, MQTT |
| F2 | Ecouteurs UDP (DNS, QUIC) | M | Sans connexion, donc regles par 5-uplet |
| F3 | Routage gRPC (h2c, sante, retries) | S | Le protocole par defaut des API internes |
| F4 | Passe-plat TLS avec routage par SNI | M | Ne pas terminer le TLS d'un client |
| F5 | Decision L4 (reputation, debit, JA4T) | M | Le WAF ne voit rien en L4 |
| F6 | Protection contre l'amplification (UDP) | M | Ne pas devenir un reflecteur |
| F7 | PROXY protocol vers l'amont | S | Garder l'adresse reelle du client |
| F8 | Limitation de connexions et delais par ecouteur | S | Tenir une attaque par epuisement |
G. Console et experience¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| G1 | Analyse par dimension (regle, pays, AS, empreinte) | M | La page qui manque le plus |
| G2 | Enquete sur une requete bloquee | M | Voir le contexte, pas juste la ligne |
| G3 | Editeur de politique avec apercu du diff | L | Configurer sans craindre de casser |
| G4 | Gestion des faux positifs (exclure une regle) | S | Le quotidien d'un infogerant |
| G5 | Journal d'audit des actions d'administration | S | Qui a desactive quoi |
| G6 | Export CSV et PDF d'un rapport d'incident | S | Ce que demande le client final |
| G7 | Tableau de bord par organisation pour l'infogerant | M | Vendre a un revendeur, pas a un site |
| G8 | Notifications (courriel, webhook, ntfy) | S | Personne ne regarde une console en permanence |
H. Exploitation et securite de la plateforme¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| H1 | Deux repliques Overwatch et base en HA | M | Ne pas perdre la console en meme temps que le bord |
| H2 | Sauvegarde et restauration verifiees | M | Une base perdue, c'est un client perdu |
| H3 | Rotation des secrets automatisee | M | Lecons des fuites de jetons |
| H4 | Chiffrement au repos des journaux | S | Donnees personnelles dans les URL |
| H5 | Retention par organisation | S | Le contrat, pas un reglage global |
| H6 | Tests de charge du bord (req/s, latence) | M | Connaitre sa limite avant le client |
| H7 | Exercice d'attaque annuel | M | Prouver la resistance, pas la supposer |
| H8 | Page de statut et SLA mesures | M | Argument commercial |
I. Produit et commercial¶
| # | Proposition | Effort | Pourquoi |
|---|---|---|---|
| I1 | Offre par site, pas par requete | S | Lisible pour une PME |
| I2 | Marque blanche (logo, domaine, courriels) | M | Vendre aux infogerants |
| I3 | Essai sans carte, 14 jours | S | Le seul modele qui convertit |
| I4 | Rapport mensuel automatique | M | Justifier l'abonnement |
| I5 | Grille de revente (marge par site) | S | Interesser un integrateur |
| I6 | Page de transparence (sous-traitants, hebergement) | S | Argument souverainete |
4. La suite JA4+ dans le produit¶
Ce que c'est¶
Neuf empreintes, chacune decrivant une couche differente de la connexion :
- JA4 : ClientHello TLS (version, chiffrements, extensions, ALPN). La plus utile au quotidien.
- JA4S : ServerHello, donc l'empreinte de notre propre reponse. Sert a reperer les clients qui ne suivent pas le protocole.
- JA4H : requete HTTP normalisee (methode, version, en-tetes dans l'ordre,
cookies, langue). Distingue un vrai navigateur d'un script qui copie son
en-tete
User-Agent. - JA4T / JA4TS : pile TCP (fenetre, options, TTL). Demande de voir le premier paquet, donc pas depuis un proxy applicatif : eBPF, nftables ou Zeek.
- JA4X : certificat X.509, utile en mTLS pour identifier un partenaire.
- JA4SSH : session SSH.
- JA4L / JA4LS : latence et distance estimees.
- JA4D : DHCP.
Ce que nous pouvons capturer, et ou¶
- JA4 : oui, au terminateur TLS. Envoy expose
%TLS_JA4_FINGERPRINT%comme operateur de commande dans les journaux d'acces. C'est la premiere brique, elle ne coute rien. - JA4H : a calculer nous-memes dans le decideur a partir des en-tetes recus. Envoy ne le fournit pas.
- JA4S : necessite de calculer sur la reponse ; possible dans le plugin wasm cote reponse, plus rarement utile.
- JA4T : impossible depuis un proxy applicatif. Il faut un programme eBPF sur le noeud (Cilium peut exporter les paquets) ou un agent dedie.
- JA4X : possible en mTLS, le certificat client est disponible au terminateur.
Licence, point bloquant a traiter avant de vendre¶
- JA4 (ClientHello) est publie sous licence BSD-3 : utilisation libre.
- JA4S, JA4H, JA4X, JA4T, JA4TS, JA4SSH, JA4L, JA4D sont sous FoxIO License 1.1, avec brevet en cours. La licence autorise l'usage interne et la recherche, mais une licence commerciale (OEM) est requise pour integrer ces empreintes dans un produit vendu.
- Consequence : soit on prend la licence OEM aupres de FoxIO, soit on se limite a JA4 (BSD) et a nos propres calculs pour JA4H (une normalisation de requete est facile a reecrire, sans copier leur code).
- A verifier avant tout engagement commercial : demander un devis, et documenter la reponse. C'est exactement le genre de dependance qui casse un contrat de revente six mois plus tard.
Mise en oeuvre, ce qui a ete appris¶
%TLS_JA4_FINGERPRINT%rendnulltant que l'inspecteur TLS ne le demande pas. L'operateur existe, la configuration est acceptee, et le champ reste vide. Il faut poserenable_ja4_fingerprinting: truesurenvoy.filters.listener.tls_inspector(EnvoyFilterLISTENER, contexte GATEWAY). Une valeur nulle est pire qu'une cle absente : on croit la donnee presente.%TLS_VERSION%n'existe pas comme operateur de journal d'acces : Envoy rejette l'ecouteur entier et le proxy garde silencieusement l'ancien format. Le symptome est un journal qui ne change pas, pas une erreur visible.- Le journal doit etre JSON avec des cles nommees : le collecteur fusionne l'objet (Merge_Log) et le decideur lit des champs, pas une ligne a decouper.
- Fluent Bit transmet tel quel : aucun changement de configuration n'a ete necessaire une fois le champ present dans la ligne.
- Cout : nul en CPU mesurable. L'empreinte est calculee une fois par connexion.
Ce qu'on en fait¶
- Un client qui se declare Firefox mais dont l'empreinte TLS est celle de Go ou de Python est un robot. C'est la regle la plus rentable, et elle est gratuite.
- Une meme empreinte vue sur cinquante adresses differentes est un reseau de machines. Une meme adresse qui change d'empreinte a chaque requete est un outils de rotation.
- Une empreinte inconnue, jamais vue, sur un site a faible trafic, merite un challenge, pas un blocage.
- Stockage : table dans Valkey, cle = empreinte, valeur = compteurs (premiere vue, derniere vue, nombre d'adresses, nombre de sites), duree de vie 30 jours. Cardinalite bornee : une empreinte fait 36 caracteres, on en voit quelques milliers par jour.
- Pieges : HTTP/3 ne passe pas par le meme chemin (QUIC, donc autre empreinte) ; un proxy d'entreprise reutilise la meme empreinte pour des milliers d'utilisateurs ; les mobiles changent d'empreinte a chaque mise a jour. Une empreinte seule ne condamne jamais : elle pese dans un score.
5. Drains de journaux vers un SOC, au format OpenTelemetry¶
Modele¶
Un drain est une destination declaree par organisation : type (otlp-grpc,
otlp-http, webhook), adresse, en-tetes d'authentification, jeu de champs,
filtre, echantillonnage, etat.
Traduction vers OTLP¶
resource:service.name=edge,service.namespace=<organisation>,exoledge.site=<domaine>,exoledge.region=<region>,host.name=<noeud>.scope:exoledge.edgeversion du composeur.logRecord:timeUnixNano(instant de la decision),severityNumberderive de l'action (block= WARN,challenge= INFO,allow= DEBUG),severityText,body= phrase lisible,attributes= la fiche structuree (section 7).- Identifiants de trace : si la requete porte un
traceparent, on le propage. Un SOC peut ainsi relier l'attaque a la trace applicative.
Livraison¶
- gRPC en priorite (protobuf, compression gzip), HTTP/protobuf en repli pour les SOC qui n'ouvrent que 443.
- Lots de 512 evenements ou 5 secondes, tampon disque de 1 Go, reprise avec attente exponentielle (1 s, 2 s, 4 s, jusqu'a 5 min), plafond de concurrence.
- Ne jamais bloquer le bord : le drain lit depuis le bus, jamais depuis le chemin de la requete. Si le SOC tombe, on perd du journal, jamais du trafic.
- Mesures exposees : evenements produits, envoyes, en echec, en attente, age du plus ancien evenement en tampon.
Choix des champs et minimisation¶
Par defaut : domaine, instant, action, regle, pays, AS, empreinte, methode,
chemin tronque, code de reponse. Pas d'adresse IP complete vers un tiers sans
accord explicite : proposer l'adresse tronquee (192.0.2.0/24) ou un hachage
avec sel par organisation. C'est la difference entre un produit vendable en Europe
et un incident RGPD.
6. Un bus de messages : Iggy¶
Pourquoi¶
Aujourd'hui, Fluent Bit pousse vers /v1/ingest en HTTP. Un seul consommateur,
aucun rejeu, aucune reprise si la console tombe. Des qu'on ajoute un drain SOC,
un export analytique et un detecteur d'anomalies, il faut un bus : plusieurs
lecteurs independants, un rejeu apres incident, une retention par sujet.
Pourquoi Iggy¶
- Ecrit en Rust, un seul binaire, faible empreinte memoire : coherent avec le reste du produit.
- Modele simple : flux, sujets, partitions, groupes de consommateurs, offsets.
- Protocoles TCP, QUIC et HTTP : un SOC peut lire en HTTP sans client special.
- Licence Apache 2.0.
Topologie proposee¶
- Flux
edge, sujets : security.events: une entree par decision, retention 72 h, volume eleve.decisions: une entree par sanction, retention 90 jours, volume faible, compacte par cle (adresse, portee).audit: actions d'administration, retention un an, jamais compacte.- Producteur : le decideur au bord, en ecriture asynchrone avec tampon borne. Si le bus est plein, on echantillonne, on ne bloque pas.
- Consommateurs : Overwatch (affichage et base), drainer OTLP, export froid, detecteur de motifs.
Reserves, a lever par la mesure¶
- Iggy est un projet jeune (Apache, en incubation). Pas d'ecosysteme, peu de retours de production a grande echelle. Il faut mesurer : 50 000 evenements par seconde, latence au 99e centile, comportement quand un consommateur est lent, reprise apres arret brutal.
- Comparer avec NATS JetStream (mature, tres leger, Rust possible via client) et Redpanda (compatible Kafka, plus lourd). Le choix doit se faire sur des chiffres, pas sur l'enthousiasme.
- Garder une interface interne (
publish,subscribe,commit) pour pouvoir changer de bus sans toucher au bord.
7. Journal de securite structure, inspire de CrowdSec¶
Le defaut actuel¶
Nos lignes de journal melangent trois choses : la requete, la decision et la sanction. Impossible de repondre proprement a "combien de fois cette regle a bloque ce pays cette semaine" sans analyser du texte.
Le modele¶
Une entree = un evenement de decision. Champs fixes, pas de dictionnaire libre.
{
"id": "018f3c2e-7b41-7c9a-9d0e-2f6b1a5c8e44",
"time": "2026-10-20T09:14:03.412Z",
"organisation": "acme",
"site": "www.acme.fr",
"kind": "decision",
"action": "challenge",
"score": 45,
"scenario": "http_probing",
"rule": "930120",
"rule_message": "OS File Access Attempt",
"phase": "request_headers",
"source": {
"ip": "203.0.113.42",
"asn": 64500,
"as_org": "Example Hosting",
"country": "NL",
"range": "203.0.113.0/24",
"reputation": { "tor": false, "proxy": true, "cve": false, "lists": ["proxies"] }
},
"client": {
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"ja4": "t13d1516h2_8daaf6152771_02713d6af862",
"ja4h": "ge11nn050000_9f8a3d2c11b0",
"coherent": false,
"clearance": false
},
"request": {
"method": "GET",
"path": "/.env",
"query_keys": ["debug"],
"host": "www.acme.fr",
"bytes": 412,
"status": 403
},
"decision": {
"type": "challenge",
"scope": "ip",
"value": "203.0.113.42",
"duration_s": 1800,
"origin": "edge"
},
"latency_ms": 3.1,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
Regles de conception¶
- Un identifiant stable (UUID v7, trie par temps) sert de cle d'idempotence dans le bus et en base.
scenariodecrit la famille (http_probing,sqli,credential_stuffing,cve_2025_55182),rulela regle technique qui a declenche. Deux niveaux, comme CrowdSec : l'alerte parle au metier, la regle parle au moteur.actionest le resultat :allow,challenge,throttle,block,log_only. Distinct dedecision.typequi est la sanction posee, avec sa duree. Une requete peut etre bloquee sans qu'une sanction soit enregistree.- Pas de corps de requete, pas d'en-tete
Authorization, pas de cookie. On garde les cles de requete, jamais les valeurs sensibles. - Adresse : tronquee dans les exports tiers, complete en base locale avec duree de vie.
- Cardinalite bornee : les etiquettes de metriques sont
rule,action,country,site. Jamais le chemin brut.
Stockage¶
- PostgreSQL en JSONB, table partitionnee par jour, index sur
site,time,source.ip,rule. - 30 jours chauds en base, un an en Parquet dans un stockage objet, restauration a la demande.
- Overwatch : nouvelle page
/eventsavec les memes filtres que le flux actuel, plus une vue par scenario et une vue par adresse.
Ce que cela debloque¶
- Repondre a "pourquoi cette requete a ete bloquee" avec la regle exacte.
- Alimenter un SIEM sans lui imposer une analyse de texte.
- Comparer deux semaines, deux sites, deux organisations.
- Facturer sur des faits mesures.
8. TCP, UDP et gRPC¶
Ce qu'Istio sait faire¶
- La porte accepte des ecouteurs
HTTP,HTTPS,TLS(passe-plat),TCP,UDP.TCPRouteetUDPRoutesont dans le canal experimental de Gateway API : il faut installer les CRD correspondantes (deja installees pourHTTPRoute). - gRPC ne demande rien de special : c'est du HTTP/2, donc un
HTTPRouteavecappProtocol: kubernetes.io/h2ccote service. Les delais, les reprises et la duplication de trafic fonctionnent comme en HTTP. - Passe-plat TLS : l'ecouteur
TLSavecmode: Passthroughroute par SNI, sans terminer la connexion. On perd l'inspection HTTP mais on garde JA4 du ClientHello, ce qui est deja beaucoup.
Ce que cela impose¶
- En L4, pas de chemin, pas d'en-tete, pas de WAF. La decision se limite a l'adresse, a la reputation, au debit de connexions et a l'empreinte TCP. La console doit le dire clairement : afficher "le WAF ne voit pas ce flux" evite une fausse impression de protection.
- UDP n'a pas de connexion : compter par 5-uplet sur une fenetre courte, et reflechir a l'amplification (une reponse DNS peut etre cinquante fois la requete). Un service UDP expose sans limite devient un reflecteur.
- Le PROXY protocol est necessaire si l'amont veut l'adresse reelle du client.
- Un ecouteur TCP qui termine le TLS doit avoir son certificat ; un ecouteur en passe-plat n'en a pas besoin.
Modele dans EdgeSite¶
spec:
listeners:
- name: grpc-api
protocol: HTTP
port: 443
hostname: api.acme.fr
http:
appProtocol: kubernetes.io/h2c
timeout: 30s
retries: 2
- name: pg
protocol: TCP
port: 5432
hostname: db.acme.fr
tcp:
upstream: postgres
port: 5432
proxyProtocol: true
maxConnections: 200
- name: dns
protocol: UDP
port: 53
udp:
upstream: dns-svc
port: 53
ratePerSecond: 500
L'operateur rend un ecouteur de porte par entree, une route HTTPRoute,
TCPRoute ou UDPRoute selon le protocole, et une politique de debit L4 quand
elle est demandee.
Ordre de mise en oeuvre¶
- gRPC (aucune brique nouvelle).
- TCP avec upstream simple, sans passe-plat.
- Passe-plat TLS par SNI.
- UDP avec limitation par 5-uplet.
- Decision L4 branchee sur la reputation et JA4T.
9. Feuille de route¶
Phase 1, deux semaines, ce qui rend le produit utilisable
Finaliseur, status.features[], evenements Kubernetes, validation CEL, defauts
dans le CRD (A1-A5, A7). Schema d'evenement de securite et page /events (7).
Drain OTLP v1 en gRPC avec tampon et evenement de test (D1, D3, D5). gRPC et TCP
simple dans EdgeSite (F1, F3). JA4 dans le journal (C1).
Phase 2, trois semaines, ce qui le rend vendable Bus Iggy derriere une interface, avec mesure face a NATS (E1-E6). JA4H calcule maison, reputation d'empreinte partagee (C2, C6). Drains par organisation avec choix des champs et redaction (D2, D4, D7). Analyse par dimension dans la console (G1). Passe-plat TLS et UDP limite (F4, F6).
Phase 3, un mois, ce qui le rend solide Rollout par vagues (A10), deux replicas et base en HA (A9, H1), archivage froid (D8), protection de compte (B5), simulateur de regles (B9), exercice d'attaque (H7), marque blanche (I2).
Ce qu'il ne faut pas faire tout de suite Un langage de politique maison (Coraza et les presets suffisent), un modele de machine learning au bord (aucune donnee, aucun gain demontre), du multi-region avant l'agent de distribution, un bus avant d'avoir mesure le volume reel.
10. Les trois decisions a prendre¶
- Licence JA4+ : payer l'OEM a FoxIO, ou se limiter a JA4 (BSD) et a nos calculs. A trancher avant la premiere vente, pas apres.
- Bus : Iggy si la mesure tient la charge, sinon NATS JetStream. Le choix se fait sur un banc d'essai, pas sur une preference.
- L4 : couvrir TCP et gRPC vite, UDP plus tard, et toujours dire au client ce que le WAF ne voit pas.