openssl consulta o comando NGINX por ip e não hostname

1

Aqui está uma situação que estou tendo dificuldade em entender. Eu tenho configuração nginx com dois blocos para hosts como o seguinte

server {
    server_name _;
    listen *:443 default_server deferred;
    return 444;
}
server {
    listen      443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.ca;

}

O pega-tudo tem um certificado SSL auto-gerado e o bloco do meu aplicativo tem um certificado SSL funcional. Esta configuração está funcionando para navegadores da web. Se um navegador da Web for para https://www.example.com , ele acessará meu aplicativo, mas se ele for para htpps://123.123.123.123 , ele não retornará nada. Mas agora eu me deparei com uma situação muito estranha. Eu estava recebendo alguns pedidos para o domínio que estavam falhando (vindo de um script), então eu tentei depurar. Primeiro tentei enrolar o URL:

$ curl https://www.example.ca
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

Eu achei isso estranho porque os navegadores mostram que as certs funcionam tanto quanto o www.ssllabs.com mostra que está funcionando. O próximo passo que tentei foi ver o certificado SSL na linha de comando:

echo | openssl s_client -showcerts -connect www.example.ca:443

Esse comando realmente mostra meu certificado SSL para o bloco catch all server e não o bloco example.ca . Se eu adicionar o endereço IP ao segundo bloco nginx, vejo o certificado ssl para example.ca . Então, agora eu sei que openssl e curl estão recebendo o certificado ssl errado porque eles estão sendo atendidos no certificado errado, mas não entendo por quê?

Eu não sei muito sobre o openssl, mas tudo o que posso pensar é que openssl / curl estão convertendo erroneamente o nome do host em um endereço IP ou estão esquecendo de adicionar um cabeçalho correto? Isso é super estranho e, se alguém souber mais, eu apreciaria algum feedback.

    
por Cody 16.11.2017 / 01:02

1 resposta

2

Servidores Vhost como nginx com vários certs (e chaves) usam a extensão Indicação do Nome do Servidor (SNI) para selecionar o certificado correto (vhost e), mas por padrão openssl s_client não envia SNI assim você obtém o certificado padrão; adicione -servername $hostname conforme descrito na página man (logo após -connect ). Existem muitas duplicatas desta parte em várias outras pilhas, mas não consigo encontrar uma aqui.

OTOH curl envia automaticamente o SNI (assim como os navegadores e ssllabs), a menos que você tenha uma versão antiga do próprio curl ou do middleware usado (que não é sempre sempre OpenSSL; verifique curl -V maiúscula). Tente adicionar -v para obter mais detalhes sobre o que está fazendo e obtendo, e se isso não for suficiente, obtenha um rastreamento de fio com tcpdump / Wireshark / etc.

    
por 16.11.2017 / 02:39