CFNetwork SSLHandshake a échoué iOS 9


207

est-ce que quelqu'un avec iOS 9 beta 1 a eu ce problème?

J'utilise NSURLConnection standard pour me connecter à un webservice et dès qu'un appel est fait vers le webservice, j'obtiens l'erreur ci-dessous. Cela fonctionne actuellement dans iOS 8.3

Bug bêta possible? toutes les idées ou pensées seraient super! Je sais que c'est très tôt dans le développement d'iOS 9

Voici l'erreur complète:

CFNetwork SSLHandshake a échoué (-9824) Échec du chargement HTTP NSURLSession / NSURLConnection (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];

Réponses:


310

iOS 9 et OSX 10.11 nécessitent SSL TLSv1.2 pour tous les hôtes auprès desquels vous prévoyez de demander des données, sauf si vous spécifiez des domaines d'exception dans le fichier Info.plist de votre application.

La syntaxe de la configuration Info.plist ressemble à ceci:

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

Si votre application (un navigateur Web tiers, par exemple) doit se connecter à des hôtes arbitraires, vous pouvez la configurer comme suit:

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

Si vous devez le faire, il est probablement préférable de mettre à jour vos serveurs pour utiliser TLSv1.2 et SSL, s'ils ne le font pas déjà. Cela doit être considéré comme une solution de contournement temporaire.

À ce jour, la documentation préliminaire ne fait mention d'aucune de ces options de configuration d'une manière spécifique. Une fois cela fait, je mettrai à jour la réponse pour créer un lien vers la documentation pertinente.


1
App Transport Security (ATS) permet à une application d'ajouter une déclaration à son fichier Info.plist qui spécifie les domaines avec lesquels elle a besoin d'une communication sécurisée. ATS empêche la divulgation accidentelle, fournit un comportement par défaut sécurisé et est facile à adopter. Vous devez adopter ATS dès que possible, que vous créiez une nouvelle application ou que vous mettiez à jour une application existante. Si vous développez une nouvelle application, vous devez utiliser HTTPS exclusivement. Si vous avez une application existante, vous devez utiliser HTTPS autant que possible en ce moment et créer un plan pour migrer le reste de votre application dès que possible.
user3099837

2
@StevenPeterson hey steve, je ne peux pas faire fonctionner l'exemple de domaine d'exceptions, avez-vous des idées par hasard, je viens de copier et coller dans .plist changé TLSv1.1 en TLSv1.0 et le domaine en notre domaine sans https: // etc
user3099837

27
Désolé pour la longue conversation, mais je l'ai compris, je devais désactiver <key> NSTemporaryExceptionRequiresForwardSecrecy </key> <false />
user3099837

2
@RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion est utilisé pour indiquer à ATS que vous travaillez avec un serveur non 1.2. Par exemple, utilisez ceci si vous essayez de vous connecter à un hôte qui utilise TLS 1.0. Vous devez également utiliser NSTemporaryExceptionRequiresForwardSecrecy défini sur false, comme indiqué par user3099837 ci-dessus.
Womble

2
ste.vn/2015/06/10/… - Ceci est le blog d'où provient la réponse.
Sean Dev du

66

Dans iOS 10+, la chaîne TLS DOIT être de la forme "TLSv1.0". Ce ne peut pas être simplement "1.0". (Soupir)


La combinaison suivante des autres réponses fonctionne.

Supposons que vous essayez de vous connecter à un hôte (YOUR_HOST.COM) qui ne dispose que de TLS 1.0.

Ajoutez-les à Info.plist de votre application

<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
Il semble que l'ajout a NSTemporaryExceptionRequiresForwardSecrecyfait l'affaire pour moi, merci!
Josh Valdivieso

2
Cette version ne fonctionnait pas pour moi sur iOS9.1 - J'avais besoin d'utiliser le format de chaîne TLSVersion dans l'une des autres réponses <key> NSTemporaryExceptionMinimumTLSVersion </key> <string> TLSv1.1 </string>
300baud

Cela fonctionne, mais ma question est la suivante: cela signifie-t-il que mon application n'utilise pas SSL lorsque ces paramètres sont activés et que les données ne sont pas chiffrées?
theDC

33

Pour plus d'informations Configuration des exceptions de sécurité du transport d'application dans iOS 9 et OSX 10.11

Curieusement, vous remarquerez que la connexion tente de changer le protocole http en https pour se protéger contre les erreurs dans votre code où vous pouvez avoir accidentellement mal configuré l'URL. Dans certains cas, cela peut réellement fonctionner, mais c'est aussi déroutant.

Cette expédition d'une application avec App Transport Security couvre quelques bons conseils de débogage

Échec ATS

La plupart des échecs ATS se présenteront sous la forme de CFErrors avec un code de la série -9800. Ceux-ci sont définis dans l'en-tête Security / SecureTransport.h

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

CFNETWORK_DIAGNOSTICS

Définissez la variable d'environnement CFNETWORK_DIAGNOSTICS sur 1 afin d'obtenir plus d'informations sur la console concernant l'échec

nscurl

L'outil exécutera plusieurs combinaisons différentes d'exceptions ATS, essayant une connexion sécurisée à l'hôte donné sous chaque configuration ATS et rapportant le résultat.

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

1
Seul point que nscurl est uniquement disponible dans Mac OS X "El Capitan"
webo80

1
Une autre astuce de débogage, pour vérifier quel chiffrement de connexion TLS est utilisé par votre serveur: curl -v https: // <nom d'hôte>
André Morujão

1
Des idées sur ce qui peut causer le problème si curl PASS passe toutes les étapes correctement?
Aston

@ onmyway133 pouvez-vous ajouter une explication sur la façon de "définir la variable d'environnement CFNETWORK_DIAGNOSTICS à 1"?
YakirNa

1
@YakirNa, vous pouvez lire comment faire ici nshipster.com/launch-arguments-and-environment-variables c'est assez simple :)
onmyway133

2

Si votre backend utilise une connexion sécurisée et vous obtenez en utilisant NSURLSession

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

vous devez vérifier la configuration de votre serveur en particulier pour obtenir la version ATS et le certificat SSL Info:

Au lieu de simplement autoriser une connexion non sécurisée en définissant NSExceptionAllowsInsecureHTTPLoads = YES, vous devez plutôt autoriser une sécurité réduite au cas où votre serveur ne répondrait pas à l'exigence minimale (v1.2) pour ATS (ou mieux pour corriger côté serveur).

Permettre une sécurité réduite à un seul serveur

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

utilisez le client openssl pour étudier le certificat et obtenir la configuration de votre serveur à l'aide du client openssl:

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

..trouver à la fin

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)

App Transport Security (ATS) requiert le protocole Transport Layer Security (TLS) version 1.2.

Conditions requises pour la connexion à l'aide d'ATS:

La configuration requise pour qu'une connexion de service Web utilise App Transport Security (ATS) implique le serveur, les chiffrements de connexion et les certificats, comme suit:

Les certificats doivent être signés avec l'un des types de clés suivants:

  • Clé Secure Hash Algorithm 2 (SHA-2) avec une longueur de résumé d'au moins 256 (c'est-à-dire SHA-256 ou plus)

  • Clé de cryptographie à courbe elliptique (ECC) avec une taille d'au moins 256 bits

  • Clé Rivest-Shamir-Adleman (RSA) d'une longueur d'au moins 2048 bits Un certificat non valide entraîne une défaillance matérielle et aucune connexion.

Les chiffrements de connexion suivants prennent en charge le secret avancé (FS) et fonctionnent avec 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

Mise à jour: il s'avère que openssl ne fournit que la version minimale du protocole Protocole: liens TLSv1


la question reste de savoir s'il est possible d'interpréter les informations openssl pour savoir si le serveur répond aux exigences. Aussi Protocole: TLSv1 peut être la version makor au lieu de 1.x
Idali

Je le fais général, dans le cas où
Idali

La réponse laisse plus de questions ouvertes que de réponses. Il semble qu'un problème puisse être lié aux correspondances entre les rapports openssl et la documentation Apple. Il n'est pas possible à partir de la sortie openssl de déterminer si TLS 1.2 est pris en charge. La réponse ne permet pas non plus de déterminer si Perfect Forward Secrecy est pris en charge.
zaph

2

Après deux jours de tentatives et d'échecs, ce qui a fonctionné pour moi, c'est ce code de womble

avec un changement, selon cet article, nous devrions cesser d'utiliser les sous-clés associées au dictionnaire NSExceptionDomains de ce type de convention

  NSTemporaryExceptionMinimumTLSVersion

Et utiliser à la nouvelle Convention

  NSExceptionMinimumTLSVersion

au lieu.

documentation Apple

mon code

<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 autre outil utile est nmap (installer bmap nmap)

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

Donne une sortie

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

très utile pour déboguer le problème de certificat
Lopakhin

0

Cette erreur apparaissait parfois dans les journaux lorsque j'utilisais une version iOS de Cordova buggy / crashy. Il a disparu lorsque j'ai mis à niveau ou rétrogradé cordova iOS.

Le serveur auquel je me connectais utilisait SSL TLSv1.2, donc je savais que ce n'était pas le problème.


0

Dans votre .plistfichier de projet , ajoutez cette autorisation:

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

0

La syntaxe de la configuration 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

Réponse mise à jour (après la WWDC 2016):

Les applications iOS nécessiteront des connexions HTTPS sécurisées d'ici la fin de 2016. Si vous désactivez ATS, votre application pourrait être rejetée à l'avenir.

App Transport Security, ou ATS, est une fonctionnalité introduite par Apple dans iOS 9. Lorsque ATS est activé, il oblige une application à se connecter aux services Web via une connexion HTTPS plutôt que HTTP non sécurisé.

Cependant, les développeurs peuvent toujours désactiver ATS et autoriser leurs applications à envoyer des données via une connexion HTTP, comme mentionné dans les réponses ci-dessus. Fin 2016, Apple rendra l' ATS obligatoire pour tous les développeurs qui souhaitent soumettre leurs applications sur l'App Store. lien


0

L'appareil sur lequel j'ai testé avait un mauvais réglage de l'heure. Ainsi, lorsque j'essayais d'accéder à une page avec un certificat qui s'épuiserait bientôt, cela refuserait l'accès car le périphérique bien que le certificat ait expiré. Pour corriger, réglez l'heure appropriée sur l'appareil!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.