CFNetwork SSLHandshake 失败 iOS 9

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30720813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:16:18  来源:igfitidea点击:

CFNetwork SSLHandshake failed iOS 9

iossslnsurlconnectionios9

提问by user3099837

has anyone with the iOS 9 beta 1 had this issue?

有 iOS 9 beta 1 的人有这个问题吗?

I use standard NSURLConnection to connect to a webservice and as soon as a call is made to the webservice i get the below error. This is currently working in iOS 8.3

我使用标准 NSURLConnection 连接到网络服务,一旦调用网络服务,我就会收到以下错误。这目前在 iOS 8.3 中工作

Possible beta bug? any ideas or thoughts would be great ! I know its very early in iOS 9 development

可能的测试版错误?任何想法或想法都会很棒!我知道它在 iOS 9 开发的早期

Here is the full error:

这是完整的错误:

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

CFNetwork SSLHandshake 失败 (-9824) NSURLSession/NSURLConnection 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];

回答by Steven Peterson

iOS 9 and OSX 10.11 require TLSv1.2 SSL for all hosts you plan to request data from unless you specify exception domains in your app's Info.plist file.

除非您在应用程序的 Info.plist 文件中指定异常域,否则 iOS 9 和 OSX 10.11 要求您计划从中请求数据的所有主机都使用 TLSv1.2 SSL。

The syntax for the Info.plist configuration looks like this:

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

If your application (a third-party web browser, for instance) needs to connect to arbitrary hosts, you can configure it like this:

如果您的应用程序(例如第三方 Web 浏览器)需要连接到任意主机,您可以像这样配置它:

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

If you're having to do this, it's probably best to update your servers to use TLSv1.2 and SSL, if they're not already doing so. This should be considered a temporary workaround.

如果您必须这样做,最好更新您的服务器以使用 TLSv1.2 和 SSL,如果他们还没有这样做的话。这应被视为一种临时解决方法。

As of today, the prerelease documentation makes no mention of any of these configuration options in any specific way. Once it does, I'll update the answer to link to the relevant documentation.

截至今天,预发布文档未以任何特定方式提及任何这些配置选项。一旦完成,我将更新答案以链接到相关文档。

回答by Womble

In iOS 10+, the TLS string MUST be of the form "TLSv1.0". It can't just be "1.0". (Sigh)

在 iOS 10+ 中,TLS 字符串必须采用“TLSv1.0”形式。它不能只是“1.0”。(叹)



The following combination of the other Answers works.

其他答案的以下组合有效。

Let's say you are trying to connect to a host (YOUR_HOST.COM) that only has TLS 1.0.

假设您正在尝试连接到只有 TLS 1.0 的主机 (YOUR_HOST.COM)。

Add these to your app's Info.plist

将这些添加到您的应用程序的 Info.plist

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

回答by onmyway133

For more info Configuring App Transport Security Exceptions in iOS 9 and OSX 10.11

有关详细信息,请在 iOS 9 和 OSX 10.11 中配置应用程序传输安全例外

Curiously, you'll notice that the connection attempts to change the http protocol to https to protect against mistakes in your code where you may have accidentally misconfigured the URL. In some cases, this might actually work, but it's also confusing.

奇怪的是,您会注意到连接尝试将 http 协议更改为 https 以防止代码中出现错误,因为您可能不小心错误地配置了 URL。在某些情况下,这可能确实有效,但也令人困惑。

This Shipping an App With App Transport Securitycovers some good debugging tips

这篇使用 App Transport Security 发布 App涵盖了一些很好的调试技巧

ATS Failure

ATS 故障

Most ATS failures will present as CFErrors with a code in the -9800 series. These are defined in the Security/SecureTransport.h header

大多数 ATS 故障将显示为带有 -9800 系列代码的 CFError。这些在 Security/SecureTransport.h 头文件中定义

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

CFNETWORK_DIAGNOSTICS

CFNETWORK_DIAGNOSTICS

Set the environment variable CFNETWORK_DIAGNOSTICS to 1 in order to get more information on the console about the failure

将环境变量 CFNETWORK_DIAGNOSTICS 设置为 1,以便在控制台上获取有关失败的更多信息

nscurl

卷曲

The tool will run through several different combinations of ATS exceptions, trying a secure connection to the given host under each ATS configuration and reporting the result.

该工具将运行几种不同的 ATS 异常组合,在每个 ATS 配置下尝试与给定主机的安全连接并报告结果。

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

回答by Idali

If your backend uses a secure connection ant you get using NSURLSession

如果您的后端使用安全连接蚂蚁,您将使用 NSURLSession

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

you need to check your server configuration especially to get ATS version and SSL certificate Info:

您需要检查您的服务器配置,尤其是要获取 ATS 版本和 SSL 证书信息:

Instead of just Allowing Insecure Connectionby setting NSExceptionAllowsInsecureHTTPLoads = YES, instead you need to Allow Lowered Securityin case your server do not meet the min requirement (v1.2) for ATS (or better to fix server side).

而不是通过设置允许不安全连接NSExceptionAllowsInsecureHTTPLoads = YES,相反,您需要允许降低安全性,以防您的服务器不满足 ATS 的最低要求 (v1.2)(或更好地修复服务器端)。

Allowing Lowered Security to a Single Server

允许降低单个服务器的安全性

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

use openssl client to investigate certificate and get your server configuration using openssl client :

使用 openssl 客户端调查证书并使用 openssl 客户端获取服务器配置:

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

..find at the end

..找到最后

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) require Transport Layer Security (TLS) protocol version 1.2.

应用传输安全 (ATS) 需要传输层安全 (TLS) 协议版本 1.2。

Requirements for Connecting Using ATS:

使用 ATS 连接的要求:

The requirements for a web service connection to use App Transport Security (ATS) involve the server, connection ciphers, and certificates, as follows:

Certificates must be signed with one of the following types of keys:

  • Secure Hash Algorithm 2 (SHA-2) key with a digest length of at least 256 (that is, SHA-256 or greater)
  • Elliptic-Curve Cryptography (ECC) key with a size of at least 256 bits

  • Rivest-Shamir-Adleman (RSA) key with a length of at least 2048 bits An invalid certificate results in a hard failure and no connection.

The following connection ciphers support forward secrecy (FS) and work with 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

Web 服务连接使用 App Transport Security (ATS) 的要求涉及服务器、连接密码和证书,如下所示:

必须使用以下类型的密钥之一签署证书:

  • 摘要长度至少为 256(即 SHA-256 或更大)的安全哈希算法 2 (SHA-2) 密钥
  • 大小至少为 256 位的椭圆曲线加密 (ECC) 密钥

  • 长度至少为 2048 位的 Rivest-Shamir-Adleman (RSA) 密钥无效证书会导致硬故障和无连接。

以下连接密码支持前向保密 (FS) 并与 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: it turns out that openssl only provide the minimal protocol version Protocol : TLSv1 links

更新:事实证明,openssl 只提供最小协议版本协议:TLSv1 链接

回答by yehoni amran

After two days of attempts and failures, what worked for me is this code of womble

经过两天的尝试和失败,对我有用的是这个womble代码

with One change, according to this postwe should stop using sub-keys associated with the NSExceptionDomainsdictionary of that kind of Convention

有一个变化,根据这篇文章,我们应该停止使用与那种约定的NSExceptionDomains字典关联的子键

  NSTemporaryExceptionMinimumTLSVersion

And use at the new Convention

并在新公约中使用

  NSExceptionMinimumTLSVersion

instead.

反而。

apple documentation

苹果文档

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

回答by Ryan Heitner

Another useful tool is nmap (brew install nmap)

另一个有用的工具是 nmap (brew install nmap)

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

Gives 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

回答by Warpzit

The device I tested at had wrong time set. So when I tried accessing a page with a certificate that would run out soon it would deny access because the device though the certificate had expired. To fix, set proper time on the device!

我测试的设备设置了错误的时间。因此,当我尝试使用即将用完的证书访问页面时,它会拒绝访问,因为该设备虽然证书已过期。要修复,请在设备上设置适当的时间!

回答by im3r3k

This error was showing up in the logs sometimes when I was using a buggy/crashy Cordova iOS version. It went away when I upgraded or downgraded cordova iOS.

当我使用有问题的/崩溃的 Cordova iOS 版本时,有时会在日志中显示此错误。当我升级或降级cordova iOS时它就消失了。

The server I was connecting to was using TLSv1.2 SSL so I knew that was not the problem.

我连接的服务器使用的是 TLSv1.2 SSL,所以我知道这不是问题所在。

回答by Hiren Dhamecha

In your project .plistfile in add this permission :

在您的项目 .plist文件中添加此权限:

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

回答by ALOK KUMAR

The syntax for the Info.plist 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>