CFNetwork SSLHandshake ist unter iOS 9 fehlgeschlagen


207

Hat jemand mit iOS 9 Beta 1 dieses Problem gehabt?

Ich verwende Standard-NSURLConnection, um eine Verbindung zu einem Webservice herzustellen, und sobald der Webservice aufgerufen wird, wird der folgende Fehler angezeigt. Dies funktioniert derzeit in iOS 8.3

Möglicher Beta-Bug? Ideen oder Gedanken wären toll! Ich weiß, dass es sehr früh in der iOS 9-Entwicklung ist

Hier ist der vollständige Fehler:

CFNetwork SSLHandshake fehlgeschlagen (-9824) HTTP-Laden von NSURLSession / NSURLConnection fehlgeschlagen (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];

Antworten:


310

iOS 9 und OSX 10.11 erfordern TLSv1.2-SSL für alle Hosts, von denen Sie Daten anfordern möchten, es sei denn, Sie geben in der Info.plist-Datei Ihrer App Ausnahmedomänen an.

Die Syntax für die Info.plist-Konfiguration sieht folgendermaßen aus:

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

Wenn Ihre Anwendung (z. B. ein Webbrowser eines Drittanbieters) eine Verbindung zu beliebigen Hosts herstellen muss, können Sie sie folgendermaßen konfigurieren:

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

Wenn Sie dies tun müssen, ist es wahrscheinlich am besten, Ihre Server für die Verwendung von TLSv1.2 und SSL zu aktualisieren, sofern dies noch nicht geschehen ist. Dies sollte als vorübergehende Problemumgehung betrachtet werden.

Bis heute werden in der Dokumentation zur Vorabversion keine dieser Konfigurationsoptionen in irgendeiner Weise erwähnt. Sobald dies der Fall ist, aktualisiere ich die Antwort, um auf die entsprechende Dokumentation zu verlinken.


1
Mit App Transport Security (ATS) kann eine App ihrer Info.plist-Datei eine Deklaration hinzufügen, die die Domänen angibt, mit denen sie eine sichere Kommunikation benötigt. ATS verhindert versehentliche Offenlegung, bietet sicheres Standardverhalten und ist einfach anzuwenden. Sie sollten ATS so schnell wie möglich einführen, unabhängig davon, ob Sie eine neue App erstellen oder eine vorhandene aktualisieren. Wenn Sie eine neue App entwickeln, sollten Sie ausschließlich HTTPS verwenden. Wenn Sie über eine vorhandene App verfügen, sollten Sie HTTPS so oft wie möglich verwenden und einen Plan für die baldige Migration des Rests Ihrer App erstellen.
user3099837

2
@StevenPeterson Hey Steve, ich kann nicht scheinen, dass das Ausnahme-Domain-Beispiel funktioniert. Haben Sie zufällige Ideen? Ich habe es einfach kopiert und in .plist eingefügt. TLSv1.1 wurde in TLSv1.0 geändert und die Domain in unsere Domain ohne https: // etc
user3099837

27
Entschuldigung für den langen Chat, aber ich habe herausgefunden, dass ich <key> NSTemporaryExceptionRequiresForwardSecrecy </ key> <false />
deaktivieren musste

2
@RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion wird verwendet, um ATS mitzuteilen, dass Sie mit einem Nicht-1.2-Server arbeiten. Verwenden Sie diese Option beispielsweise, wenn Sie versuchen, eine Verbindung zu einem Host herzustellen, der TLS 1.0 verwendet. Sie müssen auch NSTemporaryExceptionRequiresForwardSecrecy verwenden, das auf false gesetzt ist, wie oben angegeben, Benutzer 3099837.
Womble

2
ste.vn/2015/06/10/… - Dies ist der Blog, aus dem die Antwort stammt.
Sean Dev

66

In iOS 10+ MUSS die TLS-Zeichenfolge die Form "TLSv1.0" haben. Es kann nicht einfach "1.0" sein. (Seufzer)


Die folgende Kombination der anderen Antworten funktioniert.

Angenommen, Sie versuchen, eine Verbindung zu einem Host (YOUR_HOST.COM) herzustellen, der nur TLS 1.0 enthält.

Fügen Sie diese zur Info.plist Ihrer App hinzu

<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
Scheint, dass das Hinzufügen NSTemporaryExceptionRequiresForwardSecrecyden Trick für mich getan hat, danke!
Josh Valdivieso

2
Diese Version funktionierte unter iOS9.1 nicht für mich. Ich musste das TLSVersion-Zeichenfolgenformat in einer der anderen Antworten verwenden. <key> NSTemporaryExceptionMinimumTLSVersion </ key> <string> TLSv1.1 </ string>
300baud

Das funktioniert, aber meine Frage ist: Bedeutet das, dass meine App SSL nicht verwendet, wenn diese Parameter aktiviert sind und die Daten nicht verschlüsselt sind?
theDC

33

Weitere Informationen Konfigurieren von Sicherheitsausnahmen für den App-Transport in iOS 9 und OSX 10.11

Seltsamerweise werden Sie feststellen, dass die Verbindung versucht, das http-Protokoll in https zu ändern, um sich vor Fehlern in Ihrem Code zu schützen, bei denen Sie die URL möglicherweise versehentlich falsch konfiguriert haben. In einigen Fällen funktioniert dies möglicherweise tatsächlich, ist aber auch verwirrend.

Dieser Versand einer App mit App Transport Security enthält einige gute Debugging-Tipps

ATS-Fehler

Die meisten ATS-Fehler werden als CFErrors mit einem Code der Serie -9800 angezeigt. Diese sind im Header Security / SecureTransport.h definiert

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

CFNETWORK_DIAGNOSTICS

Setzen Sie die Umgebungsvariable CFNETWORK_DIAGNOSTICS auf 1, um weitere Informationen über den Fehler in der Konsole zu erhalten

nscurl

Das Tool durchläuft verschiedene Kombinationen von ATS-Ausnahmen, versucht unter jeder ATS-Konfiguration eine sichere Verbindung zum angegebenen Host herzustellen und meldet das Ergebnis.

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

1
Nur darauf hinweisen, dass nscurl nur in Mac OS X "El Capitan"
verfügbar ist

1
Noch ein Debugging-Tipp, um zu überprüfen, welche TLS-Verbindungsverschlüsselung von Ihrem Server verwendet wird: curl -v https: // <Hostname>
André Morujão

1
Irgendwelche Ideen, was das Problem verursachen könnte, wenn Curl PASS alle Schritte in Ordnung ist?
Aston

@ onmyway133 können Sie eine Erläuterung hinzufügen, wie "die Umgebungsvariable CFNETWORK_DIAGNOSTICS auf 1 gesetzt wird"?
YakirNa

1
@ YakirNa Sie können hier lesen, wie das geht nshipster.com/launch-arguments-and-environment-variables es ist ziemlich einfach :)
onmyway133

2

Wenn Ihr Backend eine sichere Verbindung verwendet, verwenden Sie NSURLSession

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

Sie müssen Ihre Serverkonfiguration überprüfen, um Informationen zur ATS-Version und zum SSL-Zertifikat zu erhalten:

Anstatt nur eine unsichere Verbindung durch Festlegen zuzulassenNSExceptionAllowsInsecureHTTPLoads = YES , müssen Sie stattdessen eine verminderte Sicherheit zulassen, falls Ihr Server die Mindestanforderungen (v1.2) für ATS nicht erfüllt (oder besser, um die Serverseite zu reparieren).

Verringerte Sicherheit für einen einzelnen Server zulassen

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

Verwenden Sie den openssl-Client, um das Zertifikat zu untersuchen und Ihre Serverkonfiguration mithilfe des openssl-Clients abzurufen:

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

..find am Ende

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)

Für App Transport Security (ATS) ist das TLS-Protokoll (Transport Layer Security) Version 1.2 erforderlich.

Voraussetzungen für die Verbindung mit ATS:

Die Anforderungen für eine Webdienstverbindung zur Verwendung von App Transport Security (ATS) umfassen den Server, die Verbindungschiffren und die Zertifikate wie folgt:

Zertifikate müssen mit einem der folgenden Schlüsseltypen signiert sein:

  • Secure Hash Algorithm 2 (SHA-2) -Schlüssel mit einer Digest-Länge von mindestens 256 (dh SHA-256 oder höher)

  • ECC-Schlüssel (Elliptic-Curve Cryptography) mit einer Größe von mindestens 256 Bit

  • Rivest-Shamir-Adleman (RSA) -Schlüssel mit einer Länge von mindestens 2048 Bit Ein ungültiges Zertifikat führt zu einem harten Fehler und keiner Verbindung.

Die folgenden Verbindungschiffren unterstützen Forward Secrecy (FS) und arbeiten mit 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

Update: Es stellt sich heraus, dass openssl nur die minimale Protokollversion bereitstellt. Protokoll: TLSv1- Links


Die Frage bleibt, ob es möglich ist, openssl-Informationen zu interpretieren, um herauszufinden, ob der Server die Anforderungen erfüllt. Auch Protokoll: TLSv1 kann die Makor-Version anstelle von 1.x sein
Idali

Ich mache es allgemein, falls Sie Port verwenden
Idali

Die Antwort lässt mehr Fragen offen als beantwortet. Es scheint, dass ein Problem die Zuordnung zwischen den OpenSL-Berichten und der Apple-Dokumentation sein kann. Anhand der openssl-Ausgabe kann nicht festgestellt werden, ob TLS 1.2 unterstützt wird. In der Antwort kann auch nicht festgestellt werden, ob Perfect Forward Secrecy unterstützt wird.
Zaph

2

Nach zwei Tagen voller Versuche und Misserfolge hat dieser Code von für mich funktioniert voller Womble- funktioniert

Mit einer Änderung sollten wir gemäß diesem Beitrag die Verwendung von Unterschlüsseln einstellen, die dem NSExceptionDomains- Wörterbuch dieser Art von Konvention zugeordnet sind

  NSTemporaryExceptionMinimumTLSVersion

Und verwenden Sie auf der neuen Konvention

  NSExceptionMinimumTLSVersion

stattdessen.

Apfeldokumentation

mein 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

Ein weiteres nützliches Tool ist nmap (Brew Install nmap)

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

Gibt Ausgabe

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

sehr nützlich, um Zertifikat Problem zu debuggen
Lopakhin

0

Dieser Fehler wurde manchmal in den Protokollen angezeigt, wenn ich eine fehlerhafte / abstürzende Cordova iOS-Version verwendete. Es ging weg, als ich Cordova iOS aktualisierte oder herunterstufte.

Der Server, zu dem ich eine Verbindung herstellte, verwendete TLSv1.2 SSL, sodass ich wusste, dass dies nicht das Problem war.


0

Fügen Sie in Ihrer Projektdatei .plistdiese Berechtigung hinzu:

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

0

Die Syntax für die Info.plist-Konfiguration

   <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

Aktualisierte Antwort (nach WWDC 2016):

Für iOS-Apps sind bis Ende 2016 sichere HTTPS-Verbindungen erforderlich. Wenn Sie ATS deaktivieren, wird Ihre App möglicherweise in Zukunft abgelehnt.

App Transport Security (ATS) ist eine Funktion, die Apple in iOS 9 eingeführt hat. Wenn ATS aktiviert ist, wird eine App gezwungen, über eine HTTPS-Verbindung eine Verbindung zu Webdiensten herzustellen, anstatt über nicht sicheres HTTP.

Entwickler können ATS jedoch weiterhin ausschalten und ihren Apps erlauben, Daten über eine HTTP-Verbindung zu senden, wie in den obigen Antworten erwähnt. Ende 2016 wird Apple ATS für alle Entwickler verbindlich machen , die hoffen, ihre Apps im App Store einzureichen. Verknüpfung


0

Das Gerät, bei dem ich getestet habe, hatte eine falsche Zeit eingestellt. Wenn ich also versuchte, auf eine Seite mit einem Zertifikat zuzugreifen, das bald leer sein würde, wurde der Zugriff verweigert, da das Gerät, obwohl das Zertifikat abgelaufen war. Stellen Sie zum Beheben die richtige Zeit am Gerät ein!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.