Cette version marque une étape : la mécanique sous-jacente est désormais prête à accueillir les fonctionnalités produit que nous voulons bâtir au-dessus. Plutôt qu’une liste de correctifs, nous avons regroupé le travail en six thèmes ; pour chacun, nous disons deux choses — ce qui a été livré, et ce que cela rend possible, pour celles et ceux qui font tourner leurs applications sur la plateforme comme pour les opérateurs qui exécutent Sōzu sur leur propre infrastructure.
1. Un multiplexer HTTP/2 réécrit intégralement
La pile HTTP/1 de Sōzu avait déjà été réécrite autour de kawa, notre format pivot : une représentation interne du message HTTP indépendante de sa version, dans le même esprit que le format HTX de HAProxy. Le multiplexer HTTP/2 en est le prolongement naturel — il étend kawa avec la gestion des sessions et le multiplexing des streams.
Il couvre l’intégralité de la matrice des protocoles (H1↔H1, H1↔H2, H2↔H1, H2↔H2), avec un état de stream partagé, la compression HPACK assurée par loona-hpack, le pooling des connexions HTTP/2 vers les backends, la priorisation des streams selon RFC 9218 Extensible Priorities, et la négociation ALPN par listener, afin que chaque connexion TLS aboutisse sur le bon chemin de code. Environ 181 tests end-to-end et deux cibles de fuzzing (cargo-fuzz) maintiennent le parser et le décodeur HPACK dans le droit chemin — dont des garde-fous de régression qui vérifient octet pour octet l’intégrité des réponses volumineuses sur un trajet « backend HTTP/1 → frontend HTTP/2 », précisément la frontière où se cachent les bugs de readiness en mode edge-triggered d’epoll.
Pour les clients Clever Cloud, l’incidence concrète est simple : chaque application servie par la plateforme parle désormais HTTP/2 par défaut, côté frontend — aucun opt-in, aucune modification de code, aucune configuration. L’activation du HTTP/2 jusqu’au backend reste un choix par cluster — un cluster, dans le modèle de Sōzu, étant l’une de vos applications ; activée de bout en bout, elle débloque notamment gRPC sur toute la chaîne. Les pages s’affichent en moins de connexions TCP ; les navigateurs peuvent mutualiser les requêtes entre les hôtes qui partagent un certificat (nous honorons le SAN coalescing décrit dans la RFC 7540 §9.1.1 : lorsque le certificat, l’autorité d’origine et les conditions de connexion s’y prêtent, Firefox et Chrome peuvent réutiliser une seule connexion vers vos cdn.example.com et assets.example.com au lieu d’en ouvrir plusieurs en parallèle). Il s’agit, au meilleur sens du terme, d’une mise à niveau silencieuse de la plateforme.
C’est aussi le prérequis structurel pour la suite — HTTP/3 sur QUIC et des fondations de streaming plus solides à l’edge. La réécriture du multiplexer est la pièce de la roadmap qui devait advenir en premier.
2. La sécurité pour socle, non comme option
La seconde moitié de la réécriture HTTP/2 est celle dont personne ne réclame l’existence tant qu’elle ne fait pas défaut : la résistance aux floods et aux attaques par déni de service. Sōzu 2.0 embarque des mitigations natives pour les vulnérabilités CVE-2023-44487 (Rapid Reset), CVE-2024-27316 (CONTINUATION flood), CVE-2025-8671 (MadeYouReset), ainsi que pour la famille PING / SETTINGS / empty-DATA des CVE-2019-9512/CVE-2019-9515/CVE-2019-9518. Chaque mitigation expose un counter dédié — douze métriques sous h2.flood.violation.* — afin qu’un SIEM puisse mesurer en fenêtre glissante le taux de déclenchement, sans avoir à parser les logs. Dix-sept motifs de rejet HPACK sont exposés selon le même principe ; il s’agit du premier signal observable côté opérateur pour les tentatives de request smuggling contre la pile HTTP/2.
Le reste du travail de sécurité se déploie à travers le proxy : un plafond de connexions par couple (cluster, IP source) assorti d’une réponse 429 Too Many Requests ; une éviction optionnelle des sessions les plus anciennes lorsque l’accept queue sature ; un durcissement du command channel, du parser HTTP/1, du pattern-trie router (fermeture d’un contournement de routing via regex non ancrées) et du wildcard matcher ; un assainissement du pipeline d’audit contre les séquences Trojan-Source et le SIEM column-smuggling ; et une rotation à chaud des certificats TLS qui ne laisse jamais tomber le certificat fonctionnel en cas d’échec, quand bien même le nouveau serait malformé. Quatre security advisories de dépendances purgées au cours de la même fenêtre.
Chaque mutation privilégiée atterrit désormais dans un journal d’audit structuré : chaque action du plan de contrôle est consignée sous la forme d’une ligne Command(verb=…, actor_uid=…, actor_user=…, result=…) — qui a fait quoi, depuis où, et avec quel résultat. Deux sinks dédiés l’exportent : audit_logs_target pour le flux lisible, et audit_logs_json_target pour un objet JSON à schéma stable par ligne, de sorte que la piste se déverse directement dans un SIEM (Wazuh, Elastic, Loki, Splunk) sans parser sur mesure — dans un format pensé pour PCI-DSS 10.5.
Le cadrage produit est limpide : notre métier, c’est d’opérer la plateforme et de protéger vos applications dès que nous le pouvons. Lorsque la prochaine vulnérabilité HTTP/2 de cette classe paraît un vendredi à vingt-et-une heures, elle n’a pas à se traduire par un week-end de correctifs et de redéploiements sur des milliers d’applications : les attaques de cette classe sont largement absorbées ou atténuées au niveau du proxy, un counter s’incrémente sur un dashboard, et les applications continuent de servir leur trafic. Le « trust-by-default » n’est pas un slogan : c’est l’effet cumulé de dizaines de petits correctifs défensifs, livrés à la couche où la frontière de sécurité se joue véritablement.
3. De la visibilité à chaque couche
L’ajout le plus visible pour l’utilisateur en 2.0 est sozu top — une TUI opérateur (derrière le feature flag Cargo tui) qui offre une vue en temps réel, à la manière de btop ou htop, sur sept panes : Overview, Clusters, Backends, Listeners, H2, Certificates, Events. Palette accessible aux personnes daltoniennes, thèmes personnalisables : l’essentiel tient dans un terminal, sans dashboard externe.
Sous la TUI, la surface des métriques elle-même a été refondue. Le multiplexer expose des counters par type de frame et par code d’erreur RFC 9113, la télémétrie des handshakes TLS, des counters HTTP par status code, et de nouvelles gauges de cycle de vie du worker. L’access log gagne les champs TLS et de forwarding (version, cipher, SNI, ALPN, chaîne XFF), la propagation x_request_id de bout en bout, ainsi que les RTT client et serveur — de quoi corréler une requête d’un hop à l’autre.
Une nouvelle commande, SetMetricDetail, permet à un opérateur d’élever à la demande la cardinalité des métriques, via un lease à durée limitée qui expire : la production reste à faible cardinalité par défaut, et l’inspection fine devient une décision ponctuelle plutôt qu’une réécriture de configuration.
Pour Clever Cloud, c’est le socle du prochain chapitre de l’observabilité tournée vers le client — percentiles de latence par application, disponibilité par cluster, décomposition des handshakes TLS, request IDs traçables d’un hop à l’autre. Les métriques existent désormais au niveau du proxy. L’étape suivante consiste à les exposer dans la console Clever Cloud, à leur juste place, aux côtés des vues de build et de déploiement — afin qu’aucun APM externe ne soit nécessaire pour comprendre le trafic que votre application reçoit véritablement.
4. Des policies de trafic enfin actionnables d’un geste
Sōzu 2.0 refond l’intégralité de la surface des policies côté frontend (#1231) : HSTS typé (RFC 6797), configurable par listener et par frontend ; URL rewrite (host, path, port) avec propagation des regex captures depuis le routing trie vers les rewrite templates ; réécriture des headers de requête et de réponse par frontend — ajouter, modifier ou supprimer n’importe quel header (une valeur vide le supprime, parité avec le del-header de HAProxy), avec en complément l’injection de X-Real-IP au niveau listener et l’élision anti-spoofing des valeurs fournies par le client ; redirects HTTP 301 / 302 / 308 au travers d’une enum typée RedirectPolicy ; et l’authentification HTTP Basic par frontend, avec des credentials hashés en SHA-256 et une comparaison constant-time assurée par la crate subtle (le credential boundary est durci contre les side-channels temporels — la code review l’avait identifié).
C’est la partie de la release où l’opportunité produit est la plus saillante. Aujourd’hui, mener une migration de domaine propre sur une plateforme managée requiert typiquement soit un backend sachant rediriger, soit un service de redirection déployé en parallèle ; placer une URL de preview derrière un mot de passe requiert typiquement un add-on d’authentification. Avec Sōzu 2.0, ces usages deviennent des boutons sur le proxy. La plomberie existe ; ce qu’il reste à accomplir, c’est d’exposer ces boutons dans la console Clever Cloud — sous la forme d’une case à cocher sur un domaine, ou d’un toggle à clic unique pour les preview environments. C’est la surface no-code de contrôle du trafic que nous voulons construire ensuite.
5. L’exploitation comme bénéfice pour le client
Une réécriture de cette profondeur ne se livre sereinement que si la flotte demeure en mouvement en dessous. L’exploitation au quotidien a reçu une attention particulière en 2.0.
sozu listener {http,https,tcp} update est un nouveau patch verb field-masked qui ajuste à la volée les paramètres d’un listener modifiables sans recycler les sockets sous-jacents : seuils de flood HTTP/2, SNI binding, préférence ALPN, idle timeouts, HSTS, custom answers. Les mitigations CVE peuvent désormais être resserrées sous attaque sans recycler les sockets d’écoute. Les health checks actifs des backends s’exécutent à l’intérieur de la loop d’événements mio existante (aucun scheduler async, aucun thread supplémentaire), avec des sondes HTTP/1.1 et HTTP/2, des intervalles dotés d’un léger jitter, et un fail-open path qui achemine à travers les backends au statut Normal dont la retry policy l’autorise. L’intégration systemd (qui clôt #228) effectue enfin ce qu’il convient : des units Type=notify, un READY=1 envoyé seulement après la création des workers initiaux et le replay de l’état sauvegardé, un STOPPING=1 lors du graceful shutdown, un MAINPID=<nouveau> lors des hot upgrades.
Les releases elles-mêmes ont changé de forme. Pousser un tag produit désormais dix tarballs pré-compilés (trois cibles Linux croisées avec jusqu’à quatre crypto providers), signés keyless via sigstore (cosign + GitHub OIDC), accompagnés d’une attestation SLSA build provenance et d’un pointeur SOURCE.txt vers le code source correspondant satisfaisant l’AGPL §6 et la LGPL §4 — refermant ainsi l’écart noté dans #1089. Les fichiers fullchain.pem ACME se chargent à présent proprement, y compris lorsque le client a émis le leaf en tête de chaîne (Certbot, lego, acme.sh) ; une race condition vieille de six ans sur l’auto-restart des workers (#515) est corrigée par pinning de l’inode original au moyen de /proc/self/fd. Le verbe IPC LoadState demeure forward-compatible avec les clients sozu-command-lib 1.1.1, de sorte que l’écosystème d’intégrations ne se brise pas lors de l’upgrade.
À l’échelle de Clever Cloud, le coût d’un incident d’exploitation ne se mesure pas en tickets — il s’agit d’une latence qui s’accumule sur des milliers d’applications, et du temps d’ingénierie que nous devons à la construction de l’étape suivante. Sōzu 2.0 est le proxy qui se laisse exploiter en silence, et cette tranquillité est ce que les clients vivent comme de l’uptime. C’est également ce qui rend Sōzu crédible comme outil que l’on peut exécuter sur sa propre infrastructure : binaires signés, hot reloads, particularités ACME absorbées, intégration systemd menée correctement.
6. Une crypto prête pour demain
La pile TLS a reçu une refonte plus discrète, mais d’égale importance (#1191). Sōzu prend désormais en charge quatre crypto providers pluggables pour rustls : crypto-ring (par défaut), crypto-aws-lc-rs, crypto-openssl, et fips (qui implique aws-lc-rs en mode FIPS). Les quatre sont exercés par la CI, et la precedence chain fips > ring > aws-lc-rs > openssl résout le provider actif de manière déterministe lorsque plusieurs features sont activées simultanément.
Ce dont nous sommes le plus satisfaits, en revanche, est le groups_list par défaut : X25519MLKEM768 est désormais le groupe d’échange de clés en première préférence lorsque le provider le prend en charge. Il s’agit de l’hybride post-quantique en cours de normalisation à l’IETF (draft-ietf-tls-ecdhe-mlkem), déjà enregistré dans le registre TLS de l’IANA ; en pratique, cela signifie qu’un client uniquement compatible X25519 et un client post-quantum négocient l’un comme l’autre l’échange le plus robuste mutuellement pris en charge, sans aucune action de l’opérateur.
Lorsque la transition post-quantique deviendra une exigence réglementaire — selon un calendrier dont l’industrie débat encore — les fondations seront déjà en place sur Clever Cloud : tout client TLS 1.3 qui propose l’hybride le négocie dès aujourd’hui, sans action de l’opérateur. Nous avons effectué ce choix en silence, et nous l’avons inscrit par défaut.
Du reverse proxy à l’edge programmable
Sōzu a toujours été un load balancer d’infrastructure : bien au-delà du HTTP, il équilibre aussi du TCP brut, avec un chemin de forwarding zéro-copie via splice(2) sous Linux pour les listeners TCP. Avec la 2.0, il se rapproche d’une API gateway et devient le substrat d’un edge programmable — et « programmable » est le mot qui compte. Chaque capacité décrite ci-dessus (HTTP/2 par défaut, contrôles anti-abus, observabilité, policies de trafic, crypto agility, calme opérationnel) est un bouton. L’année qui vient de la roadmap Clever Cloud consiste à exposer ces boutons sous la forme de features produit : à travers la console, à travers l’API, à travers les workflows que vous utilisez déjà pour déployer vos applications.
Voilà ce que nous voulons dire lorsque nous affirmons que Sōzu 2.0 est un premier pas vers quelque chose de plus grand. La 2.0 n’est pas la destination — c’est la plateforme sur laquelle nous bâtissons désormais. Le HTTP/2 managé, partout, en constitue la première brique. La deuxième : une console permettant d’activer HSTS, de protéger par mot de passe un preview environment, ou de rediriger un domaine migré. L’aboutissement — un edge entièrement programmable, doté de policy primitives que vous composez — est ce vers quoi nous bâtissons au fil du prochain release cycle.
Deux chantiers sont déjà sur l’établi. D’abord, un volet load balancing UDP — dans l’esprit d’IPVS, mais avec le rechargement à chaud propre à Sōzu — assorti de health checks TCP pour valider la disponibilité des backends UDP ; de quoi ancrer un peu plus le rôle de load balancer d’infrastructure. Ensuite, des backends joignables en HTTPS, qui consolident la connectivité amont et ouvrent la voie à l’API gateway.
Sōzu est un projet open source publié sous AGPL-3.0 (la command library est diffusée sous LGPL-3.0). Les binaires de la version 2.0 sont signés via sigstore et embarquent une attestation SLSA ; si vous opérez votre propre edge, cette version vous appartient : à utiliser, à auditer, à étendre. Le code, l’issue tracker, et les conversations vivent à l’adresse github.com/sozu-proxy/sozu.
Nous remercions les contributeurs qui ont rendu cette release possible — ainsi que toutes celles et ceux qui exécutent Sōzu en production, dont les retours guident la suite.
Références
Standards et spécifications
- RFC 6797 — HTTP Strict Transport Security (HSTS). https://datatracker.ietf.org/doc/html/rfc6797
- RFC 7540 — Hypertext Transfer Protocol Version 2 (HTTP/2). Désormais obsolétée par la RFC 9113, mais le §9.1.1 sur le connection coalescing demeure la citation reprise par la RFC 9113. https://datatracker.ietf.org/doc/html/rfc7540
- RFC 9113 — HTTP/2 (en vigueur). §5 streams, §6 frames, §6.8 GOAWAY, §7 codes d’erreur, §8.1 sémantique HTTP. https://datatracker.ietf.org/doc/html/rfc9113
- RFC 9218 — Extensible Prioritization Scheme for HTTP. https://datatracker.ietf.org/doc/html/rfc9218
- draft-ietf-tls-ecdhe-mlkem — Hybrid key exchange in TLS 1.3 : X25519MLKEM768 (Internet-Draft IETF, enregistré à l’IANA ; l’hybride post-quantique que Sōzu privilégie par défaut). https://datatracker.ietf.org/doc/html/draft-ietf-tls-ecdhe-mlkem
CVE
- CVE-2019-9512 — HTTP/2 Ping Flood. https://nvd.nist.gov/vuln/detail/CVE-2019-9512
- CVE-2019-9515 — HTTP/2 Settings Flood. https://nvd.nist.gov/vuln/detail/CVE-2019-9515
- CVE-2019-9518 — HTTP/2 Empty Frames Flood. https://nvd.nist.gov/vuln/detail/CVE-2019-9518
- CVE-2021-42574 — Trojan Source (bidirectional override). https://nvd.nist.gov/vuln/detail/CVE-2021-42574
- CVE-2023-44487 — HTTP/2 Rapid Reset. https://nvd.nist.gov/vuln/detail/CVE-2023-44487
- CVE-2024-27316 — HTTP/2 CONTINUATION Flood. https://nvd.nist.gov/vuln/detail/CVE-2024-27316
- CVE-2025-8671 — MadeYouReset (HTTP/2). https://nvd.nist.gov/vuln/detail/CVE-2025-8671
Pour aller plus loin
- Cloudflare — HTTP/2 Rapid Reset: deconstructing the record-breaking attack. Le compte rendu canonique de la divulgation coordonnée d’octobre 2023, incluant la mécanique de l’attaque ainsi que le pic de 398 millions de rps capturé en direct. https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/
- HAProxy Technologies — HAProxy is Not Affected by the HTTP/2 Rapid Reset Attack (CVE-2023-44487). L’argument structurel de HAProxy quant à la raison pour laquelle son cycle de vie de stream absorbe naturellement le Rapid Reset ; un contraste utile face à l’approche par counters de flood retenue par Sōzu. https://www.haproxy.com/blog/haproxy-is-not-affected-by-the-http-2-rapid-reset-attack-cve-2023-44487
- Cloudflare blog — série Post-quantum. Couverture pluriannuelle assurée par Bas Westerbaan et ses collaborateurs sur l’échange de clés post-quantique et les groupes hybrides ; filiation de l’hybride X25519MLKEM768 que Sōzu négocie désormais par défaut. https://blog.cloudflare.com/tag/post-quantum/
- Cloudflare Learning Center — What is HSTS?. Primer accessible sur HSTS, la sémantique max-age / includeSubDomains / preload, et la politique de la HSTS preload list.