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


207

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

답변:


310

앱의 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을 사용하도록 아직 업데이트하지 않은 경우 서버를 업데이트하는 것이 가장 좋습니다. 이는 임시 해결 방법으로 간주되어야합니다.

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


1
앱 전송 보안 (ATS)을 통해 앱은 Info.plist 파일에 보안 통신이 필요한 도메인을 지정하는 선언을 추가 할 수 있습니다. ATS는 우발적 인 공개를 방지하고 안전한 기본 동작을 제공하며 쉽게 채택 할 수 있습니다. 새 앱을 만들거나 기존 앱을 업데이트하는지 여부에 관계없이 가능한 한 빨리 ATS를 채택해야합니다. 새로운 앱을 개발하는 경우 HTTPS를 독점적으로 사용해야합니다. 기존 앱이있는 경우 지금 가능한 한 HTTPS를 사용하고 가능한 한 빨리 나머지 앱을 마이그레이션 할 계획을 만들어야합니다.
user3099837 2016 년

2
@StevenPeterson 안녕하세요 steve 나는 예외 도메인 예제가 작동하지 않는 것 같습니다. 우연히 아이디어가 있습니까? 방금 복사하여 .plist에 붙여 넣었습니다. // etc
user3099837 2016 년

27
긴 대화에 대해 죄송하지만 알아 차리면 <key> NSTemporaryExceptionRequiresForwardSecrecy </ key> <false />를 비활성화해야합니다.
user3099837

2
@RashmiRanjanmallick NSTemporaryExceptionMinimumTLSVersion은 1.2가 아닌 서버에서 작업 중임을 ATS에 알리는 데 사용됩니다. 예를 들어, TLS 1.0을 사용하는 호스트에 연결하려는 경우이를 사용하십시오. user3099837이 위에 표시된대로 NSTemporaryExceptionRequiresForwardSecrecy를 false로 설정해야합니다.
Womble

2
ste.vn/2015/06/10/…- 이 블로그는 답변의 출처입니다.
Sean Dev

66

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>

9
추가하면 NSTemporaryExceptionRequiresForwardSecrecy나를 위해 속임수가 된 것 같습니다 . 감사합니다!
Josh Valdivieso

2
이 버전은 iOS9.1에서 작동하지 않았습니다. 다른 답변 <key> NSTemporaryExceptionMinimumTLSVersion </ key> <string>
TLSv1.1

이것은 작동하지만 내 질문은 :이 매개 변수가 켜져 있고 데이터가 암호화되지 않은 경우 내 앱이 ssl을 사용하지 않는다는 것을 의미합니까?
theDC

33

자세한 내용 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

1
nscurl이 Mac OS X "El Capitan"에서만 가능하다는 점만 지적하십시오
webo80

1
하나는 더 TLS 연결 암호가 서버에 의해 사용되는 검사로, 팁 디버깅 : 컬 -v은 https : // <호스트 이름>
앙드레 Morujão

1
curl이 모든 단계를 제대로 통과하면 문제를 일으킬 수있는 사항에 대한 아이디어가 있습니까?
Aston

@ onmyway133 "환경 변수 CFNETWORK_DIAGNOSTICS를 1로 설정하는 방법"에 대한 설명을 추가 할 수 있습니까?
YakirNa

1
@ YakirNa 당신은 그것을 하는 방법에 대해 읽을 수 있습니다 여기 nshipster.com/launch-arguments-and-environment-variables 그것은 매우 간단합니다 :)
onmyway133

2

백엔드가 보안 연결 개미를 사용하는 경우 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 링크


문제는 서버가 요구 사항을 충족하는지 확인하기 위해 openssl 정보를 해석 할 수 있다는 것입니다. 또한 프로토콜 : TLSv1은 1.x 대신 makor 버전 일 수 있습니다.
Idali

나는 포트를 사용하는 경우에 그것을 일반적으로 만든다
Idali

답변은 답변보다 많은 질문을 공개합니다. openssl이보고하는 내용과 Apple 설명서 간의 매핑이 문제 일 수 있습니다. openssl 출력에서 ​​TLS 1.2가 지원되는지 판별 할 수 없습니다. 또한 정답 공개가 지원되는지 여부를 결정할 수 없습니다.
zaph December

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>

1

또 다른 유용한 도구는 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

인증서 문제를 디버깅하는 데 매우 유용
Lopakhin

0

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

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


0

프로젝트 .plist파일에서 다음 권한을 추가하십시오.

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

0

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>


0

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

iOS 앱은 2016 년 말까지 보안 HTTPS 연결이 필요합니다. ATS를 끄려고하면 나중에 앱이 거부 될 수 있습니다.

ATS (App Transport Security)는 Apple이 iOS 9에서 도입 한 기능입니다. ATS가 활성화되면 앱이 비보안 HTTP가 아닌 HTTPS 연결을 통해 웹 서비스에 연결되도록합니다.

그러나 개발자는 여전히 위의 답변에서 언급 한 것처럼 ATS를 끄고 앱이 HTTP 연결을 통해 데이터를 보내도록 허용 할 수 있습니다. 2016 년 말, Apple은 앱을 App Store에 제출하고자하는 모든 개발자에게 ATS를 의무화 할 것입니다. 링크


0

테스트 한 장치의 시간이 잘못 설정되었습니다. 따라서 곧 만료 될 인증서로 페이지에 액세스하려고하면 인증서가 만료되었지만 장치가 있기 때문에 액세스가 거부됩니다. 해결하려면 장치에서 적절한 시간을 설정하십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.