Résumé

  • Le server_name TLS est un nom DNS fourni par le client dans ClientHello afin d’orienter le choix d’un certificat, d’un contexte ou d’une route. Il n’authentifie pas celui qui le fournit.
  • La référence d’identité du service, Host ou :authority, le SNI amont, l’état ECH et l’autorisation applicative appartiennent à des décisions distinctes, même lorsqu’elles manipulent la même chaîne.

Trois noms identiques, trois faits différents

Le répartiteur avait reçu un SNI correspondant au locataire A. Le rappel OpenSSL avait chargé le bon SSL_CTX, puis le serveur avait présenté le certificat attendu. L’intégration a conclu que la connexion « appartenait » au locataire A et lui a ouvert une route administrative.

N’importe quel client pouvait pourtant écrire ce nom dans son ClientHello. Le certificat sélectionné servait à permettre au client d’authentifier le serveur ; il ne disait rien sur l’identité du client. L’étiquette de politique ne faisait que recopier une donnée de routage.

L’incident ne révèle donc pas une primitive TLS cassée. Il montre un déplacement d’autorité : une entrée utile pour réduire un ensemble de configurations candidates a été traitée comme une qualité du demandeur.

Ce que la syntaxe garantit — et ce qu’elle ignore

RFC 6066 place une ServerNameList dans ClientHello. Le type normalisé host_name transporte un nom d’hôte DNS en ASCII ; les adresses IPv4 et IPv6 littérales en sont exclues, et un type ne doit apparaître qu’une fois dans la liste.

Ces contraintes empêchent certaines ambiguïtés de format. Elles ne prouvent ni résolution DNS, ni maîtrise de zone, ni possession de clé, ni contrat avec un locataire. Un outil peut joindre directement une adresse et annoncer un autre nom parfaitement valide. La provenance de la valeur reste le client.

Un serveur peut interrompre avec l’alerte fatale unrecognized_name s’il refuse un nom compris. Il peut également continuer selon une politique de repli. L’existence d’une table SNI ne permet donc pas de deviner le comportement : il faut tester le nom absent, inconnu et invalide, puis identifier le contexte par défaut réellement choisi.

Un transcript intègre ne transforme pas une affirmation en titre

En TLS 1.3, ClientHello participe au transcript que Finished authentifie. Après une poignée de main valide, un intermédiaire n’a pas pu modifier silencieusement le SNI ordinaire entre les deux extrémités.

Cela confirme l’intégrité de la valeur fournie, non le droit de la fournir. Le serveur sait que ce client a demandé ce nom pendant cette poignée de main. Il n’apprend pas que le client possède ce nom ou représente son opérateur.

Sans certificat client, PSK d’identité ou authentification applicative, une poignée de main serveur parfaitement valide laisse le client anonyme. Le certificat va dans l’autre sens : il présente l’identité du service au vérificateur.

Les schémas de données doivent refléter cette asymétrie. client_requested_server_name est un fait. verified_tenant est déjà une conclusion, et elle exige une autre preuve.

Présenter le bon certificat n’est pas le vérifier

Le SNI aide le serveur à choisir une credential. Le client décide séparément si cette credential authentifie le service visé.

RFC 9525 impose de construire les identifiants de référence acceptables indépendamment des identifiants présentés dans le certificat. Le client compare ensuite les deux ensembles et applique aussi sa politique de chaîne, de validité et de révocation. Le choix réalisé par le serveur ne remplace aucune de ces étapes.

La documentation OpenSSL matérialise la séparation : définir le SNI avec SSL_set_tlsext_host_name() doit s’accompagner de la configuration du nom DNS attendu pour la validation. Un client qui ne fait que la première opération améliore la sélection côté serveur, mais n’établit pas nécessairement l’identité côté client.

Un certificat multi-SAN peut être valide pour plusieurs noms. Il rend la cryptographie plus partageable, pas les autorisations. Deux locataires couverts par la même chaîne restent deux domaines de décision.

Le requête HTTP apporte sa propre autorité

Une fois TLS terminé, HTTP transmet la cible applicative. HTTP/1.1 emploie Host; HTTP/2 et HTTP/3 s’appuient souvent sur :authority. RFC 9110 qualifie cette information de critique pour le routage et en fait une surface d’attaque explicite.

Dans le cas habituel, le client dérive SNI et autorité HTTP d’une même URI. Cette habitude produit souvent deux chaînes égales. Elle ne crée aucun lien normatif qui autoriserait la première à décider pour la seconde.

La divergence peut résulter de la réutilisation de connexion, d’un proxy, d’un test, d’une erreur ou d’une attaque. Le service doit nommer sa politique : refus strict, ensemble partagé documenté, ou réponse 421 lorsque la connexion ne convient pas à l’origine demandée. Laisser le premier SNI gouverner toutes les requêtes ultérieures transforme un choix précoce en mandat permanent.

Même un accord exact entre les deux noms ne remplace toujours pas l’identité du client. Il confirme au mieux la cohérence de deux intentions de routage.

La terminaison TLS coupe la chaîne de preuve

Un proxy qui termine TLS possède une connexion aval avec son ClientHello et une connexion amont entièrement nouvelle. Les SNI, certificats, identifiants de référence, transcripts et erreurs ne sont pas hérités.

Le SNI amont peut être fixe, venir du nom de l’hôte cible, de l’autorité HTTP aval ou d’une correspondance contrôlée. Envoy distingue ces choix, ainsi que la validation SAN fondée sur le SNI amont de celle fondée sur l’autorité de la requête. La configuration doit annoncer la source choisie et la trace doit prouver qu’elle a été utilisée.

Dans un relais opaque, la preuve est encore plus étroite. Le module ssl_preread de NGINX peut lire le SNI et aiguiller les octets TLS sans mettre fin à la poignée de main. Il prouve une extraction et une route, jamais la validation du certificat final ni l’achèvement du handshake.

Un champ unique appelé sni efface ces distinctions. Il faut au moins l’identité de chaque connexion, le rôle, la source du nom, le contexte sélectionné et le vérificateur concerné.

ECH introduit un nom public et un nom intérieur

Encrypted Client Hello place les propriétés sensibles dans ClientHelloInner. ClientHelloOuter contient normalement le nom public qui permet d’atteindre le serveur frontal et de soutenir la procédure de reprise.

Si ECH est accepté, le traitement TLS se poursuit à partir de l’inner authentifié. En cas de rejet, une connexion authentifiée pour le nom public peut seulement servir à obtenir une nouvelle configuration. RFC 9849 interdit de la présenter à l’application comme une connexion réussie à l’origine.

Le nom extérieur démontre donc parfaitement la nature limitée du SNI : il peut conduire le trafic au bon frontal tout en n’étant volontairement pas l’origine. Une métrique qui ne conserve que « le SNI » mélange nom public, nom intérieur accepté et ClientHello ordinaire.

L’observabilité doit joindre le statut ECH, le rôle du point d’observation et la source du nom. Elle doit aussi éviter de copier largement le nom intérieur, faute de quoi la télémétrie reconstituerait la fuite que le protocole cherche à réduire.

Prouver la limite par l’exécution

Le premier test soumet le nom du locataire le plus sensible sans aucune credential client. La sélection du certificat peut réussir ; le principal doit rester anonyme et l’action protégée doit échouer.

Viennent ensuite l’absence de SNI, le nom inconnu, le repli par défaut et un couple SNI/autorité HTTP appartenant à deux locataires. Un certificat couvrant les deux noms permet de vérifier que la réussite cryptographique ne dissimule pas la faute d’autorisation.

Pour un proxy, imposer un SNI amont différent et conserver deux résultats de validation. Pour un relais opaque, interdire toute assertion de certificat validé ou de poignée de main terminée. Pour ECH, parcourir acceptation, rejet avec reprise et absence d’ECH en identifiant chaque vue.

Un rappel installé et une table bien formée sont des capacités. Seule la réaction du chemin exécuté à ces cas hostiles constitue la preuve.