CFNetwork SSLHandshake не удалось iOS 9

207

кто-нибудь с iOS 9 beta 1 имел эту проблему?

Я использую стандартную NSURLConnection для подключения к веб-сервису, и как только делается звонок в веб-сервис, я получаю следующую ошибку. Это в настоящее время работает в iOS 8.3

Возможная бета-ошибка? любые идеи или мысли будут великолепны! Я знаю, что это очень рано в разработке iOS 9

Вот полная ошибка:

Не удалось выполнить SSLHandshake в CFNetwork (-9824) Ошибка загрузки HTTP NSURLSession / NSURLConnection (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];
user3099837
источник

Ответы:

310

iOS 9 и OSX 10.11 требуют TLSv1.2 SSL для всех хостов, с которых вы планируете запрашивать данные, если вы не укажете домены исключений в файле Info.plist вашего приложения.

Синтаксис для конфигурации 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
App Transport Security (ATS) позволяет приложению добавить объявление в свой файл Info.plist, в котором указаны домены, с которыми ему необходимо защищенное соединение. ATS предотвращает случайное раскрытие, обеспечивает безопасное поведение по умолчанию и проста в применении. Вы должны принять ATS как можно скорее, независимо от того, создаете ли вы новое приложение или обновляете существующее. Если вы разрабатываете новое приложение, вы должны использовать исключительно HTTPS. Если у вас есть существующее приложение, вы должны использовать HTTPS как можно больше прямо сейчас и создать план для миграции остальной части вашего приложения как можно скорее.
user3099837
2
@StevenPeterson Эй, Стив, кажется, я не могу заставить работать пример домена исключений, у вас есть какие-то идеи случайно, я просто скопировал и вставил в .plist изменил TLSv1.1 на TLSv1.0 и домен в наш домен без https: // etc
user3099837
27
Извините за длинный чат, но я понял, что мне нужно отключить <key> NSTevenExceptionRequiresForwardSecrecy </ key> <false />
user3099837
2
@RashmiRanjanmallick NSTevenExceptionMinimumTLSVersion используется, чтобы сообщить ATS, что вы работаете с сервером не 1.2. Например, используйте это, если вы пытаетесь подключиться к хосту, который использует TLS 1.0. Вы также должны использовать NSTevenExceptionRequiresForwardSecrecy со значением false, как указано пользователем 3099837 выше.
Womble
2
ste.vn/2015/06/10/… - это блог, из которого получен ответ.
Шон Дев
66

В iOS 10+ строка TLS ДОЛЖНА иметь форму «TLSv1.0». Это не может быть просто «1.0». (Вздох)


Следующая комбинация других ответов работает.

Допустим, вы пытаетесь подключиться к хосту (YOUR_HOST.COM), который имеет только TLS 1.0.

Добавьте их в 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помогло мне, спасибо!
Джош Вальдивьесо
2
Эта версия не работала для меня на iOS9.1 - мне нужно было использовать строковый формат TLSVersion в одном из других ответов <key> NSTevenExceptionMinimumTLSVersion </ key> <string> TLSv1.1 </ string>
300 бод
Это работает, но мой вопрос: означает ли это, что мое приложение не использует ssl, когда эти параметры включены, а данные не зашифрованы?
TheDC
33

Для получения дополнительной информации Настройка исключений безопасности транспорта приложений в iOS 9 и OSX 10.11

Любопытно, что вы заметите, что соединение пытается изменить протокол http на https для защиты от ошибок в вашем коде, когда вы могли случайно неправильно настроить URL-адрес. В некоторых случаях это может на самом деле работать, но это также сбивает с толку.

Эта доставка приложения с приложением Transport Security охватывает несколько хороших советов по отладке.

ATS Failure

Большинство сбоев ATS будут представлены как CFErrors с кодом в серии -9800. Они определены в заголовке 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
onmyway133
источник
1
Только отметьте, что nscurl доступен только в Mac OS X «El Capitan»
webo80
1
Еще один совет по отладке, чтобы проверить, какой шифр TLS-соединения используется вашим сервером: curl -v https: // <имя хоста>
Андре Морухао,
1
Любые идеи о том, что может вызвать проблемы, если curl PASS все шаги нормально?
Астон
@ 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, вместо этого вам нужно разрешить пониженную безопасность в случае, если ваш сервер не соответствует минимальному требованию (v1.2) для ATS (или лучше исправить на стороне сервера).

Разрешение пониженной безопасности на один сервер

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

Требования к соединению веб-службы для использования App Transport Security (ATS) включают сервер, шифры соединений и сертификаты, а именно:

Сертификаты должны быть подписаны одним из следующих типов ключей:

  • Ключ Secure Hash Algorithm 2 (SHA-2) с длиной дайджеста не менее 256 (то есть SHA-256 или выше)

  • Ключ Elliptic-Curve Cryptography (ECC) размером не менее 256 бит

  • Ключ Rivest-Shamir-Adleman (RSA) длиной не менее 2048 битов. Недействительный сертификат приводит к серьезному отказу и отсутствию соединения.

Следующие шифры подключения поддерживают прямую секретность (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 предоставляет только минимальную версию протокола Protocol: TLSv1 links

Idali
источник
остается вопрос: можно ли интерпретировать информацию openssl, чтобы выяснить, соответствует ли сервер требованиям? Также Протокол: TLSv1 может быть макор версия вместо 1.x
Идали
Я делаю это вообще, в случае использования порта
Idali
Ответ оставляет больше вопросов, чем ответил. Кажется, проблема может заключаться в сопоставлении отчетов openssl и документации Apple. Из вывода openssl невозможно определить, поддерживается ли TLS 1.2. Ответ также не позволяет определить, поддерживается ли Perfect Forward Secrecy.
Заф
2

После двух дней попыток и неудач у меня сработал этот код womble

с одним изменением, согласно этому посту, мы должны прекратить использование подключей, связанных со словарем 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
Райан Хайтнер
источник
очень полезно для отладки проблемы с сертификатом
Лопахин
0

Эта ошибка появлялась в журналах иногда, когда я использовал глючную / сбойную версию Cordova для iOS. Это ушло, когда я обновил или понизил Cordova iOS.

Сервер, к которому я подключался, использовал TLSv1.2 SSL, поэтому я знал, что это не проблема.

im3r3k
источник
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

Обновленный ответ (после WWDC 2016):

Приложениям iOS потребуются безопасные соединения HTTPS к концу 2016 года. Попытка выключить ATS может привести к отклонению вашего приложения в будущем.

App Transport Security, или ATS, - это функция, которую Apple представила в iOS 9. Когда ATS включена, она заставляет приложение подключаться к веб-службам через соединение HTTPS, а не через незащищенный HTTP.

Однако разработчики могут отключить ATS и разрешить своим приложениям отправлять данные через HTTP-соединение, как указано в ответах выше. В конце 2016 года Apple сделает ATS обязательной для всех разработчиков, которые надеются представить свои приложения в App Store. ссылка на сайт

Paraneetharan Saravanaperumal
источник
0

На устройстве, которое я тестировал, было установлено неправильное время. Поэтому, когда я пытался получить доступ к странице с сертификатом, который скоро закончится, он будет запрещать доступ, потому что срок действия сертификата истек. Чтобы исправить, установите правильное время на устройстве!

Warpzit
источник