Не вдалося створити захищений канал 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;

1
У мене схоже питання. Через атаку POODLE ми змушені вимкнути TLS 1.0 на нашому сервері. Коли я це роблю, сторонній додаток перестає працювати. Декомпіляція зразка показує код, подібний до вашого. Він використовує webclientc.SendAsync замість GetAsync. Якщо я скопіюю код у консольний додаток для тестування, я зможу відтворити помилку, і додавши ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 це працює. Я думав, що між сервером і клієнтом відбудеться якесь рукостискання, щоб розкрити, яку версію TLS використовувати? Чому він автоматично не вибирає 1.1, коли 1.0 вимкнено?
Енгерн,

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;

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


1
Спробувавши все вищезазначене безрезультатно, це була відповідь: перед створенням HttpWebRequest потрібно встановити ServicePointManager.
Генрі

2

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


1

TLS 1.0 та 1.1 тепер закінчені. Оновлено пакет на нашому веб-сервері Amazon, і ми почали отримувати цю помилку.

Відповідь вище, але ви не повинні використовувати tlsабо tls11більше.

Спеціально для ASP.Net, додайте це до одного зі своїх способів запуску.

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

але я впевнений, що щось подібне спрацює у багатьох інших випадках.


0

Якщо ви використовуєте нове доменне ім'я, і ​​ви зробили все вищезазначене, але все ще отримуєте ту саму помилку, перевірте, чи очищено кеш DNS на вашому ПК. Очистіть свій DNS, щоб отримати докладнішу інформацію.

Windows® 8

Щоб очистити кеш DNS, якщо ви використовуєте Windows 8, виконайте такі дії:

На клавіатурі натисніть Win + X, щоб відкрити меню WinX.

Клацніть правою кнопкою миші Командний рядок і виберіть Запуск від імені адміністратора.

Виконайте таку команду:

ipconfig / flushdns

Якщо команда успішна, система повертає таке повідомлення:

Конфігурація IP-адреси Windows успішно очистила кеш-пам'ять DNS Resolver

Windows® 7

Щоб очистити кеш DNS, якщо ви використовуєте Windows 7, виконайте такі дії:

Натисніть кнопку Пуск.

Введіть cmd у текстовому полі пошуку меню «Пуск».

Клацніть правою кнопкою миші Командний рядок і виберіть Запуск від імені адміністратора.

Виконайте таку команду:

ipconfig / flushdns

Якщо команда успішна, система повертає таке повідомлення: Налаштування IP-адреси Windows успішно очистило кеш-пам'ять розв'язувача DNS.


ipconfig /flushdnsв C #?
Kiquenet

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

Сподіваюся, мій досвід може допомогти комусь іншому, хто має мій особливий смак цієї проблеми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.