Запрос был прерван: не удалось создать безопасный канал SSL/TLS

Мы не можем подключиться к серверу HTTPS с помощью WebRequest из-за этого сообщения об ошибке:

The request was aborted: Could not create SSL/TLS secure channel.

Мы знаем, что на сервере нет действительного сертификата HTTPS с используемым путем, но для обхода этой проблемы мы используем следующий код, который мы взяли из другого поста Stackru:

private void Somewhere() {
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}

private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
   return true;
}

Проблема в том, что сервер никогда не проверяет сертификат и завершается с ошибкой выше. Кто-нибудь знает, что мне делать?


Я должен упомянуть, что мы с коллегой проводили тесты несколько недель назад, и это работало нормально с чем-то похожим на то, что я написал выше. Единственное "основное отличие", которое мы обнаружили, заключается в том, что я использую Windows 7, а он - Windows XP. Это что-то меняет?

53 ответа

Решение

Я наконец нашел ответ (я не отметил свой источник, но это было от поиска);

Пока код работает в Windows XP, в Windows 7 вы должны добавить это в начале:

// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons

И сейчас все работает отлично.


ДОПОЛНЕНИЕ

Как упомянул Робин Френч; если вы столкнулись с этой проблемой при настройке PayPal, обратите внимание, что они не будут поддерживать SSL3 начиная с 3 декабря 2018 года. Вам нужно будет использовать TLS. Вот страница Paypal об этом.

Решение этой проблемы в.NET 4.5

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Если у вас нет.NET 4.5, используйте

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

Убедитесь, что параметры ServicePointManager заданы до выполнения запроса HttpWebRequest, иначе он не будет работать.

Работает:

        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
               | SecurityProtocolType.Tls11
               | SecurityProtocolType.Tls12
               | SecurityProtocolType.Ssl3;

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")

Сбой:

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")

        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
               | SecurityProtocolType.Tls11
               | SecurityProtocolType.Tls12
               | SecurityProtocolType.Ssl3;

Одна из основных причин этой проблемы - активная версия.NET Framework. Версия среды выполнения.NET framework влияет на то, какие протоколы безопасности включены по умолчанию.

Похоже, что нет какой-либо авторитетной документации о том, как это конкретно работает в разных версиях, но кажется, что значения по умолчанию определены более или менее следующим образом:

  • .NET Framework 4.5 и более ранние версии - SSL 3.0, TLS 1.0
  • .NET Framework 4.6.x - TLS 1.0, 1.1, 1.2, 1.3.
  • .NET Framework 4.7+ - Система (ОС) по умолчанию

(Для более старых версий ваш пробег может несколько отличаться в зависимости от того, какие среды выполнения.NET установлены в системе. Например, может возникнуть ситуация, когда вы используете очень старую структуру, а TLS 1.0 не поддерживается, или используете 4.6. x и TLS 1.3 не поддерживаются)

В документации Microsoft настоятельно рекомендуется использовать 4.7+ и системные настройки по умолчанию:

Мы рекомендуем вам:

  • Установите для своих приложений целевой.NET Framework 4.7 или более поздние версии. Установите целевой.NET Framework 4.7.1 или более поздние версии в свои приложения WCF.
  • Не указывайте версию TLS. Настройте свой код, чтобы ОС определяла версию TLS.
  • Выполните тщательный аудит кода, чтобы убедиться, что вы не указываете версию TLS или SSL.

Для сайтов ASP.NET: проверьтеtargetFramework версия в вашем <httpRuntime> элемент, так как он (при наличии) определяет, какая среда выполнения фактически используется вашим сайтом:

<httpRuntime targetFramework="4.5" />

Лучше:

<httpRuntime targetFramework="4.7" />

У меня была эта проблема при попытке попасть на https://ct.mob0.com/Styles/Fun.png, который представляет собой изображение, распространяемое CloudFlare на его CDN и поддерживающее такие сумасшедшие вещи, как SPDY и странные сертификаты перенаправления SSL.

Вместо того, чтобы указывать Ssl3, как в ответе Саймонса, я смог исправить это, перейдя к Tls12 следующим образом:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");

Проблема в том, что у пользователя aspNet нет доступа к сертификату. Вы должны дать доступ, используя winhttpcertcfg.exe

Пример того, как это настроить, находится по адресу: http://support.microsoft.com/kb/901183

В шаге 2 в дополнительной информации

РЕДАКТИРОВАТЬ: в более поздних версиях IIS эта функция встроена в инструмент диспетчера сертификатов - и получить к нему доступ можно щелкнув правой кнопкой мыши на сертификате и используя опцию для управления закрытыми ключами. Более подробная информация здесь: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791

После многих долгих часов с этой же проблемой я обнаружил, что учетная запись ASP.NET, под которой работала клиентская служба, не имела доступа к сертификату. Я исправил это, перейдя в пул приложений IIS, под которым работает веб-приложение, перейдя в Дополнительные настройки и изменив Идентичность на LocalSystem счет от NetworkService,

Лучшее решение - заставить сертификат работать по умолчанию NetworkService учетная запись, но это работает для быстрого функционального тестирования.

Ошибка является общей, и существует множество причин, по которым согласование SSL/TLS может завершиться неудачей. Наиболее распространенным является недействительный или просроченный серверный сертификат, и вы позаботились об этом, предоставив собственный хук проверки сертификата сервера, но это не обязательно является единственной причиной. Сервер может требовать взаимной аутентификации, он может быть настроен с набором шифров, не поддерживаемых вашим клиентом, он может иметь слишком большой временной сдвиг для успешного установления связи и многие другие причины.

Лучшее решение - использовать набор инструментов для устранения неполадок SChannel. SChannel - поставщик SSPI, отвечающий за SSL и TLS, и ваш клиент будет использовать его для рукопожатия. Взгляните на Инструменты и настройки TLS/SSL.

Также смотрите Как включить ведение журнала событий Schannel.

Подход с настройкой

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

Кажется, все в порядке, потому что Tls1.2 - это последняя версия защищенного протокола. Но я решил взглянуть глубже и ответить, действительно ли нам нужно это жестко кодировать.

Технические характеристики: Windows Server 2012R2 x64.

Из Интернета сообщается, что.NetFramework 4.6+ по умолчанию должен использовать Tls1.2. Но когда я обновил свой проект до 4.6, ничего не произошло. Я нашел некоторую информацию, которая говорит, что мне нужно вручную внести некоторые изменения, чтобы включить Tls1.2 по умолчанию.

https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi

Но предлагаемое обновление Windows не работает для версии R2

Но мне помогло добавление двух значений в реестр. Вы можете использовать следующий сценарий PS, чтобы они добавились автоматически

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord

Это то, что я искал. Но все же я не могу ответить на вопрос, почему NetFramework 4.6+ не устанавливает это... значение протокола автоматически?

Еще одна возможная причина The request was aborted: Could not create SSL/TLS secure channel ошибка - это несоответствие между настроенными значениями cipher_suites вашего клиентского ПК и значениями, которые сервер настроил как желающие и способные принять. В этом случае, когда ваш клиент отправляет список значений cipher_suites, которые он может принять в своем первоначальном сообщении SSL Client handshaking/gotiation "Client Hello", сервер видит, что ни одно из предоставленных значений не является приемлемым, и может возвратить "Alert" msgstr "ответ вместо перехода к шагу" Server Hello "при установлении связи SSL.

Чтобы исследовать эту возможность, вы можете загрузить Microsoft Message Analyzer и использовать его для запуска трассировки по согласованию SSL, которое происходит, когда вы пытаетесь и не можете установить HTTPS-соединение с сервером (в вашем приложении C#).

Если вы можете установить успешное HTTPS-соединение из другой среды (например, с компьютера с Windows XP, о котором вы упомянули - или, возможно, нажав URL-адрес HTTPS в браузере не от Microsoft, который не использует настройки набора шифров ОС, такие как Chrome или Firefox), запустите другую трассировку Message Analyzer в этой среде, чтобы зафиксировать, что происходит при успешном согласовании SSL.

Надеюсь, вы увидите некоторое различие между двумя сообщениями Client Hello, которые позволят вам точно определить, что из-за сбоя при согласовании SSL приводит к сбою. Тогда вы сможете внести изменения в конфигурацию Windows, что позволит ей добиться успеха. IISCrypto - отличный инструмент для этого (даже для клиентских ПК, несмотря на название "IIS").

Следующие два раздела реестра Windows управляют значениями cipher_suites, которые будет использовать ваш компьютер:

  • HKLM \ SOFTWARE \ Policies \ Microsoft \ Cryptography \ Configuration \ SSL \ 00010002
  • HKLM \ SYSTEM \ CurrentControlSet \ Control \ Cryptography \ Configuration \ Local \ SSL \ 00010002

Вот полное описание того, как я исследовал и раскрыл пример этого разнообразия Could not create SSL/TLS secure channel проблема: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html

Что-то оригинального ответа не было. Я добавил еще немного кода, чтобы сделать его пуленепробиваемым.

ServicePointManager.Expect100Continue = true;
        ServicePointManager.DefaultConnectionLimit = 9999;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;

Наконец-то нашел для меня решение.

Попробуйте добавить следующую строку перед вызовом https url (для .Net framework 4.5):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Ответа с наибольшим количеством голосов, вероятно, будет достаточно для большинства людей. Однако в некоторых случаях вы можете продолжить получать сообщение об ошибке "Не удалось создать безопасный канал SSL/TLS" даже после принудительного использования TLS 1.2. Если это так, вы можете обратиться к этой полезной статье для дополнительных шагов по устранению неполадок. Подводя итог: независимо от проблемы версии TLS/SSL, клиент и сервер должны договориться о "наборе шифров". На этапе "рукопожатия" SSL-соединения клиент перечислит свои поддерживаемые комплекты шифров, которые сервер будет проверять по собственному списку. Но на некоторых машинах Windows некоторые общие наборы шифров могли быть отключены (по-видимому, из-за благих намерений попыток ограничить поверхность атаки), уменьшая вероятность того, что клиент и сервер согласятся на набор шифров. Если они не могут договориться, то вы можете увидеть "код фатального оповещения 40" в средстве просмотра событий и "Не удалось создать безопасный канал SSL/TLS" в вашей программе.NET.

В вышеупомянутой статье объясняется, как составить список всех потенциально поддерживаемых комплектов шифров компьютера и включить дополнительные комплекты шифров через реестр Windows. Чтобы проверить, какие наборы шифров включены на клиенте, попробуйте посетить эту диагностическую страницу в MSIE. (Использование трассировки System.Net может дать более точные результаты.) Чтобы проверить, какие наборы шифров поддерживаются сервером, попробуйте этот онлайн-инструмент (при условии, что сервер доступен через Интернет). Само собой разумеется, что изменения в реестре должны выполняться с осторожностью, особенно когда речь идет о работе сети. (Является ли ваша машина виртуальной машиной, размещенной на удаленном компьютере? Если вы нарушите работу сети, будет ли она вообще доступна?)

В случае моей компании мы включили несколько дополнительных наборов "ECDHE_ECDSA" через редактирование реестра, чтобы исправить непосредственную проблему и предотвратить будущие проблемы. Но если вы не можете (или не хотите) редактировать реестр, то на ум приходят многочисленные обходные пути (не обязательно красивые). Например: ваша.NET-программа может делегировать свой SSL-трафик отдельной программе Python (которая может сама работать, по той же причине, по которой запросы Chrome могут выполняться успешно, когда запросы MSIE не выполняются на зараженной машине).

Этот работает для меня в веб-клиенте MVC

    public string DownloadSite(string RefinedLink)
    {
        try
        {
            Uri address = new Uri(RefinedLink);

            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            using (WebClient webClient = new WebClient())
            {
                var stream = webClient.OpenRead(address);
                using (StreamReader sr = new StreamReader(stream))
                {
                    var page = sr.ReadToEnd();

                    return page;
                }
            }

        }
        catch (Exception e)
        {
            log.Error("DownloadSite - error Lin = " + RefinedLink, e);
            return null;
        }
    }

Исключение "Запрос был прерван: не удалось создать безопасный канал SSL/TLS", если сервер возвращает HTTP 401 Несанкционированный ответ на запрос HTTP.

Вы можете определить, происходит ли это, включив ведение журнала System.Net уровня трассировки для своего клиентского приложения, как описано в этом ответе.

Как только эта конфигурация журнала будет создана, запустите приложение и воспроизведите ошибку, а затем найдите в выходных данных журнала следующую строку:

System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.

В моей ситуации мне не удалось установить определенный файл cookie, который ожидал сервер, что привело к тому, что сервер ответил на запрос с ошибкой 401, что, в свою очередь, привело к исключению "Не удалось создать безопасный канал SSL/TLS".

Другая возможность - неправильный ввоз сертификата на коробку. Обязательно установите флажок в кружке. Первоначально я этого не делал, поэтому код либо прерывался, либо выдавал то же исключение, что закрытый ключ не мог быть найден.

диалог импорта сертификата

Это помогло мне:

      System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

У меня была эта проблема, потому что мой web.config имел:

<httpRuntime targetFramework="4.5.2" />

и не:

<httpRuntime targetFramework="4.6.1" />

В моем случае учетная запись службы, на которой запущено приложение, не имела разрешения на доступ к закрытому ключу. Как только я дал это разрешение, ошибка ушла

  1. ММС
  2. сертификаты
  3. Развернуть в личный
  4. выберите сертификат
  5. щелкните правой кнопкой мыши
  6. Все задачи
  7. Управление закрытыми ключами
  8. добавлять

Как вы можете сказать, есть множество причин, по которым это может произойти. Думал, я бы добавил причину, с которой столкнулся...

Если вы установите значение WebRequest.Timeout в 0это исключение, которое выбрасывается. Ниже приведен код, который у меня был... (За исключением жестко закодированного 0 для значения тайм-аута у меня был параметр, который был случайно установлен в 0).

WebRequest webRequest = WebRequest.Create(@"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...

Корень этого исключения в моем случае заключался в том, что в какой-то момент кода вызывалось следующее:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Это действительно плохо. Он не только инструктирует.NET использовать небезопасный протокол, но и влияет на каждый новый (и аналогичный) запрос WebClient, сделанный впоследствии в вашем домене приложения. (Обратите внимание, что входящие веб-запросы не затрагиваются в вашем приложении ASP.NET, но новые запросы WebClient, такие как общение с внешней веб-службой, есть).

В моем случае это было на самом деле не нужно, поэтому я мог просто удалить инструкцию, и все остальные мои веб-запросы снова начали работать нормально. Основываясь на моем чтении в другом месте, я узнал несколько вещей:

  • Это глобальная настройка в вашем домене приложения, и если у вас есть одновременная активность, вы не можете надежно установить для нее одно значение, выполнить действие и затем вернуть его обратно. Другое действие может иметь место в течение этого небольшого окна и может быть затронуто.
  • Правильный параметр - оставить его по умолчанию. Это позволяет.NET продолжать использовать любое безопасное значение по умолчанию с течением времени, и вы обновляете фреймворки. Установка его на TLS12 (который является наиболее безопасным на момент написания статьи) будет работать сейчас, но через 5 лет может начать вызывать загадочные проблемы.
  • Если вам действительно нужно установить значение, вам следует рассмотреть возможность сделать это в отдельном специализированном приложении или домене приложения и найти способ общения между ним и вашим основным пулом. Поскольку это единое глобальное значение, попытка управлять им в загруженном пуле приложений приведет только к проблемам. Этот ответ: /questions/37203503/ustanovite-securityprotocol-ssl3-ili-tls-vnet-httpwebrequest-dlya-kazhdogo-zaprosa/37203513#37203513 предоставляет возможное решение с помощью пользовательского прокси. (Обратите внимание, я лично не реализовал это.)

Если вы запускаете свой код из Visual Studio, попробуйте запустить Visual Studio от имени администратора. Исправлена ​​проблема для меня.

System.Net.WebException: запрос был прерван: не удалось создать безопасный канал SSL/TLS.

В нашем случае мы использовали поставщика программного обеспечения, поэтому у нас не было доступа для изменения кода.NET. Очевидно, что.NET 4 не будет использовать TLS v 1.2, если нет изменений.

Для нас исправлением было добавление ключа SchUseStrongCrypto в реестр. Вы можете скопировать / вставить приведенный ниже код в текстовый файл с расширением.reg и выполнить его. Это послужило нашим "патчем" к проблеме.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

Ни один из этого ответа не работает для меня, google chrome и почтальон работают и рукопожатие сервера, но т.е. и.net не работают. в google chrome на вкладке безопасности> соединение показывает, что зашифровано и аутентифицировано с использованием ECDHE_RSA с набором шифров P-256 и AES_256_GCM для установления связи с сервером.

Я устанавливаю IIS Crypto и в списке наборов шифров на сервере Windows 2012 R2 не могу найти ECDHE_RSA с набором шифров P-256 и AES_256_GCM. затем я обновляю окна до последней версии, но проблема не решается. наконец, после поисков я понял, что Windows Server 2012 R2 не поддерживает GSM правильно и обновил мой сервер до Windows Server 2016, и моя проблема решена.

В случае, если клиент является машиной Windows, возможной причиной может быть то, что протокол tls или ssl, требуемый службой, не активирован.

Это может быть установлено в:

Панель управления -> Сеть и Интернет -> Свойства обозревателя -> Дополнительно

Прокрутите настройки до "Безопасность" и выберите между

  • Использовать SSL 2.0
  • Использовать SSL 3.0
  • Используйте TLS 1.0
  • Используйте TLS 1.1
  • Используйте TLS 1.2

Я боролся с этой проблемой весь день.

Когда я создал новый проект с.NET 4.5, я, наконец, заставил его работать.

Но если я опустился до 4.0, у меня снова возникла та же проблема, и она стала необратимой для этого проекта (даже когда я попытался обновить до 4.5 снова).

Странное нет другого сообщения об ошибке, кроме "Запрос был прерван: не удалось создать безопасный канал SSL/TLS". подошел к этой ошибке

Другая возможность состоит в том, что выполняемый код не имеет необходимых разрешений.

В моем случае я получил эту ошибку при использовании отладчика Visual Studio для проверки вызова веб-службы. Visual Studio не запускалась от имени администратора, что вызвало это исключение.

Ни один из ответов не сработал для меня.

Вот что сработало:

Вместо инициализации моего X509Certifiacte2 как это:

   var certificate = new X509Certificate2(bytes, pass);

Я сделал это так:

   var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

Обратите внимание на X509KeyStorageFlags.Exportable !!

Я не изменил остальную часть кода (WebRequest сам):

// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true; 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    // etc...
}

На самом деле я даже не уверен, что первые две строки необходимы...

У меня возникла такая же проблема, и я обнаружил, что этот ответ работает правильно для меня. Ключ 3072. Эта ссылка содержит подробности исправления 3072.

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);

В моем случае исправление потребовалось на двух каналах:

https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss

Попробуй это:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Другие вопросы по тегам