CFNetwork SSLHandshake falló iOS 9

207

¿Alguien con iOS 9 beta 1 ha tenido 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 funciona actualmente 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 falló (-9824) NSURLSession / NSURLConnection Error de carga 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];
usuario3099837
fuente

Respuestas:

310

iOS 9 y OSX 10.11 requieren SSL TLSv1.2 para todos los hosts de los que planea solicitar datos, a menos que especifique dominios de excepción en el archivo Info.plist de su aplicación.

La sintaxis para la configuración de Info.plist se ve así:

<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 aún 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 manera específica. Una vez que lo haga, actualizaré la respuesta para vincular a la documentación relevante.

Steven Peterson
fuente
1
App Transport Security (ATS) permite que una aplicación agregue una declaración a su archivo Info.plist que especifica los dominios con los que necesita una comunicación segura. ATS evita la divulgación accidental, proporciona un comportamiento predeterminado seguro y es fácil de adoptar. Debe adoptar ATS lo antes posible, independientemente de si está creando una nueva aplicación o actualizando una existente. Si está desarrollando una nueva aplicación, debe usar HTTPS exclusivamente. Si tiene una aplicación existente, debe usar HTTPS tanto como pueda en este momento y crear un plan para migrar el resto de su aplicación lo antes posible.
user3099837
2
@StevenPeterson Hola Steve, parece que no puedo obtener el ejemplo de dominio de excepciones para trabajar, ¿tienes alguna idea por casualidad? // etc
user3099837
27
Perdón por el largo chat, pero descubrí que necesitaba desactivar <key> NSTemporaryExceptionRequiresForwardSecrecy </key> <false />
user3099837
2
@RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion se usa para decirle a ATS que está trabajando con un servidor que no es 1.2. Por ejemplo, use esto si está intentando conectarse a un host que usa TLS 1.0. También debe usar NSTemporaryExceptionRequiresForwardSecrecy establecido en falso, como el usuario 3099837 indicado anteriormente.
Womble
2
ste.vn/2015/06/10/… - Este es el blog de donde proviene la respuesta.
Sean Dev
66

En iOS 10+, la cadena TLS DEBE tener la forma "TLSv1.0". No puede ser solo "1.0". (Suspiro)


La siguiente combinación de las otras respuestas funciona.

Digamos que está intentando conectarse a un host (YOUR_HOST.COM) que solo tiene TLS 1.0.

Agréguelos a la lista de información 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>
Womble
fuente
9
Parece que agregar me NSTemporaryExceptionRequiresForwardSecrecysirvió, ¡gracias!
Josh Valdivieso
2
Esta versión no me funcionó en iOS9.1: necesitaba usar el formato de cadena TLSVersion en una de las otras respuestas <key> NSTemporaryExceptionMinimumTLSVersion </key> <string> TLSv1.1 </string>
300baud
Esto funciona, pero mi pregunta es: ¿eso significa que mi aplicación no usa SSL cuando estos parámetros están activados y los datos no están encriptados?
theDC
33

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 incorrectamente la URL accidentalmente. En algunos casos, esto podría funcionar, pero también es confuso.

Este envío de una aplicación con App Transport Security cubre algunos buenos consejos de depuración

Falla 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 en la consola sobre la falla

nscurl

La herramienta se ejecutará a través de varias combinaciones diferentes de excepciones ATS, intentando una conexión segura al host dado en cada configuración ATS e informando el resultado.

nscurl --ats-diagnostics https://example.com
onmyway133
fuente
1
Solo señale que nscurl solo está disponible en Mac OS X "El Capitan"
webo80
1
Un consejo más para la depuración, para comprobar qué cifrado de conexión TLS está utilizando su servidor: curl -v https: // <nombrehost>
André Morujão
1
¿Alguna idea sobre lo que puede causar el problema si curl PASS todos los pasos están bien?
Aston
@ onmyway133 ¿puede agregar una explicación sobre cómo "Establecer la variable de entorno CFNETWORK_DIAGNOSTICS a 1"?
YakirNa
1
@YakirNa puedes leer sobre cómo hacerlo aquí nshipster.com/launch-arguments-and-environment-variables es bastante sencillo :)
onmyway133
2

Si su backend usa una conexión segura y se obtiene usando 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 una conexión insegura mediante la configuración NSExceptionAllowsInsecureHTTPLoads = YES, en su lugar, debe Permitir seguridad reducida en caso de que su servidor no cumpla con el requisito mínimo (v1.2) para ATS (o mejor para arreglar el lado del servidor).

Permitir seguridad reducida a un ú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 el cliente openssl para investigar el certificado y obtenga la configuración de su servidor usando el cliente openssl:

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

..encuentra 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 conectarse usando ATS:

Los requisitos para una conexión de servicio web para usar App Transport Security (ATS) implican el servidor, los cifrados de conexión y los certificados, de la siguiente manera:

Los certificados deben estar firmados con uno de los siguientes tipos de claves:

  • Clave segura del algoritmo hash 2 (SHA-2) 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 dura y no hay conexión.

Los siguientes cifrados de conexión admiten el secreto directo (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 mínima del protocolo Protocolo: enlaces TLSv1

Idali
fuente
la pregunta sigue siendo si es posible interpretar información openssl para averiguar si el servidor cumple con los requisitos. También Protocolo: TLSv1 puede ser la versión makor en lugar de 1.x
Idali
Lo hago general, en caso de que use el puerto
Idali
La respuesta deja más preguntas abiertas que respondidas. Parece que un problema puede ser el mapeo entre los informes de OpenSL y la documentación de Apple. Desde la salida de openssl no es posible determinar si TLS 1.2 es compatible. La respuesta tampoco permite determinar si se admite Perfect Forward Secrecy.
zaph
2

Después de dos días de intentos y fracasos, lo que funcionó para mí es este código de womble

Con un cambio, de acuerdo con esta publicación , deberíamos dejar de usar subclaves asociadas con el diccionario NSExceptionDomains de ese tipo de Convención

  NSTemporaryExceptionMinimumTLSVersion

Y usar en la nueva Convención

  NSExceptionMinimumTLSVersion

en lugar.

documentación de apple

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>
yehoni amran
fuente
1

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
Ryan Heitner
fuente
muy útil para depurar el problema del certificado
Lopakhin
0

Este error aparecía en los registros a veces cuando estaba usando una versión iOS de Cordova con errores. Se fue cuando actualicé o degradé cordova iOS.

El servidor al que me estaba conectando estaba usando SSL TLSv1.2, así que sabía que ese no era el problema.

im3r3k
fuente
0

En su .plistarchivo de proyecto , agregue este permiso:

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

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>

ALOK KUMAR
fuente
0

Respuesta actualizada (post-WWDC 2016):

Las aplicaciones de iOS requerirán conexiones HTTPS seguras para finales de 2016. Intentar desactivar ATS puede hacer que su aplicación sea rechazada en el futuro.

App Transport Security, o ATS, es una característica 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á que ATS sea obligatorio para todos los desarrolladores que esperan enviar sus aplicaciones a la App Store. enlace

Paraneetharan Saravanaperumal
fuente
0

El dispositivo que probé tenía un tiempo incorrecto configurado. Entonces, cuando intenté acceder a una página con un certificado que se agotaría pronto, negaría el acceso porque el dispositivo había expirado. Para solucionarlo, configure el tiempo adecuado en el dispositivo.

Warpzit
fuente