CFNetwork SSLHandshake falhou no iOS 9

207

alguém com o iOS 9 beta 1 teve esse problema?

Eu uso o padrão NSURLConnection para conectar-se a um serviço da web e, assim que uma chamada é feita, eu recebo o erro abaixo. No momento, está funcionando no iOS 8.3

Possível bug beta? quaisquer idéias ou pensamentos seriam ótimos! Eu sei que é muito cedo no desenvolvimento do iOS 9

Aqui está o erro completo:

CFNetwork SSLHandshake falhou (-9824) NSURLSession / NSURLConnection falha no carregamento HTTP (kCFStreamErrorDomainSSL, -9824)

 NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://mywebserviceurl"]];
        NSURLResponse * response = nil;
        NSError * error = nil;
        NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                                  returningResponse:&response
                                                              error:&error];
user3099837
fonte

Respostas:

310

O iOS 9 e o OSX 10.11 exigem SSL TLSv1.2 para todos os hosts dos quais você planeja solicitar dados, a menos que você especifique domínios de exceção no arquivo Info.plist do seu aplicativo.

A sintaxe da configuração do Info.plist é semelhante a esta:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow insecure HTTP requests-->
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

Se seu aplicativo (um navegador da web de terceiros, por exemplo) precisar se conectar a hosts arbitrários, você poderá configurá-lo da seguinte maneira:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Se você precisar fazer isso, provavelmente é melhor atualizar seus servidores para usar TLSv1.2 e SSL, caso ainda não o estejam fazendo. Isso deve ser considerado uma solução temporária.

Atualmente, a documentação de pré-lançamento não menciona nenhuma dessas opções de configuração de nenhuma maneira específica. Depois disso, atualizarei a resposta para vincular à documentação relevante.

Steven Peterson
fonte
1
O App Transport Security (ATS) permite que um aplicativo adicione uma declaração ao seu arquivo Info.plist que especifica os domínios com os quais ele precisa de comunicação segura. O ATS evita a divulgação acidental, fornece um comportamento padrão seguro e é fácil de adotar. Você deve adotar o ATS o mais rápido possível, independentemente de criar um novo aplicativo ou atualizar um existente. Se você estiver desenvolvendo um novo aplicativo, use HTTPS exclusivamente. Se você possui um aplicativo existente, deve usar o HTTPS o máximo possível no momento e criar um plano para migrar o restante do aplicativo o mais rápido possível.
precisa saber é o seguinte
2
@StevenPeterson hey steve, parece que não consigo obter o exemplo de domínio de exceções para funcionar, você tem alguma idéia por acaso, apenas copiei e colei em .plist mudou o TLSv1.1 para TLSv1.0 e o domínio para o nosso domínio sem o https: // etc
user3099837
27
Desculpem a longa conversa, mas eu percebi isso eu precisava para desativar <key> NSTemporaryExceptionRequiresForwardSecrecy </ key> <false />
user3099837
2
O @RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion é usado para informar ao ATS que você está trabalhando com um servidor não 1.2. Por exemplo, use isso se você estiver tentando se conectar a um host que usa o TLS 1.0. Você também deve usar NSTemporaryExceptionRequiresForwardSecrecy definido como false, como user3099837 indicado acima.
Womble
2
ste.vn/2015/06/10/… - Este é o blog de onde a resposta é obtida.
Sean Dev
66

No iOS 10+, a string TLS DEVE estar no formato "TLSv1.0". Não pode ser apenas "1.0". (Suspiro)


A seguinte combinação das outras respostas funciona.

Digamos que você esteja tentando se conectar a um host (YOUR_HOST.COM) que tenha apenas o TLS 1.0.

Adicione-os ao Info.plist do seu aplicativo

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_HOST.COM</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>
Womble
fonte
9
Parece que a adição NSTemporaryExceptionRequiresForwardSecrecyfez o truque para mim, obrigado!
Josh Valdivieso
2
Esta versão não funcionou para mim no iOS9.1 - eu precisava usar o formato de string TLSVersion em uma das outras respostas <key> NSTemporaryExceptionMinimumTLSVersion </key> <string> TLSv1.1 </string>
300baud
Isso funciona, mas minha pergunta é: isso significa que meu aplicativo não usa ssl quando esses parâmetros estão ativados e os dados não são criptografados?
theDC
33

Para obter mais informações: Configurando exceções de segurança do App Transport no iOS 9 e OSX 10.11

Curiosamente, você notará que a conexão tenta alterar o protocolo http para https para proteger contra erros no seu código, onde você pode ter acidentalmente configurado mal o URL. Em alguns casos, isso pode realmente funcionar, mas também é confuso.

Este envio de um aplicativo com segurança de transporte de aplicativos abrange algumas boas dicas de depuração

Falha no ATS

A maioria das falhas do ATS será apresentada como CFErrors com um código na série -9800. Eles são definidos no cabeçalho Security / SecureTransport.h

2015-08-23 06:34:42.700 SelfSignedServerATSTest[3792:683731] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

CFNETWORK_DIAGNOSTICS

Defina a variável de ambiente CFNETWORK_DIAGNOSTICS como 1 para obter mais informações no console sobre a falha

nscurl

A ferramenta executará várias combinações diferentes de exceções do ATS, tentando uma conexão segura com o host especificado em cada configuração do ATS e relatando o resultado.

nscurl --ats-diagnostics https://example.com
onmyway133
fonte
1
Apontar apenas que nscurl está disponível apenas no Mac OS X "El Capitan"
webo80
1
Mais uma dica de depuração, para verificar qual cifra de conexão TLS está sendo usada pelo servidor: curl -v https: // <hostname>
André Morujão 12/15/15
1
Alguma idéia sobre o que pode causar o problema se enrolar PASSA bem todas as etapas?
Aston
@ onmyway133 você pode adicionar explicações sobre como "Definir a variável de ambiente CFNETWORK_DIAGNOSTICS como 1"?
precisa saber é o seguinte
1
@YakirNa você pode ler sobre como fazer isso aqui nshipster.com/launch-arguments-and-environment-variables é bastante simples :)
onmyway133
2

Se o seu back-end usa uma conexão segura e você obtém o NSURLSession

CFNetwork SSLHandshake failed (-9801)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)

você precisa verificar a configuração do servidor, especialmente para obter a versão ATS e o certificado SSL.

Em vez de apenas Permitir conexão insegura por meio da configuração NSExceptionAllowsInsecureHTTPLoads = YES, é necessário Permitir segurança reduzida , caso o servidor não atenda ao requisito mínimo (v1.2) do ATS (ou melhor, para corrigir o lado do servidor).

Permitindo segurança reduzida para um único servidor

<key>NSExceptionDomains</key>
<dict>
    <key>api.yourDomaine.com</key>
    <dict>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>TLSv1.0</string>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <false/>
    </dict>
</dict>

use o cliente openssl para investigar o certificado e obtenha a configuração do servidor usando o cliente openssl:

openssl s_client  -connect api.yourDomaine.com:port //(you may need to specify port or  to try with https://... or www.)

..Encontre no final

SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: //
    Session-ID-ctx: 
    Master-Key: //
    Key-Arg   : None
    Start Time: 1449693038
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

O App Transport Security (ATS) requer o protocolo TLS (Transport Layer Security) versão 1.2.

Requisitos para conectar usando o ATS:

Os requisitos para uma conexão de serviço da Web usar o App Transport Security (ATS) envolvem o servidor, as cifras de conexão e os certificados, da seguinte maneira:

Os certificados devem ser assinados com um dos seguintes tipos de chaves:

  • Chave Secure Hash Algorithm 2 (SHA-2) com um comprimento de resumo de pelo menos 256 (ou seja, SHA-256 ou superior)

  • Chave de criptografia de curva elíptica (ECC) com um tamanho de pelo menos 256 bits

  • Chave Rivest-Shamir-Adleman (RSA) com um comprimento de pelo menos 2048 bits Um certificado inválido resulta em falha grave e sem conexão.

As seguintes cifras de conexão suportam o sigilo direto (FS) e funcionam com o ATS:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

Atualização: verifica-se que o openssl fornece apenas a versão mínima do protocolo Protocolo: links TLSv1

Idali
fonte
a questão que resta é se é possível interpretar as informações do openssl para descobrir se o servidor atende aos requisitos. Também Protocolo: TLSv1 pode ser a versão makor em vez de 1.x
Idali
Eu o generalizo, no caso de usar port #
Idali
A resposta deixa mais perguntas abertas do que respondidas. Parece que um problema pode ser o mapeamento entre o que é o openssl reports e a documentação da Apple. Na saída openssl, não é possível determinar se o TLS 1.2 é suportado. A resposta também não permite determinar se o Perfect Forward Secrecy é suportado.
Zaph
2

Depois de dois dias de tentativas e fracassos, o que funcionou para mim é esse código de confusão

com uma alteração, de acordo com este post , devemos parar de usar subchaves associadas ao dicionário NSExceptionDomains desse tipo de convenção

  NSTemporaryExceptionMinimumTLSVersion

E usar na nova Convenção

  NSExceptionMinimumTLSVersion

em vez de.

documentação da apple

meu código

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>YOUR_HOST.COM</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
yehoni amran
fonte
1

Outra ferramenta útil é o nmap (brew install nmap)

nmap --script ssl-enum-ciphers -p 443 google.com

Dá saída

Starting Nmap 7.12 ( https://nmap.org ) at 2016-08-11 17:25 IDT
Nmap scan report for google.com (172.217.23.46)
Host is up (0.061s latency).
Other addresses for google.com (not scanned): 2a00:1450:4009:80a::200e
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: client
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 5.48 seconds
Ryan Heitner
fonte
muito útil para o problema de certificado de depuração
Lopakhin
0

Às vezes, esse erro aparecia nos logs quando eu estava usando uma versão iOS do Cordova com falha / com falha. Ele desapareceu quando eu atualizei ou desativei o cordova iOS.

O servidor ao qual estava me conectando estava usando o TLSv1.2 SSL, então sabia que não era esse o problema.

im3r3k
fonte
0

No seu .plistarquivo de projeto , adicione esta permissão:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Hiren Dhamecha
fonte
0

A sintaxe da configuração do Info.plist

   <key>NSAppTransportSecurity</key>
   <dict>
   <key>NSExceptionDomains</key>
    <dict>
    <key>yourserver.com</key>
   <dict>
  <!--Include to allow subdomains-->
  <key>NSIncludesSubdomains</key>
  <true/>
  <!--Include to allow insecure HTTP requests-->
  <key>NSExceptionAllowsInsecureHTTPLoads</key>
  <true/>
  <!--Include to specify minimum TLS version-->
  <key>NSExceptionMinimumTLSVersion</key>
  <string>TLSv1.1</string>
   </dict>
 </dict>

ALOK KUMAR
fonte
0

Resposta atualizada (pós-WWDC 2016):

Os aplicativos para iOS exigirão conexões HTTPS seguras até o final de 2016. Tentar desativar o ATS pode levar seu aplicativo a ser rejeitado no futuro.

O App Transport Security, ou ATS, é um recurso que a Apple introduziu no iOS 9. Quando o ATS é ativado, ele força um aplicativo a se conectar aos serviços da Web por uma conexão HTTPS em vez de HTTP não seguro.

No entanto, os desenvolvedores ainda podem desativar o ATS e permitir que seus aplicativos enviem dados por uma conexão HTTP, conforme mencionado nas respostas acima. No final de 2016, a Apple tornará o ATS obrigatório para todos os desenvolvedores que esperam enviar seus aplicativos para a App Store. ligação

Paraneetharan Saravanaperumal
fonte
0

O dispositivo em que testei estava com o horário errado. Portanto, quando tentei acessar uma página com um certificado que acabaria em breve, ele negaria o acesso porque o dispositivo, embora o certificado tivesse expirado. Para corrigir, defina a hora adequada no dispositivo!

Warpzit
fonte