Résumé

  • La requête reçue du client et celle transmise à l’origine n’ont pas nécessairement la même taille : le proxy ajoute les champs portant le certificat et, selon sa configuration, la chaîne de validation.
  • La taille du certificat binaire, celle des champs textuels après décompression HTTP et le coût sur le réseau ou dans une table de compression ne sont pas des budgets interchangeables.
  • Une marge doit être prévue pour les ajouts. Ni une valeur annoncée par un pair, ni la capacité d’un analyseur, ni une bonne compression ne garantissent l’acceptation de la requête complète.

Qui a consommé la place restante ?

Imaginons un client dont la requête tient dans l’enveloppe acceptée par un proxy. La connexion TLS mutuellement authentifiée a été établie. Le proxy joint ensuite le certificat client à la requête qu’il envoie à l’application. Si l’ensemble dépasse ce que cette application veut recevoir, la difficulté apparaît après l’envoi du client, au moment où le message est enrichi.

Cette situation est une construction explicative, pas un incident observé ni un essai exécuté. Elle montre néanmoins pourquoi demander seulement au client de réduire ses en-têtes peut manquer une partie du problème. Les octets ajoutés proviennent d’un engagement du proxy envers le serveur d’origine. Le participant qui a respecté une limite en amont ne maîtrise pas forcément cette augmentation en aval.

RFC9440, publié en juillet 2023 dans la catégorie Informational de l’IETF, codifie une pratique de transfert de certificats afin de rendre les composants indépendants plus faciles à faire fonctionner ensemble. Ce n’est pas une spécification de la filière Internet Standards Track. Le document fixe une représentation prévisible ; il ne certifie ni la capacité d’une infrastructure réelle ni un gain de performances.

Le mécanisme vise un mandataire inverse qui termine la connexion TLS du client et transmet à l’origine les informations de son certificat. Les champs décrivent le certificat du client initial, pas celui d’un éventuel dernier relais interne. La poignée de main et les champs HTTP restent deux étapes distinctes du même déploiement logique. La présente analyse porte sur la place nécessaire pour faire passer les informations de l’une à l’autre.

La confiance dans le chemin est indispensable, mais ce n’est pas une réponse à la question de capacité. Un trajet correctement protégé peut conduire à un récepteur dont l’enveloppe de traitement est insuffisante. Ajouter des données authentiquement obtenues ne rend pas gratuites leur sérialisation, leur transmission et leur réception. Il faut savoir à qui appartient chaque contrainte.

Décompter sans changer d’unité

Client-Cert porte le certificat final, encodé en DER, sous forme de Byte Sequence de Structured Fields. La valeur textuelle utilise le base64 entre deux caractères deux-points. Les retours à la ligne et les espaces ne font pas partie de cette représentation. Le proxy ne transporte donc pas simplement le tableau binaire tel quel dans un champ HTTP.

Un premier compte mesure l’objet DER. Un deuxième mesure la valeur sérialisée, puis les noms et valeurs de tous les champs reçus. L’expansion du base64, les délimiteurs et la syntaxe d’une éventuelle liste y ont leur place. Calculer cette transformation relève de l’encodage ; cela ne permet pas de déduire un seuil universel que chaque application serait tenue d’accepter.

Un troisième compte concerne la représentation comprimée sur le réseau. HPACK ou QPACK peuvent représenter une valeur en s’appuyant sur un état partagé plutôt qu’en retransmettant tout son texte. Mais le décodeur HTTP restitue des champs textuels : la valeur est encore du base64 à cette étape. Le décodage binaire du certificat intervient sur un autre plan. Confondre ces deux opérations de décodage sous-estime ce que compte une limite de section de champs.

Enfin, l’espace occupé dans une table dynamique ne se confond pas avec le nombre d’octets transférés ni avec la taille admissible d’une requête. Une valeur réutilisée peut coûter peu sur le fil tout en restant volumineuse une fois restituée. Une valeur envoyée littéralement peut éviter une entrée persistante sans disparaître du message à traiter. Il n’existe pas de conversion automatique entre ces réussites.

Le vocabulaire importe ici davantage qu’une valeur unique de « taille maximale ». L’équipe des certificats peut parler du binaire ; celle du proxy, de la sérialisation ; celle du transport, du débit comprimé ; l’application, de sa limite de champs. Un accord utile commence par indiquer ce qui est compté, à quel endroit et pour quelle requête.

Une marge réservée au trajet, pas une soustraction magique

Si le proxy reprend telle quelle la capacité annoncée par son aval, le client peut utiliser l’enveloppe entière avant que les ajouts n’interviennent. La difficulté ne vient alors pas d’un certificat « trop gros » dans l’absolu. Elle vient de l’absence de place réservée à une transformation prévue par le déploiement.

RFC9440 conseille aux intermédiaires qui annoncent une taille maximale d’en-têtes de tenir compte de leurs ajouts et de présenter aux clients une valeur suffisamment inférieure. Cette recommandation ne donne pas une constante à soustraire partout. Elle n’ajoute pas non plus une nouvelle obligation normative universelle. Le supplément dépend des données réellement jointes et du récepteur effectivement choisi.

Un budget bilatéral devrait donc préciser les ajouts prévus, l’unité de comptage et les conditions susceptibles de les faire varier. Une chaîne de validation différente peut changer le volume sans changer la réussite de l’authentification. Un autre trajet peut aboutir à une application qui applique sa propre limite. Ce sont des possibilités à examiner, non des migrations constatées dans cet article.

Ce budget doit aussi couvrir les autres champs de la requête. Le certificat n’arrive pas dans un espace vide : il partage l’enveloppe avec ce que le client a envoyé et avec les autres éléments éventuellement ajoutés. Démontrer qu’une valeur isolée est analysable ne démontre pas que son assemblage avec le reste du message reste admissible.

Une chaîne facultative n’est pas une donnée que l’on peut faire disparaître

Les deux champs de RFC9440 n’ont pas la même forme. Client-Cert est réservé aux requêtes et ne peut contenir une liste ni apparaître plusieurs fois. Il porte le certificat final. Client-Cert-Chain, facultatif, est une liste de Byte Sequences dans l’ordre des certificats TLS ; il ne répète pas ce certificat final et ne doit pas apparaître sans le premier champ.

Le caractère facultatif décrit un choix de configuration. Il ne prouve pas qu’une application ayant prévu de recevoir la chaîne peut continuer à fonctionner avec la même signification si elle ne la reçoit plus. Économiser des octets peut être un résultat mesurable ; préserver le contrat applicatif est une question différente.

Le RFC permet d’omettre la racine si l’origine destinataire est connue pour posséder l’ancre de confiance ainsi retirée. Cette condition est plus précise qu’un souhait de réduire la taille. Elle ne permet pas d’enlever arbitrairement les éléments que l’application attend parce que le message approche d’une limite. La possession d’une ancre ne se déduit pas d’un budget de réception.

Une liste de chaîne peut aussi être répartie entre plusieurs occurrences du champ, ce qui peut être avantageux pour la compression. Mais les comptes de section de champs peuvent facturer chaque ligne avec son nom et son coût fixe. La représentation favorable à un mécanisme n’est pas nécessairement la moins coûteuse pour l’autre. Cette opposition mérite un choix explicite, pas une règle de regroupement décidée sans connaître le compteur utilisé.

Les paramètres annoncent une enveloppe, pas une promesse générale

HTTP/2 emploie SETTINGS_MAX_HEADER_LIST_SIZE. RFC9113 définit ce paramètre indicatif à partir des longueurs non comprimées des noms et valeurs, auxquelles s’ajoutent 32 octets par ligne. Le récepteur peut imposer une limite inférieure pour une requête donnée. La valeur initiale sans limite ne constitue pas une mesure de la capacité d’une application ou d’une route.

HTTP/3 emploie SETTINGS_MAX_FIELD_SECTION_SIZE. Dans RFC9114, le calcul porte également sur les noms et valeurs non comprimés, avec 32 octets par champ. Le pair qui reçoit le paramètre devrait éviter de dépasser la taille indiquée. Le RFC souligne toutefois que les intermédiaires peuvent appliquer chacun leur propre limite. Rester sous une annonce ne garantit pas la réception à l’autre extrémité du trajet.

Il serait donc erroné de prendre un petit bloc comprimé comme preuve de conformité au budget de champs. Le texte restitué par la compression peut être plus grand, et il reste à comparer ce texte au seuil pertinent. Il serait tout aussi erroné de renommer le paramètre HTTP/2 avec le nom du paramètre HTTP/3 : ils ont des noms distincts et doivent être lus dans leur contexte.

Structured Fields ajoute un autre seuil, d’une autre nature. RFC8941 et son successeur RFC9651 exigent que les analyseurs de Byte Sequences prennent en charge au moins 16 384 octets après décodage binaire. Cette capacité du type de données n’oblige pas le serveur HTTP à accepter une requête complète contenant un tel objet. Elle ne fournit pas davantage un budget textuel, puisque le base64 et les autres champs restent à compter.

Il peut donc être cohérent de respecter la capacité exigée de l’analyseur et de refuser un message au-delà d’une enveloppe opérationnelle plus étroite. L’inverse ne permet aucune conclusion de confiance : un grand budget ne valide ni le certificat ni l’autorisation demandée. Chaque affirmation a son objet et sa portée.

Le rendement de la compression se paie ailleurs

RFC9440 décrit un cas conditionnel : plusieurs clients dont les requêtes sont multiplexées sur une connexion proxy-origine capable de comprimer les champs. Des valeurs de certificat volumineuses et variables peuvent dégrader sensiblement le rendement. Ce constat du texte n’est pas un résultat mesuré sur une flotte et ne signifie pas que chaque déploiement souffre de cette difficulté.

Le RFC évoque l’augmentation de la table dynamique du côté de l’origine. Il indique aussi qu’un proxy jugeant la table insuffisante pourrait trouver avantageux de transmettre systématiquement la valeur comme littéral plutôt que d’y créer une entrée. Ces possibilités déplacent le compromis entre état conservé et représentation transmise ; aucune n’est la configuration gagnante pour tous les usages.

HPACK, défini par RFC7541, compte une entrée à partir des longueurs du nom et de la valeur avant codage Huffman, plus 32 octets. Le protocole environnant limite la capacité autorisée, et l’encodeur peut en utiliser moins. Augmenter cette capacité offre davantage de place à l’état de compression, pas davantage de place dans le budget que l’application accepte pour une requête.

Avec QPACK, RFC9204 borne la capacité maximale de la table dynamique par la valeur SETTINGS_QPACK_MAX_TABLE_CAPACITY envoyée par le décodeur. Une capacité maximale nulle interdit les insertions. Ce réglage n’est pas SETTINGS_MAX_FIELD_SECTION_SIZE. La présence des deux paramètres dans un même transport ne les transforme pas en un seul levier ; il n’est pas affirmé ici que QPACK bloquerait nécessairement les requêtes avec certificats.

Le choix dépend de la répétition réelle des valeurs. Un certificat récurrent et une succession de certificats différents ne promettent pas le même réemploi. Le responsable du transport peut chercher à réduire les octets transmis ou l’état retenu, tandis que le responsable applicatif protège sa capacité de traitement. Ces objectifs peuvent être légitimes sans être équivalents.

Refuser un volume ne doit pas modifier discrètement une identité

RFC6585 définit 431 pour une requête dont les champs, pris ensemble ou isolément, dépassent ce que le serveur veut traiter. Une nouvelle tentative est possible après réduction ; lorsqu’un champ est responsable, la représentation devrait l’indiquer. Le code n’est cependant pas obligatoire, notamment lorsque le serveur préfère interrompre des connexions sous attaque. Le mécanisme ne garantit donc pas une réponse 431 à chaque dépassement.

RFC9110 demande une réponse appropriée de classe 4xx pour les champs de requête trop volumineux et met en garde contre leur simple ignorance, qui augmente l’exposition à la contrebande de requêtes. Faire disparaître le certificat n’est pas une manière neutre de résoudre le problème. On pourrait obtenir un message plus petit tout en donnant à l’application une entrée différente de celle qu’elle attendait.

L’absence de certificat peut être prévue et légitime, par exemple dans un autre arrangement d’authentification. Il ne s’agit pas d’exiger partout un refus en son absence. Il s’agit de ne pas laisser un incident de capacité définir cet arrangement à la place de ses responsables. Des tentatives identiques répétées ne créent pas de marge et ne clarifient pas cette sémantique.

La reprise de session pose un choix voisin. Certains mécanismes TLS ne conservent pas les informations de certificat lors d’une reprise. RFC9440 recommande aux implémentations incapables de produire des champs cohérents soit de désactiver la reprise pour ces connexions, soit d’omettre dès le départ un champ qui pourrait manquer ensuite. C’est une alternative conditionnelle de conception, pas une instruction pour modifier un service actuel ni l’affirmation que toute reprise perd le certificat.

Il reste une autre séparation : les tables HPACK/QPACK ne sont pas des caches de réponses. Quand Client-Cert sert à sélectionner une réponse, RFC9440 impose soit de rendre celle-ci non stockable, soit de réserver son réemploi aux requêtes ayant la même valeur par Vary: Client-Cert. Un proxy de terminaison voyant les champs de certificat dans Vary devrait remplacer cette valeur par * pour empêcher la mise en cache par l’agent utilisateur. Les réponses 431, elles, ne doivent pas être stockées en cache. Une table dynamique agrandie ne satisfait aucune de ces règles à elle seule.

Le chemin de confiance reste un prérequis distinct : les champs reçus de sources non autorisées doivent être assainis et le trajet interne protégé. Le fait de tenir dans une limite ne dispense pas de ces obligations. La capacité complète l’arrangement de déploiement ; elle ne l’authentifie pas.

Sources et portée

Les situations présentées sont hypothétiques et non exécutées. Cette recherche repose sur les spécifications, pas sur une télémétrie de production. Elle ne fournit ni défaut supposé d’un fournisseur, ni seuil universel, ni incident observé, ni avantage chiffré. Les recommandations opérationnelles sont des interprétations éditoriales, séparées des exigences explicites des textes.