- En tant que protocole de proxy transmettant les requêtes par socket à des backends de longue durée de vie, il peut être adopté presque sans modifier la structure existante des gestionnaires HTTP
- Le reverse proxy HTTP/1.1 reste propice à des divergences d’interprétation des frontières de message selon les implémentations, ce qui peut continuer à engendrer de graves problèmes de sécurité comme le desync et le request smuggling
- FastCGI fournit depuis 1996 un framing de message clair et sépare structurellement les en-têtes du client des informations de confiance ajoutées par le proxy
- Dans Go,
net/http/fcgirenseigneREMOTE_ADDRdansRequest.RemoteAddret reflète aussi l’usage de HTTPS dansRequest.TLS, ce qui permet de gérer la transmission d’informations de confiance sans middleware supplémentaire - Il a des limites — absence de prise en charge de WebSockets, écosystème d’outils faible, débit plus faible sur certaines charges — mais s’il n’y a pas besoin de WebSockets et que les performances sont suffisantes, cela reste une option pratique
Positionnement et mode d’adoption de FastCGI
- FastCGI ne sert pas uniquement à exécuter un processus par fichier ; il peut aussi être utilisé comme protocole proxy-backend envoyant les requêtes via TCP ou socket UNIX à des démons persistants
- En Go, il suffit en pratique d’importer le paquet
net/http/fcgiet de remplacerhttp.Serveparfcgi.Serve- Les handlers existants continuent d’utiliser
http.ResponseWriterethttp.Request - Le reste de la structure de l’application reste inchangé
- Les handlers existants continuent d’utiliser
- Les principaux proxies comme Apache, Caddy, nginx et HAProxy prennent en charge les backends FastCGI, avec une configuration relativement simple
Problèmes de parsing quand HTTP est utilisé comme protocole backend
- Le reverse proxy HTTP ressemble à un véritable champ de mines sécuritaire, et des problèmes comme la vulnérabilité de desync du proxy média de Discord, permettant d’entrevoir des pièces jointes privées, continuent d’apparaître
- HTTP/1.1 semble à première vue être un protocole texte simple, mais il existe trop de façons d’exprimer un même message et trop de cas particuliers, ce qui favorise des interprétations différentes selon les implémentations
- Le plus gros problème est que les messages HTTP n’ont pas de framing explicite
- La fin d’un message est décrite par le message lui-même de plusieurs manières
- Différentes implémentations peuvent interpréter différemment l’endroit où un message se termine et où commence le suivant
- Ces divergences sont à la base des HTTP desync attacks ou du request smuggling, en faisant comprendre différemment les frontières de message au reverse proxy et au backend, avec à la clé de graves problèmes de sécurité
- Corriger en continu les différences entre parseurs a peu de chances d’être une solution de fond
- James Kettle continue à découvrir de nouveaux types d’attaques
- Après avoir trouvé d’autres cas l’an dernier, il est même allé jusqu’à parler de "HTTP/1.1 must die"
Gestion des frontières de message dans FastCGI et HTTP/2
- HTTP/2, s’il est utilisé de manière cohérente entre le proxy et le backend, peut résoudre les problèmes de desync en clarifiant les frontières de message
- FastCGI fournit cette séparation nette depuis 1996, avec un protocole plus simple
- nginx prend en charge les backends FastCGI depuis sa première version, mais la prise en charge des backends HTTP/2 n’a été ajoutée qu’à la fin de 2025
- Côté Apache, la prise en charge backend de HTTP/2 reste encore à l’état "experimental"
Problème des en-têtes non fiables et séparation apportée par FastCGI
- Le problème ne se limite pas au desync : HTTP manque aussi d’un moyen robuste de transporter des données que le proxy doit transmettre de façon fiable, comme la véritable IP du client, le nom d’utilisateur authentifié par le proxy, ou les informations de certificat client en mTLS
- En pratique, ces informations sont placées dans des en-têtes HTTP, mais il n’existe aucune séparation structurelle entre les données de confiance ajoutées par le proxy et les en-têtes non fiables envoyés par le client
- Des en-têtes comme
X-Real-IPsont souvent utilisés pour transmettre l’IP réelle du client, mais pour être sûr, le proxy doit d’abord supprimer complètement tout en-tête existant correspondant, y compris les variantes de casse, avant de le réinjecter - Cette méthode évolue sur un terrain extrêmement dangereux, avec de nombreux chemins par lesquels le backend peut finir par faire confiance à des données injectées par un attaquant
- Le proxy ne doit pas seulement supprimer
X-Real-IP, mais tout en-tête susceptible de servir à cette fin - Par exemple, le middleware Chi vérifie d’abord
True-Client-IPpour déterminer l’IP réelle du client, et n’utiliseX-Real-IPqu’en son absence- Même si le proxy gère correctement
X-Real-IP, un attaquant peut poser problème en envoyantTrue-Client-IP
- Même si le proxy gère correctement
- FastCGI distingue les en-têtes du client et les informations ajoutées par le proxy par séparation de domaines
- Les deux sont transmis comme des listes de paramètres clé/valeur, mais les noms d’en-têtes HTTP reçoivent le préfixe
HTTP_ - Ainsi, un en-tête envoyé par le client ne peut pas être interprété structurellement comme une donnée de confiance du proxy
- Les deux sont transmis comme des listes de paramètres clé/valeur, mais les noms d’en-têtes HTTP reçoivent le préfixe
Gestion des informations de confiance FastCGI dans Go
- FastCGI définit des paramètres standard comme
REMOTE_ADDRpour transmettre l’IP réelle du client - Dans Go,
net/http/fcgirenseigne automatiquement cette valeur danshttp.Request.RemoteAddr, ce qui fonctionne sans middleware supplémentaire - Le proxy peut aussi transmettre, via des paramètres non standard, des informations comme l’usage de HTTPS, la suite de chiffrement TLS négociée ou le certificat client
- Go définit automatiquement le champ
TLSdeRequestsur une valeur non nulle lorsqu’une requête utilise HTTPS- Même vide, cela reste utile pour vérifier l’obligation d’HTTPS
fcgi.ProcessEnvpermet d’accéder à l’ensemble complet des paramètres de confiance envoyés par le proxy
Pourquoi l’adoption reste lente et quelles sont les limites réelles
- Si FastCGI est meilleur, pourquoi n’est-il pas plus largement utilisé ? Il semble que l’image datée de son nom et le manque de prise de conscience des problèmes de sécurité du reverse proxy HTTP jouent tous deux un rôle
- Watchfire traitait déjà des attaques de desync en 2005 et avertissait qu’elles seraient difficiles à résoudre, mais ces attaques sont restées largement ignorées pendant plus de dix ans
- FastCGI reste encore utilisable en pratique aujourd’hui, et SSLMate l’utilise en production depuis plus de dix ans
- Cela dit, en tant que technologie ancienne, il a aussi ses faiblesses
- Il n’a pas été mis à jour pour prendre en charge WebSockets
- Son écosystème d’outils est limité
- Par exemple, curl prend en charge FTP, Gopher et SMTP, mais ne peut pas envoyer de requêtes FastCGI
- Lors de benchmarks d’un serveur FastCGI Go derrière plusieurs reverse proxies, certaines charges ont montré un débit inférieur à HTTP/1.1 ou HTTP/2
- Cela semble moins relever d’une limite intrinsèque du protocole que d’un chemin de code FastCGI moins optimisé que celui de HTTP
Verdict final
- S’il n’y a pas besoin de WebSockets et que les performances actuelles sont suffisantes, FastCGI reste une option valable
- Même si un goulot d’étranglement apparaît, il vaut mieux ajouter du matériel que subir la complexité et le cauchemar sécuritaire du reverse proxy HTTP
Aucun commentaire pour le moment.