web-dev-qa-db-fra.com

Server compatible CURL et SNI

Je suis en cours d'exécution sur un serveur compatible SNI avec la commande suivante

curl --cacert CustomCA.crt -H "Host: example.com" https://1.2.3.4/foo

Cependant, je ne reçois pas le bon certificat où le nom commun (CN) ensemble comme example.com (d'où la vérification du certificat n'a pas). Je sais que la configuration SNI est terminée correctement car je vois que le bon certificat est livré lors de l'accès à celui-ci via un navigateur Web. Juste au cas où mon environnement actuel est

> curl --version
curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3
Protocols: dict file ftp ftps Gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smtp smtps telnet tftp 
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP 
> lsb_release -a
LSB Version:    core-2.0-AMD64:core-2.0-noarch:core-3.0-AMD64:core-3.0-noarch:core-3.1-AMD64:core-3.1-noarch:core-3.2-AMD64:core-3.2-noarch:core-4.0-AMD64:core-4.0-noarch:core-4.1-AMD64:core-4.1-noarch:security-4.0-AMD64:security-4.0-noarch:security-4.1-AMD64:security-4.1-noarch
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.1 LTS
Release:        14.04
Codename:       trusty

EDIT: J'ai oublié de mentionner qu'il n'y a pas d'entrée DNS à la carte de la carte à 1.2.3.4. C'est en fait une partie de mon travail que je l'ai fait dans Ruby comme suit:

  context = OpenSSL::SSL::SSLContext.new
  context.ca_file = 'CustomCA.crt'
  context.verify_mode = OpenSSL::SSL::VERIFY_PEER

  tcp_client = TCPSocket.new('1.2.3.4', 443)
  ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client, context)
  ssl_client.hostname = 'example.com'
  ssl_client.connect
  cert = OpenSSL::X509::Certificate.new(ssl_client.peer_cert)
  cert_ca = OpenSSL::X509::Certificate.new(File.read(ca_path))
  ssl_client.sysclose
  tcp_client.close

Je me demande simplement comment ré-créer quelque chose comme celui-ci en utilisant simplement Curl.

Et ... en modifiant ma propre copie de/etc/hosts, la commande fonctionnerait correctement

1.2.3.4 example.com

pourquoi donc?

Edit 2: Fais-le faire via OpenSSL

openssl s_client -connect 1.2.3.4:443 -servername example.com
6
Jeffrey04

L'en-tête d'accueil n'a rien à voir avec Sni. Pour utiliser SNI, vous devez utiliser le nom d'hôte dans l'URL, c'est-à-dire l'utilisation https://example.com/ à la place de http://1.2.3.4/ (et bien sûr utiliser https: // pas http: //).

Plus de détails: Sni envoie le nom d'hôte à l'intérieur de la poignée de main TLS (Clienthello). Le serveur choisit ensuite le certificat correct en fonction de ces informations. Une fois que la connexion TLS est établie avec succès, elle enverra la demande HTTP, qui contient l'en-tête d'hôte que vous avez spécifié.

En ce qui concerne votre édition/commentaires:

  • Je me demande comment vous avez accédé au site avec succès avec le navigateur s'il n'y a pas d'entrée DNS pour l'hôte. Si le navigateur ne connaît pas le nom d'hôte, il ne peut pas utiliser SNI non plus.
  • Si vous ajoutez le mappage hôte/IP à /etc/hosts Cela fonctionnera lors de l'accès à https://example.com Avec CURL parce que vous savez que vous avez le nom d'hôte pour SNI et l'adresse IP correspondante pour le TCP Connection.
  • Votre Ruby fichier définit ssl_client.hostname. Ceci n'est pas identique à l'en-tête HTTP hôte que vous avez défini avec CURL.
  • Je ne vois pas une option de curl où vous pourriez définir l'hôteName pour TLS Sni et IP pour TCP Connection de manière indépendante.
6
Steffen Ullrich