curl e servidor ativado por sni

5

Estou executando o curl em um servidor habilitado para sni com o seguinte comando

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

No entanto, não estou obtendo o certificado correto no qual o nome comum (CN) está definido como example.com (por isso, a verificação do certificado falhou). Eu sei que a configuração SNI é feita corretamente porque eu vejo o certificado certo é entregue ao acessá-lo através do navegador da web. Apenas no caso, meu ambiente atual é

> 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: eu esqueci de mencionar que não há nenhuma entrada do DNS para mapear exemplo.com para 1.2.3.4. Esta é realmente uma parte do meu trabalho, que eu fiz em ruby da seguinte forma:

  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

Estou apenas imaginando como recriar algo assim usando apenas curl.

E ... editando minha própria cópia de / etc / hosts, o comando funcionaria corretamente

1.2.3.4 example.com

por que isso?

EDIT 2: fazendo isso via openssl

openssl s_client -connect 1.2.3.4:443 -servername example.com
    
por Jeffrey04 07.08.2014 / 09:51

2 respostas

6

O cabeçalho do host não tem nada a ver com o SNI. Para usar o SNI, você precisa usar o nome do host no URL, ou seja, usar https://example.com/ em vez de http://1.2.3.4/ (e, claro, usar https: // não http: //).

Mais detalhes: O SNI envia o nome do host dentro do handshake TLS (ClientHello). O servidor escolhe o certificado correto com base nessas informações. Somente depois que a conexão TLS for estabelecida com sucesso, ele enviará a solicitação HTTP, que contém o cabeçalho do Host especificado por você.

Em relação à sua edição / comentários:

  • Gostaria de saber como você acessou o site com êxito com o navegador, se não houver entrada de DNS para o host. Se o navegador não souber o nome do host, ele não poderá usar o SNI.
  • Se você adicionar o mapeamento de host / ip a /etc/hosts , funcionará ao acessar https://example.com com curl porque você sabe que tem o nome do host para SNI e o IP correspondente para a conexão TCP.
  • Seu código ruby define ssl_client.hostname. Isso não é o mesmo que o cabeçalho do host HTTP que você definiu com o curl.
  • Não vejo uma opção para curl onde você pode definir o nome do host para o TLS SNI e o IP para a conexão TCP independentemente.
por 07.08.2014 / 11:11
21

Finalmente encontrei a resposta depois de me referir a isso .

curl --cacert CustomCA.crt --resolve example.com:443:1.2.3.4 https://example.com/foo
    
por 08.08.2014 / 08:47

Tags