CFNetwork SSLHandshake falló iOS 9
nsurlconnection ios9 (13)
Para obtener más información Configuración de excepciones de seguridad de transporte de aplicaciones en iOS 9 y OSX 10.11
Curiosamente, notará que la conexión intenta cambiar el protocolo http a https para protegerlo contra errores en su código donde puede haber configurado erróneamente la URL. En algunos casos, esto podría funcionar, pero también es confuso.
Enviar una aplicación con App Transport Security cubre algunos buenos consejos para la eliminación de errores
Fracaso ATS
La mayoría de las fallas ATS se presentarán como CFErrors con un código en la serie -9800. Estos se definen en el encabezado Security / SecureTransport.h
2015-08-23 06:34:42.700 SelfSignedServerATSTest[3792:683731] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
CFNETWORK_DIAGNOSTICS
Establezca la variable de entorno CFNETWORK_DIAGNOSTICS en 1 para obtener más información sobre la falla en la consola
nscurl
La herramienta ejecutará varias combinaciones diferentes de excepciones ATS, probando una conexión segura al host dado bajo cada configuración ATS e informando el resultado.
nscurl --ats-diagnostics https://example.com
¿Alguien con iOS 9 beta 1 tuvo este problema?
Utilizo NSURLConnection estándar para conectarme a un servicio web y, tan pronto como se realiza una llamada al servicio web, aparece el siguiente error. Esto actualmente está funcionando en iOS 8.3
Posible error beta? ¡cualquier idea o pensamiento sería genial! Sé que es muy temprano en el desarrollo de iOS 9
Aquí está el error completo:
CFNetwork SSLHandshake failed (-9824) NSURLSession / NSURLConnection Carga HTTP fallida (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];
Si tu back-end usa una conexión segura, obtienes NSURLSession
CFNetwork SSLHandshake failed (-9801)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)
debe verificar la configuración de su servidor, especialmente para obtener la versión ATS y la información del certificado SSL:
En lugar de simplemente Permitir conexión insegura configurando NSExceptionAllowsInsecureHTTPLoads = YES
, en su lugar debe Permitir seguridad rebajada en caso de que su servidor no cumpla con el requisito mínimo (v1.2) para ATS (o mejor para reparar el lado del servidor).
Permitir bajada de seguridad a un solo servidor
<key>NSExceptionDomains</key>
<dict>
<key>api.yourDomaine.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
utiliza el cliente de openssl para investigar el certificado y obtener la configuración de tu servidor usando el cliente de openssl:
openssl s_client -connect api.yourDomaine.com:port //(you may need to specify port or to try with https://... or www.)
.. encontrar al 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)
App Transport Security (ATS) requiere la versión 1.2 del protocolo Transport Layer Security (TLS).
Requisitos para la conexión mediante ATS:
Los requisitos para una conexión de servicio web para utilizar App Transport Security (ATS) implican el servidor, las cifras de conexión y los certificados, de la siguiente manera:
Los certificados deben estar firmados con uno de los siguientes tipos de claves:
- Secure Hash Algorithm 2 (SHA-2) clave con una longitud de resumen de al menos 256 (es decir, SHA-256 o superior)
Clave de criptografía de curva elíptica (ECC) con un tamaño de al menos 256 bits
Clave Rivest-Shamir-Adleman (RSA) con una longitud de al menos 2048 bits Un certificado no válido da como resultado una falla grave y ninguna conexión.
Los siguientes sistemas de cifrado de conexión admiten el secreto de envío (FS) y funcionan 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
Actualización: resulta que openssl solo proporciona la versión de protocolo mínima Protocolo: enlaces TLSv1
iOS 9 y OSX 10.11 requieren TLSv1.2 SSL para todos los hosts a los que planea solicitar datos, a menos que especifique dominios de excepción en el archivo Info.plist de su aplicación.
La sintaxis de la configuración de Info.plist tiene este aspecto:
<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 su aplicación (un navegador web de terceros, por ejemplo) necesita conectarse a hosts arbitrarios, puede configurarla así:
<key>NSAppTransportSecurity</key>
<dict>
<!--Connect to anything (this is probably BAD)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Si tiene que hacer esto, probablemente sea mejor actualizar sus servidores para usar TLSv1.2 y SSL, si es que todavía no lo están haciendo. Esto debe considerarse una solución temporal.
A partir de hoy, la documentación preliminar no menciona ninguna de estas opciones de configuración de ninguna manera específica. Una vez que lo haga, actualizaré la respuesta para vincularla a la documentación relevante.
info.plist como a continuación o simplemente copie y pase ese trabajo para mí hasta iOS 9.2
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
Este error aparecía en los registros a veces cuando usaba una versión Buggy / crashy Cordova iOS. Se fue cuando actualicé o disminuí el cordova iOS.
El servidor al que me estaba conectando usaba TLSv1.2 SSL, así que sabía que ese no era el problema.
En su archivo de proyecto .plist
, agregue este permiso:
<key>NSAppTransportSecurity</key>
<dict>
<!--Connect to anything (this is probably BAD)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
La sintaxis para la configuración de 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>
Respuesta actualizada (post-WWDC 2016):
Para fines de 2016, las aplicaciones iOS requerirán conexiones HTTPS seguras. Intentar desactivar ATS puede hacer que su aplicación sea rechazada en el futuro.
App Transport Security, o ATS, es una función que Apple introdujo en iOS 9. Cuando ATS está habilitado, obliga a una aplicación a conectarse a servicios web a través de una conexión HTTPS en lugar de HTTP no seguro.
Sin embargo, los desarrolladores aún pueden desactivar ATS y permitir que sus aplicaciones envíen datos a través de una conexión HTTP como se menciona en las respuestas anteriores. A finales de 2016, Apple hará obligatorio el ATS para todos los desarrolladores que deseen enviar sus aplicaciones a la App Store. enlazar
** NOTA IMPORTANTE PARA iOS 10 BETA: **
En iOS 10, la cadena TLS DEBE tener la forma "TLSv1.0". No puede ser simplemente "1.0". Sí, esto es increíblemente estúpido y rompe aplicaciones. Bienvenido al desarrollo de iOS.
La siguiente combinación de los consejos anteriores funciona.
Digamos que está intentando conectarse a un host (YOUR_HOST.COM) que solo tiene TLS 1.0.
Agregue estos a Info.plist de su aplicación
<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>
Otra herramienta útil es nmap (brew install nmap)
nmap --script ssl-enum-ciphers -p 443 google.com
Da salida
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
El dispositivo que probé tenía un tiempo equivocado. Entonces, cuando intenté acceder a una página con un certificado que se agotaría pronto, denegaría el acceso porque el dispositivo había caducado. Para solucionarlo, ¡configure el tiempo adecuado en el dispositivo!
Después de dos días de intentos y fracasos, lo que funcionó para mí es este código de womble
con One change, de acuerdo con esta publicación deberíamos dejar de usar las subclases asociadas con el diccionario NSExceptionDomains de ese tipo de Convención
NSTemporaryExceptionMinimumTLSVersion
Y uso en la nueva Convención
NSExceptionMinimumTLSVersion
en lugar.
mi 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>