CFNetwork SSLHandshake가 iOS 9에 실패했습니다.


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

나는 webservice에 연결하기 위해 표준 NSURLConnection을 사용하고 webservice에 대한 호출이 이루어 지 자마자 아래 오류가 발생합니다. 현재 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];


Answers



iOS 9 및 OSX 10.11에서는 앱의 Info.plist 파일에 예외 도메인을 지정하지 않으면 데이터를 요청하려는 모든 호스트에 대해 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 베타에 대한 중요 참고 사항 : **

iOS 10에서 TLS 문자열은 "TLSv1.0"형식이어야합니다. "1.0"일 수는 없습니다. 예, 이것은 어리 석고 app-breaking입니다. iOS 개발에 오신 것을 환영합니다.

위의 조언의 다음 조합이 작동합니다.

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에서 App Transport Security 예외 구성

궁금한 점은 실수로 URL을 잘못 구성했을 수있는 코드의 실수를 막기 위해 http 프로토콜을 https로 변경하려고 시도한다는 것입니다. 경우에 따라서는 실제로 작동하지만 혼란 스러울 수도 있습니다.

앱 전송 보안적용된 앱 배송 에는 몇 가지 유용한 디버깅 팁이 나와 있습니다.

ATS 실패

대부분의 ATS 실패는 -9800 시리즈의 코드와 함께 CFErrors로 표시됩니다. 이들은 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에 대해 최소 요구 사항 (v1.2)을 충족하지 못하거나 서버 측을 수정하는 데 더 적합하지 않은 경우 NSExceptionAllowsInsecureHTTPLoads = YES 보안 허용 이 필요합니다.

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

<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 (응용 프로그램 전송 보안)에는 TLS (전송 계층 보안) 프로토콜 버전 1.2가 필요합니다.

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

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

인증서는 다음 유형의 키 중 하나를 사용하여 서명해야합니다.

  • 다이제스트 길이가 256 이상인 SHA-2 (Secure Hash Algorithm 2) 키 (즉, SHA-256 이상)
  • 최소 256 비트 크기의 Elliptic-Curve Cryptography (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

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




2 일간의 시도와 실패 후에 나에게 도움이 된 것은

하나의 변경으로,이 게시물 에 따르면 우리는 그 종류의 협약의 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 버전을 사용할 때 로그에 표시되는 경우가있었습니다. 내가 cordoz iOS를 업그레이드하거나 다운 그레이드했을 때 사라졌습니다.

내가 연결하고 있던 서버는 TLSv1.2 SSL을 사용하여 문제가 아님을 알았습니다.




프로젝트에서 .plist 파일에 다음 권한 추가 :

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



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>




업데이트 된 답변 (WWDC 2016 이후) :

iOS 앱에는 2016 년 말까지 보안 HTTPS 연결이 필요합니다. ATS를 사용 중지하면 향후 앱이 거부 될 수 있습니다.

App Transport Security (ATS)는 Apple에서 iOS 9에 도입 한 기능입니다. ATS를 사용하면 앱이 보안되지 않은 HTTP 대신 HTTPS 연결을 통해 웹 서비스에 연결됩니다.

그러나 개발자는 여전히 위의 답변에서 언급 한 것처럼 ATS를 해제하고 앱이 HTTP 연결을 통해 데이터를 보낼 수 있도록 허용 할 수 있습니다. 2016 년 말에 애플은 앱 스토어에 앱을 제출하기를 희망하는 모든 개발자에게 ATS를 의무화 할 예정이다. 링크




왜 그렇게 복잡한 지 -

iOS 개발 타겟 설정 - 8.0

그리고 Cmd + Shift + K




테스트 한 기기에 잘못된 시간이 설정되었습니다. 그래서 곧 인증서가 만료 된 페이지에 액세스하려고 시도했을 때 인증서가 만료되었지만 액세스가 거부되었으므로 액세스가 거부되었습니다. 문제를 해결하려면 기기에서 적절한 시간을 설정하십시오!




아래 info.plist 또는 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>