[ios] CFNetwork SSLHandshake가 iOS 9에 실패했습니다

iOS 9 베타 1을 사용하는 사람 에게이 문제가 있습니까?

표준 NSURLConnection을 사용하여 웹 서비스에 연결하고 웹 서비스를 호출하자마자 아래 오류가 발생합니다. 이것은 현재 iOS 8.3에서 작동합니다

가능한 베타 버그? 어떤 아이디어 나 생각이라도 좋을 것입니다! iOS 9 개발 초기에 알고 있습니다

전체 오류는 다음과 같습니다.

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



답변

앱의 Info.plist 파일에 예외 도메인을 지정하지 않으면 iOS 9 및 OSX 10.11에는 데이터를 요청하려는 모든 호스트에 대해 TLSv1.2 SSL이 필요합니다.

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>

응용 프로그램 (예 : 타사 웹 브라우저)이 임의의 호스트에 연결해야하는 경우 다음과 같이 구성 할 수 있습니다.

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

이 작업을 수행해야하는 경우 TLSv1.2 및 SSL을 사용하도록 아직 업데이트하지 않은 경우 서버를 업데이트하는 것이 가장 좋습니다. 이는 임시 해결 방법으로 간주되어야합니다.

현재 시험판 문서에서는 이러한 구성 옵션에 대해 특정 방식으로 언급하지 않습니다. 일단 완료되면 관련 문서로 연결되도록 답변을 업데이트하겠습니다.


답변

iOS 10 이상에서 TLS 문자열은 “TLSv1.0″형식이어야합니다. 단지 “1.0”일 수 없습니다. (한숨)


다른 답변의 다음 조합이 작동합니다.

TLS 1.0 만있는 호스트 (YOUR_HOST.COM)에 연결하려고한다고 가정 해 봅시다.

이것을 앱의 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>


답변

자세한 내용 iOS 9 및 OSX 10.11에서 앱 전송 보안 예외 구성

흥미롭게도 연결에서 실수로 URL을 잘못 구성했을 수있는 코드의 실수로부터 보호하기 위해 http 프로토콜을 https로 변경하려고 시도합니다. 경우에 따라 실제로 작동 할 수도 있지만 혼동되기도합니다.

App Transport Security와 함께 앱 배송에는 유용한 디버깅 팁이 포함되어 있습니다.

ATS 실패

대부분의 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를 1로 설정하십시오.

nscurl

이 도구는 여러 가지 ATS 예외 조합을 통해 실행되어 각 ATS 구성에서 지정된 호스트에 대한 보안 연결을 시도하고 결과를보고합니다.

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


답변

백엔드가 보안 연결 개미를 사용하는 경우 NSURLSession을 사용합니다.

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

특히 ATS 버전 및 SSL 인증서 정보를 얻으려면 서버 구성을 확인해야합니다.

대신의 안전하지 않은 연결 허용 설정에 의해을 NSExceptionAllowsInsecureHTTPLoads = YES, 대신 당신은 할 필요가 보안을 낮춘 허용 하는 경우 귀하의 ATS에 대한 최소 요구 사항 (1.2)을 만족하지 않는 서버 (또는 더 나은 수정 서버 측에)에서.

단일 서버에 대한 보안 저하 허용

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

openssl 클라이언트를 사용하여 인증서를 조사하고 openssl 클라이언트를 사용하여 서버 구성을 얻으십시오.

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

.. 끝에서 찾기

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)

ATS (App Transport Security)에는 TLS (Transport Layer Security) 프로토콜 버전 1.2가 필요합니다.

ATS를 사용하여 연결하기위한 요구 사항 :

ATS (App Transport Security)를 사용하기위한 웹 서비스 연결 요구 사항에는 다음과 같이 서버, 연결 암호 및 인증서가 포함됩니다.

인증서는 다음 유형의 키 중 하나로 서명해야합니다.

  • 다이제스트 길이가 최소 256 (SHA-256 이상) 인 보안 해시 알고리즘 2 (SHA-2) 키

  • 최소 256 비트 크기의 ECC (Elliptic-Curve Cryptography) 키

  • 길이가 2048 비트 이상인 RSA (Rivest-Shamir-Adleman) 키 인증서가 유효하지 않으면 하드 오류가 발생하고 연결되지 않습니다.

다음 연결 암호는 FS (Forward Secrecy)를 지원하고 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

업데이트 : openssl은 최소 프로토콜 버전 만 제공합니다. 프로토콜 : TLSv1 링크


답변

이틀간의 시도와 실패 후, 나를 위해 일한 것은이 럼블 코드입니다 .

게시물 에 따르면 한 번의 변경 으로 해당 컨벤션 의 NSExceptionDomains 사전 과 관련된 하위 키 사용을 중지해야합니다

  NSTemporaryExceptionMinimumTLSVersion

그리고 새로운 협약에서 사용

  NSExceptionMinimumTLSVersion

대신에.

사과 문서

내 코드

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


답변

또 다른 유용한 도구는 nmap (brew install nmap)입니다.

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

출력 제공

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


답변

이 오류는 버그가 있거나 거친 Cordova iOS 버전을 사용할 때 때때로 로그에 표시되었습니다. 나는 cordova iOS를 업그레이드하거나 다운 그레이드했을 때 사라졌습니다.

연결하려는 서버가 TLSv1.2 SSL을 사용하고 있었으므로 문제가 아니라는 것을 알았습니다.