Comment détecter si un serveur utilise SNI pour HTTPS?

41

Je cherche un moyen simple de savoir si un serveur utilise l'extension SSL d'indication de nom de serveur pour son certificat HTTPS sur un site Web. Une méthode qui utilise un navigateur ou une ligne de commande Unix convient parfaitement.

Merci!

spookylukey
la source

Réponses:

20

SNI est lancé par le client, vous avez donc besoin d'un client qui le prend en charge. Sauf si vous êtes sur Windows XP, votre navigateur fera l'affaire. Si votre client vous permet de déboguer correctement les connexions SSL (malheureusement, même les commandes CLI gnutls / openssl ne le permettent pas), vous pouvez voir si le serveur renvoie un champ nom_serveur dans le hello étendu. Notez que l'absence de ce champ signifie uniquement que le serveur n'a pas utilisé le nom_serveur dans le hello du client pour faciliter la sélection d'un certificat, et non qu'il ne le prend pas en charge.

Donc, dans la pratique, le test le plus simple consiste simplement à essayer de se connecter. Pour cela, vous devez connaître deux noms qui correspondent à la même adresse IP et auxquels une connexion SSL peut être établie. Il est plus simple d'utiliser https, car il vous suffit ensuite de parcourir les deux noms et de voir si le certificat approprié vous est présenté.

Il y a trois résultats:

  • Vous obtenez un certificat générique (ou un avec subjectAltName) qui couvre les deux noms: vous n’apprenez rien
  • Vous obtenez le mauvais certificat pour au moins l'un d'entre eux: le serveur ne supporte pas SNI ou il a été mal configuré
  • Vous obtenez deux certificats différents, les deux pour le nom correct: SNI est pris en charge et correctement configuré.

Un test légèrement plus compliqué qui donnera plus d’informations est d’avoir Wireshark ouvert et de capturer lors de la navigation. Vous pouvez ensuite trouver les paquets pertinents en filtrant ssl.handshake. Les captures d'écran ci-dessous illustrent un exemple de couple client / serveur où SNI est pris en charge:

Bonjour client Bonjour serveur

Encore une fois, bien sûr, l'absence d'un champ nom_serveur dans le serveur Bonjour n'indique pas que SNI n'est pas pris en charge. Le nom de serveur fourni par le client n'a pas été utilisé pour décider du certificat à utiliser.

Dennis Kaarsemaker
la source
9
Dennis - pas d'accord sur openssl. Certains détails sont disponibles: openssl s_client -servername alice.sni.velox.ch -tlsextdebug -msg -connect alice.sni.velox.ch:443Quelques indications sur l’utilisation de SNI sont fournies lors du test Qualys SSL .
Deer Hunter
Ah, ça m'a échappé dans la page de manuel. Merci pour l'ajout.
Dennis Kaarsemaker
26

La ligne que vous recherchez probablement pour détecter la présence d'un en-tête d'extension d'indication de nom de serveur SSL / TLS est:

openssl s_client -servername www.SERVERNAME.com -tlsextdebug -connect www.YOURSERVER.com:443 2>/dev/null | grep "server name"

www.SERVERNAME.comest la valeur SNI que vous testez et www.YOURSERVER.comle nom de domaine ou l'adresse IP du serveur compatible TLS que vous testez.

Les utilisations de ligne de commande de openssll » s_client(voir les s_client (1) ) de se connecter au serveur à www.YOURSERVER.comsur le port 443. L' -tlsextdebugoption active la sortie de débogage de l'extension TLS. L' -servernameoption indique au s_clientprogramme de transmettre www.SERVERNAME.comla valeur du champ SNI dans le paquet ClientHello lors de l'établissement de la liaison TLS.

Enfin, 2>/dev/nullcache simplement la sortie stderr (qui peut être bruyante) et le | grep "server name"filtre de pipeline stdout pour afficher l’extension TLS appelée "nom du serveur" dans s_clientla sortie de débogage de l’extension TLS.

Si vous voyez une ligne de sortie telle que

TLS server extension "server name" (id=0), len=0

alors le serveur renvoie les informations d'en-tête SNI dans sa réponse ServerHello. Si vous ne le faites pas, il est possible que le serveur ne prend pas en charge SNI ou qu'il n'ait pas été configuré pour renvoyer des informations SNI en fonction du nom que vous demandez. Dans ce cas, vérifiez que vous utilisez un nom de domaine dans l' -servernameoption à laquelle le serveur doit répondre avec les informations SNI.

Meitar
la source
1
La sortie est la même si j'utilise correct -servernameou non. -servername sdfsdlkfjsdf23.somedomain.somewhere -connect realhost.somedomain.somewhere= TLS server extension "server name" (id=0), len=0(Et même résultat s'ils correspondent.) Comment vérifiez-vous qu'il ne correspond pas à un hôte sur le serveur à partir de la sortie?
bshea
1
@bshea Vous devez passer -msgen plus des paramètres ci-dessus et grep pour "Alert". Si -servernamecela ne va pas, vous obtiendrez quelque chose du genre TLS 1.2 Alert ... warning unrecognized_namedu serveur. @Meitar Je pense que si vous ajoutez cela à la réponse, cela sera utile pour d'autres personnes.
Viktor Nonov le
@ViktorNonov Le -msgcommutateur ajoute simplement un hexdump de messages de protocole TLS. Il n’est pas nécessaire d’observer une erreur de négociation TLS, il serait donc incorrect d’ajouter à cette réponse. De plus, les erreurs de négociation TLS comme celle-ci sont imprimées dans STDOUT, ce qui signifierait que l’ 2>/dev/nullaffichage doit être supprimé de la réponse pour que celle-ci puisse être traitée grepen premier lieu. Ce que @bshea demande en réalité, c'est "Comment détecter les erreurs TLS?" ce qui est une question totalement différente de celle de "Ce serveur utilise-t-il la fonctionnalité SNI du protocole TLS?" quel est le sujet ici.
Meitar le
@Meitar, je ne pouvais pas trouver un autre moyen d'observer les messages de prise de contact TLS. De plus, même si je redirige le STDERRfichier vers un fichier texte, je ne reçois pas cette erreur. Sans cela, -msgje ne pourrais trouver aucune autre option affichant les messages de négociation. (en utilisant openssl 1.0.2q). Tant que la pertinence de la réponse vous convient peut-être.
Viktor Nonov le
-2

Vous pouvez utiliser opensslpour récupérer et interroger le certificat.

  • chercher le cert avec openssl s_client -connect
  • analyser le cert avec openssl x509
  • grep trouver le "DNS:" info

openssl s_client -connect alice.sni.velox.ch:443 | openssl x509 -noout -text | grep DNS:

% openssl s_client -connect alice.sni.velox.ch:443 | openssl x509 -noout -text | grep DNS:
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
verify return:1
depth=1 C = BM, O = QuoVadis Limited, CN = QuoVadis Global SSL ICA G2
verify return:1
depth=0 C = CH, ST = Zuerich, L = Zuerich, O = Kaspar Brand, CN = alice.sni.velox.ch
verify return:1
                DNS:alice.sni.velox.ch, DNS:carol.sni.velox.ch

La dernière ligne affiche toutes les entrées SNI présentes dans le certificat:

                DNS:alice.sni.velox.ch, DNS:carol.sni.velox.ch
spazm
la source
Qu'est-ce que je recherche dans cette sortie? Le fait que plusieurs domaines sont présents?
Spookylukey
Les DNS:... entrées de la dernière ligne indiquent tous les noms de SNI valides dans le certificat.
Spazm
4
Les SAN dans un certificat et la prise en charge de SNI sur un serveur sont des choses différentes, l’utilisation des SAN pour l’hébergement virtuel HTTPS est quelque chose de bidon antérieur à SNI. Pour SNI, vous n'avez pas besoin d'un certificat avec les réseaux de stockage, car le serveur peut sélectionner un certificat individuel correspondant aux attentes de nommage des clients.
mr.spuratic