Не удалось создать безопасный канал SSL / TLS, несмотря на настройку ServerCertificateValidationCallback

85

Я пытаюсь установить соединение SSL / TLS с тестовым сервером с самозаверяющим сертификатом . Связь по незащищенному каналу работала без проблем.

Вот мой пример кода, который я написал на основе этих решений: Разрешить ненадежные сертификаты SSL с HttpClient C # Игнорировать ошибки сертификата? Клиент .NET, подключающийся к веб-API SSL

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

var c = new HttpClient();
var r = c.GetAsync("https://10.3.0.1:8443/rest/v1").Result;
if (r.IsSuccessStatusCode)
{
    Log.AddMessage(r.Content.Get<string>());
}
else
{
    Log.AddMessage(string.Format("{0} ({1})", (int)r.StatusCode, r.ReasonPhrase));
}

также пробовал это:

var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = delegate { return true; };
var c = new HttpClient(handler);
...

и это

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

но каждый раз возникает исключение:

InnerException: System.Net.Http.HttpRequestException
   _HResult=-2146233088
   _message=An error occurred while sending the request.
   HResult=-2146233088
   IsTransient=false
   Message=An error occurred while sending the request.
   InnerException: System.Net.WebException
        _HResult=-2146233079
        _message=The request was aborted: Could not create SSL/TLS secure channel.
        HResult=-2146233079
        IsTransient=false
        Message=The request was aborted: Could not create SSL/TLS secure channel.
        Source=System
        StackTrace:
             at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
             at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
        InnerException: 

Что я делаю не так? Почему я не могу подключиться к этому серверу (с недействительным самозаверяющим сертификатом)

Марцин Конрад Цегларек
источник

Ответы:

166

Вы делаете это правильно с помощью ServerCertificateValidationCallback. Это не та проблема, с которой вы столкнулись. Проблема, с которой вы столкнулись, скорее всего, связана с версией протокола SSL / TLS.

Например, если ваш сервер предлагает только SSLv3 и TLSv10, а вашему клиенту нужен TLSv12, вы получите это сообщение об ошибке. Что вам нужно сделать, так это убедиться, что и клиент, и сервер поддерживают общую версию протокола.

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

  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Wapac
источник
1
У меня похожая проблема. Из-за POODLE-атаки мы вынуждены отключить TLS 1.0 на нашем сервере. Когда я это делаю, стороннее приложение перестает работать. Декомпиляция ассамблея показывает код, похожий на ваш. Он использует webclientc.SendAsync вместо GetAsync. Если я скопирую код в консольное приложение для тестирования, я могу воспроизвести ошибку, и добавив ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11, он заработает. Я подумал, что между сервером и клиентом будет какое-то рукопожатие, чтобы узнать, какую версию TLS использовать? Почему он не выбирает автоматически 1.1, когда 1.0 отключен?
Engern
3
Благодаря! Боролся с этим часа 3. Добавление этой строки сделало это для меня:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thomas T
1
Обратите внимание, что в более новой версии .NET это включено по умолчанию, все, что нам нужно сделать, это установить версию .NET на 4.6.1
martinh_kentico
1
Это означает, что вам все равно, действительно ли это действительно так. Этот обратный вызов позволяет вам просто избежать любых проверок безопасности этого сертификата.
Wapac
1
Отличный ответ, я чувствую, что это ServicePointManager.SecurityProtocolзначение должно быть по умолчанию. Или, по крайней мере, должно быть больше информации непосредственно внутри брошенного исключения.
Чад
28

Только сегодня мы решали ту же проблему, и все, что вам нужно сделать, это увеличить версию .NET во время выполнения.

4.5.2 не сработал для нас с вышеуказанной проблемой, в то время как 4.6.1 был в порядке

Если вам нужно сохранить версию .NET, установите

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
martinh_kentico
источник
1
Какой из вариантов вы использовали и как именно?
martinh_kentico
1
У меня есть приложение .NET 4.5, которое с сегодняшнего дня не будет работать с конкретным сайтом SSL. Если я перейду на 4.6.1, он будет работать нормально, но я не могу ничего изменить. Я не знаю, что делать: |
Цуры
16

В качестве продолжения для тех, кто все еще сталкивается с этим, я добавил параметры ServicePointManager.SecurityProfile, как указано в решении:

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

И все же я продолжал получать ту же ошибку «Запрос был прерван: не удалось создать безопасный канал SSL / TLS». Я пытался подключиться к некоторым старым голосовым серверам с интерфейсами HTTPS SOAP API (то есть голосовой почтой, системами IP-телефонии и т. Д.… Установленными несколько лет назад). Они поддерживают только соединения SSL3, поскольку последний раз обновлялись несколько лет назад.

Можно было бы подумать, что включение SSl3 в список протоколов безопасности поможет, но этого не произошло. Единственный способ установить соединение - включить ТОЛЬКО протокол Ssl3 и никаких других:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

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

В любом случае - если вы все еще сталкиваетесь с этим на некоторых старых сайтах / серверах, стоит попробовать.

Джефф Линдборг
источник
1
У нас есть модуль CUCMPowerShell для использования API-интерфейса Cisco Unified Communications AXL через PowerShell, и ваш ответ помог нам решить эту проблему, добавив [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Ssl3. Спасибо! Полный код можно увидеть в функции Invoke-CUCMSOAPAPIF
Крис Магнусон,
2
@Jeff - Прочтите связанную статью. Я думаю, это может объяснить, почему Ssl3 не работает, и предлагает два способа повторно включить Ssl3. docs.microsoft.com/en-us/dotnet/framework/migration-guide/…
Скотт
4

переместите эту строку: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Перед этой строкой: HttpWebRequest request = (HttpWebRequest) WebRequest.Create (uri);

Исходное сообщение: обновление безопасности KB4344167 нарушает код TLS

user2686690
источник
1
После безрезультатных попыток всего вышеперечисленного был ответ: ServicePointManager необходимо настроить до создания HttpWebRequest.
Генри
2

В моем случае TLS1_2 был включен как на клиенте, так и на сервере, но сервер использовал MD5, а клиент отключил его. Итак, протестируйте и клиент, и сервер на http://ssllabs.com или протестируйте с помощью openssl / s_client, чтобы увидеть, что происходит. Также проверьте выбранный шифр с помощью Wireshark.

user960567
источник
1

TLS 1.0 и 1.1 теперь End of Life. Пакет на нашем веб-сервере Amazon обновился, и мы начали получать эту ошибку.

Ответ выше, но вы не должны использовать tlsили tls11больше.

Специально для ASP.Net добавьте это в один из методов запуска.

        public Startup()
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

но я уверен, что что-то подобное сработает и во многих других случаях.

Bluebaron
источник
0

Если вы используете новое доменное имя, выполнили все вышеперечисленное, но по-прежнему получаете ту же ошибку, проверьте, очищаете ли вы кеш DNS на своем компьютере. Очистите свой DNS для получения дополнительных сведений.

Windows® 8

Чтобы очистить кеш DNS, если вы используете Windows 8, выполните следующие действия:

На клавиатуре нажмите Win + X, чтобы открыть меню WinX.

Щелкните правой кнопкой мыши Командную строку и выберите Запуск от имени администратора.

Выполните следующую команду:

ipconfig / flushdns

Если команда завершилась успешно, система возвращает следующее сообщение:

Конфигурация IP-адреса Windows успешно очистила кеш DNS-преобразователя.

Windows® 7

Чтобы очистить кеш DNS, если вы используете Windows 7, выполните следующие действия:

Щелкните Пуск.

Введите cmd в текстовое поле поиска меню «Пуск».

Щелкните правой кнопкой мыши Командную строку и выберите Запуск от имени администратора.

Выполните следующую команду:

ipconfig / flushdns

Если команда выполнена успешно, система возвращает следующее сообщение: IP-конфигурация Windows успешно очистила кэш DNS-преобразователя.

Мишель
источник
ipconfig /flushdnsв C #?
Kiquenet 05
0

Я наткнулся на эту тему, потому что у меня также была ошибка Не удалось создать безопасный канал SSL / TLS. В моем случае я пытался получить доступ к REST API конфигурации Siebel из PowerShell, используяInvoke-RestMethod , и ни одно из приведенных выше предложений не помогло.

В конце концов я обнаружил причину своей проблемы: сервер, с которым я связывался, требовал аутентификации сертификата клиента.

Чтобы звонки работали, мне пришлось предоставить сертификат клиента (включая закрытый ключ) с -Certificate параметром:

$Pwd = 'certificatepassword'
$Pfx = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2'
$Pfx.Import('clientcert.p12', $Pwd, 'Exportable,PersistKeySet')
Invoke-RestMethod -Uri 'https://your.rest.host/api/' -Certificate $Pfx -OtherParam ...

Надеюсь, мой опыт может помочь кому-то еще, у кого есть мой особый вкус к этой проблеме.

Paulf
источник