CFNetwork SSLHandshake non riuscito iOS 9


207

qualcuno con iOS 9 beta 1 ha avuto questo problema?

Uso NSURLConnection standard per connettermi a un servizio Web e non appena viene effettuata una chiamata al servizio Web ottengo l'errore di seguito. Questo funziona attualmente in iOS 8.3

Possibile bug beta? qualsiasi idea o pensiero sarebbe fantastico! So che è molto presto nello sviluppo di iOS 9

Ecco l'errore completo:

CFNetwork SSLHandshake fallito (-9824) NSURLSession / NSURLConnection Caricamento HTTP non riuscito (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];

Risposte:


310

iOS 9 e OSX 10.11 richiedono TLSv1.2 SSL per tutti gli host da cui prevedi di richiedere dati a meno che non specifichi domini di eccezione nel file Info.plist della tua app.

La sintassi per la configurazione di Info.plist è simile alla seguente:

<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 l'applicazione (un browser Web di terze parti, ad esempio) deve connettersi a host arbitrari, è possibile configurarla in questo modo:

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

Se devi farlo, probabilmente è meglio aggiornare i tuoi server per utilizzare TLSv1.2 e SSL, se non lo stanno già facendo. Questo dovrebbe essere considerato una soluzione temporanea.

Ad oggi, la documentazione pre-release non menziona nessuna di queste opzioni di configurazione in alcun modo specifico. Una volta fatto, aggiornerò la risposta per collegarmi alla documentazione pertinente.


1
App Transport Security (ATS) consente a un'app di aggiungere una dichiarazione al suo file Info.plist che specifica i domini con i quali necessita di comunicazioni sicure. ATS impedisce la divulgazione accidentale, fornisce un comportamento predefinito sicuro ed è facile da adottare. È necessario adottare ATS il prima possibile, indipendentemente dal fatto che si stia creando una nuova app o aggiornando una esistente. Se stai sviluppando una nuova app, dovresti utilizzare esclusivamente HTTPS. Se disponi di un'app esistente, dovresti utilizzare HTTPS il più possibile in questo momento e creare un piano per la migrazione del resto dell'app nel più breve tempo possibile.
user3099837

2
@StevenPeterson hey steve non riesco a far funzionare l'esempio del dominio delle eccezioni, hai qualche idea per caso, ho appena copiato e incollato in .plist cambiato TLSv1.1 in TLSv1.0 e il dominio nel nostro dominio senza https: // etc
user3099837

27
Ci scusiamo per la lunga chat ma ho capito che dovevo disabilitare <key> NSTemporaryExceptionRequiresForwardSecrecy </key> <false />
user3099837

2
@RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion è usato per dire ad ATS che stai lavorando con un server non 1.2. Ad esempio, utilizzare questo se si sta tentando di connettersi a un host che utilizza TLS 1.0. È inoltre necessario utilizzare NSTemporaryExceptionRequiresForwardSecrecy impostato su false, come indicato dall'utente3099837 sopra.
Womble,

2
ste.vn/2015/06/10/… - Questo è il blog da cui proviene la risposta.
Sean Dev,

66

In iOS 10+, la stringa TLS DEVE essere nel formato "TLSv1.0". Non può essere solo "1.0". (Sospiro)


La seguente combinazione delle altre risposte funziona.

Supponiamo che tu stia provando a connetterti a un host (YOUR_HOST.COM) che ha solo TLS 1.0.

Aggiungi questi alla Info.plist della tua app

<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>

9
Sembra che l'aggiunta abbia NSTemporaryExceptionRequiresForwardSecrecyfatto il trucco per me, grazie!
Josh Valdivieso,

2
Questa versione non ha funzionato per me su iOS9.1 - Avevo bisogno di utilizzare il formato stringa TLSVersion in una delle altre risposte <key> NSTemporaryExceptionMinimumTLSVersion </key> <stringa> TLSv1.1 </string>
300baud

Funziona ma la mia domanda è: ciò significa che la mia app non usa SSL quando questi parametri sono attivi e i dati non sono crittografati?
theDC

33

Per ulteriori informazioni Configurazione delle eccezioni di sicurezza del trasporto app in iOS 9 e OSX 10.11

Curiosamente, noterai che la connessione tenta di modificare il protocollo http in https per proteggerlo da errori nel codice in cui potresti aver accidentalmente configurato l'URL. In alcuni casi, questo potrebbe effettivamente funzionare, ma è anche fonte di confusione.

Questa spedizione di un'app con App Transport Security offre alcuni suggerimenti utili per il debug

Errore ATS

La maggior parte dei guasti ATS presenterà come CFErrors un codice nella serie -9800. Questi sono definiti nell'intestazione Security / SecureTransport.h

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

CFNETWORK_DIAGNOSTICS

Impostare la variabile di ambiente CFNETWORK_DIAGNOSTICS su 1 per ottenere maggiori informazioni sulla console sull'errore

nscurl

Lo strumento eseguirà diverse combinazioni diverse di eccezioni ATS, provando una connessione sicura all'host specificato in ciascuna configurazione ATS e segnalando il risultato.

nscurl --ats-diagnostics https://example.com

1
Unico punto è che nscurl è disponibile solo in Mac OS X "El Capitan"
webo80

1
Un altro suggerimento per il debug, per verificare quale codice di connessione TLS viene utilizzato dal server: curl -v https: // <nomehost>
André Morujão,

1
Qualche idea su cosa potrebbe causare il problema se l'arricciatura PASSA tutti i passaggi correttamente?
Aston,

@ onmyway133 puoi aggiungere spiegazioni su come "Impostare la variabile di ambiente CFNETWORK_DIAGNOSTICS su 1"?
YakirNa,

1
@YakirNa puoi leggere come farlo qui nshipster.com/launch-arguments-and-environment-variables è abbastanza semplice :)
onmyway133

2

Se il tuo back-end utilizza una formica di connessione sicura otterrai NSURLSession

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

è necessario verificare la configurazione del server in particolare per ottenere la versione ATS e il certificato SSL Informazioni:

Invece di consentire solo l' insicurezza della connessione impostando NSExceptionAllowsInsecureHTTPLoads = YES, è invece necessario consentire la sicurezza ridotta nel caso in cui il server non soddisfi i requisiti minimi (v1.2) per ATS (o meglio per risolvere il lato server).

Consentire la sicurezza ridotta a un singolo server

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

usa il client openssl per esaminare il certificato e ottenere la configurazione del tuo server usando il client openssl:

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

..trova alla fine

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)

La sicurezza del trasporto app (ATS) richiede il protocollo TLS (Transport Layer Security) versione 1.2.

Requisiti per la connessione tramite ATS:

I requisiti per una connessione al servizio Web per l'utilizzo di App Transport Security (ATS) coinvolgono il server, i codici di connessione e i certificati, come segue:

I certificati devono essere firmati con uno dei seguenti tipi di chiavi:

  • Tasto Secure Hash Algorithm 2 (SHA-2) con una lunghezza digest di almeno 256 (ovvero SHA-256 o superiore)

  • Chiave di crittografia a curva ellittica (ECC) con una dimensione di almeno 256 bit

  • Chiave Rivest-Shamir-Adleman (RSA) con una lunghezza di almeno 2048 bit Un certificato non valido provoca un errore grave e nessuna connessione.

I seguenti codici di connessione supportano il segreto di andata (FS) e funzionano con 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

Aggiornamento: si scopre che openssl fornisce solo la versione minima del protocollo Protocollo: collegamenti TLSv1


la domanda rimane: è possibile interpretare le informazioni di openssl per scoprire se il server soddisfa i requisiti. Anche protocollo: TLSv1 potrebbe essere la versione di makor invece di 1.x
Idali

Lo rendo generale, nel caso in cui utilizzi port
Idali il

La risposta lascia più domande aperte che risposte. Sembra che un problema potrebbe essere la mappatura tra ciò che riporta openssl e la documentazione di Apple. Dall'output di openssl non è possibile determinare se TLS 1.2 è supportato. La risposta, inoltre, non consente di determinare se Perfect Forward Secrecy è supportato.
zaph,

2

Dopo due giorni di tentativi e fallimenti, ciò che ha funzionato per me è questo codice di womble

con una modifica, in base a questo post dovremmo smettere di usare le sottochiavi associate al dizionario NSExceptionDomains di quel tipo di convenzione

  NSTemporaryExceptionMinimumTLSVersion

E utilizzare alla nuova Convenzione

  NSExceptionMinimumTLSVersion

anziché.

documentazione Apple

il mio codice

<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>

1

Un altro strumento utile è nmap (brew install nmap)

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

Fornisce output

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

molto utile per il debug del problema con il certificato
Lopakhin,

0

Questo errore veniva visualizzato nei registri a volte quando stavo usando una versione Cordova iOS con bug / crash. È andato via quando ho aggiornato o declassato Cordova iOS.

Il server a cui mi stavo connettendo stava usando TLSv1.2 SSL, quindi sapevo che non era questo il problema.


0

Nel .plistfile di progetto in aggiungi questa autorizzazione:

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

0

La sintassi per la configurazione di 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>


0

Risposta aggiornata (post-WWDC 2016):

Le app iOS richiederanno connessioni HTTPS sicure entro la fine del 2016. Provare a disattivare ATS potrebbe in futuro rifiutare l'app.

App Transport Security, o ATS, è una funzionalità introdotta da Apple in iOS 9. Quando ATS è abilitato, forza un'app a connettersi ai servizi Web tramite una connessione HTTPS anziché HTTP non sicuro.

Tuttavia, gli sviluppatori possono comunque disattivare ATS e consentire alle loro app di inviare dati tramite una connessione HTTP come indicato nelle risposte sopra. Alla fine del 2016, Apple renderà ATS obbligatorio per tutti gli sviluppatori che sperano di inviare le loro app all'App Store. collegamento


0

Il dispositivo al quale ho provato aveva un tempo sbagliato impostato. Quindi, quando ho provato ad accedere a una pagina con un certificato che si sarebbe esaurito presto, avrei negato l'accesso perché il dispositivo era scaduto. Per risolvere, impostare l'ora corretta sul dispositivo!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.