Не вдалося встановити довірчі відносини для безпечного каналу SSL / TLS - SOAP


325

У мене є простий виклик веб-служби, що генерується додатком Windows. Це працює декілька років і продовжує робити це в десятках місцях, де він працює.

Нова установка на новому сайті стикається з проблемою. При спробі викликати веб-службу не вдається повідомлення з повідомленням:

Не вдалося встановити довірчі відносини для захищеного каналу SSL / TLS

URL-адреса веб-служби використовує SSL (https: //), але це працює давно (і продовжує це робити) у багатьох інших місцях.

Куди я дивлюсь? Чи може це бути проблемою безпеки між Windows та .NET, яка є унікальною для цієї установки? Якщо так, то де я можу встановити довірчі відносини? Я загубився!


У моєму випадку ця помилка була викликана переадресацією IP-адреси.
cja

Відповіді:


166

Думки (на основі болю в минулому):

  • чи є у вас DNS та огляд сервера?
  • ви використовуєте правильне ім’я із сертифіката?
  • чи справді сертифікат дійсний?
  • чи погано налаштований балансир навантажень псує речі?
  • чи правильно у встановленому серверному апараті встановлено тактовий час (тобто, щоб час UTC був правильним (ігноруйте місцевий час, це в значній мірі невідповідний)) - це, безумовно, має значення для WCF, тому може вплинути на регулярний SOAP?
  • чи існує проблема довіри ланцюжка сертифікатів? якщо перейти з сервера до мильної служби, чи можете ви отримати SSL?
  • пов'язане з вищезазначеним - чи встановлено сертифікат у правильному місці? (вам може знадобитися копія у довірених кореневих органах з сертифікації)
  • чи правильно встановлений проксі-сервер на рівні сервера? (який відрізняється від проксі користувача); перегляньте proxycfg для XP / 2003 (не впевнений у Vista та ін.)

2
1) Веб-служба в Інтернеті. Ми можемо переглядати його через браузер. 2) Нова машина не є сервером - це робочий стіл, на якому працює мій додаток, який збирає інформацію про замовлення та завантажує через сервіс SOAP 3) Так, ми можемо переглядати її. 4) Це для мене нове: машинний проксі-рівень?
Роб Шріпсема

2
Так; код не використовує налаштування проксі IE; він використовує окремий магазин ... важливо, щоб це було налаштовано (якщо ви використовуєте проксі). У XP найпростіший варіант (IIRC) "proxycfg -i" імпортувати налаштування IE.
Марк Гравелл

11
Дякую Марку. Це допомогло мені, і проблема полягала в тому, що сервер мав сертифікат, підписаний стороною CA, якій я ще не довіряв. Рішення полягало в тому, щоб додати цей CA до списку довірених кореневих служб CA.
p.campbell

1
Комп'ютер, що мав цей виняток, не зміг синхронізувати системний час за допомогою серверів часу. Мені довелося зайти і вручну синхронізувати час, перш ніж це спрацювало.
Кріс - Haddox Technologies

4
Ви можете отримати це, якщо ви використовували Fiddler для налагодження викликів служб і використовували режим перехоплення сертифікатів. Просто зніміть перехоплення у варіантах фідлера, і ви повинні бути хорошими
Раскін

363

Наступні фрагменти виправлять випадок, коли з сертифікатом SSL на сервері, на який ви телефонуєте, щось не так. Наприклад, це може бути самопідписаний або ім'я хоста між сертифікатом та сервером може не збігатися.

Це небезпечно, якщо ви викликаєте сервер поза вашим безпосереднім керуванням, оскільки ви більше не можете бути впевнені, що спілкуєтесь із сервером, до якого ви думаєте, що підключений. Однак якщо ви маєте справу з внутрішніми серверами та отримуєте "правильний" сертифікат не є практичним, скористайтеся наступним, щоб повідомити веб-службі, щоб ігнорувати проблеми з сертифікатом та хоробро брати участь у службі.

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

//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
    ((sender, certificate, chain, sslPolicyErrors) => true);

// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    bool result = cert.Subject.Contains("YourServerName");
    return result;
}

6
Мій досвід роботи з ServicePointManager. Будь-яка зміна в ньому вплине на весь домен додатка. Хоча відповідь дуже чітко пояснює, як це можна застосувати, мені подобається закидати це.
Amzath

Налаштування зворотного дзвінка працює для мене .NET 4.5, але не .NET 4.6
RJB

@Amzath Будь-які пропозиції щодо відновлення цього завдання після завершення певного запиту? Людині може знадобитися зробити один запит на незавірений сервер, а потім повернути речі таким, яким вони були.
Ісаак Ліман

1
@Isaac Lyman: ServicePointManager.ServerCertificateValidationCallback = null;має повернутися до поведінки за замовчуванням.
Майк Чемберлен

1
@MikeChamberlain Єдина проблема вашої пропозиції полягає в тому, що одночасні запити можуть бути небезпечними, оскільки ви маєте справу з глобальним налаштуванням додатків.
Ісаак Ліман

178

Дуже просте рішення "зловити всіх":

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Рішення від sebastian-castaldi трохи детальніше.


21
Я просто ставлю це до #If CONFIG = "Debug"заяви, щоб воно було активовано лише в режимі налагодження. Це чудово працює!
cjbarth

1
Деталі можуть бути хорошими, але є що можна сказати і для швидкої, короткої та простої лінії коду. Цей код короткий, і це робить трюк.
allen1

чи буде це діяти лише за поточної дії (наприклад, використовується ASP MVC)? або це буде встановлено як поведінка за замовчуванням для програми ASP.NET?
JeeShen Lee

2
Це слід використовувати лише з метою тестування, це рішення довіряє будь-якому сертифікату, навіть недійсному / терміну дії
Shenron

1
Як пояснено в коментарях вище, це не підтверджує, чи SSL-з'єднання більше дійсне. Тож зв’язок між вашою системою та іншими системами може бути порушений. Це завжди питання, для чого це потрібно.
Ремі

35

Мені особисто найбільше подобається таке рішення:

using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

... тоді, перш ніж подати запит на отримання помилки, зробіть наступне

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Виявив це після консультації з рішенням Луки


4
Дивіться відповідь Себастьяна Касталді щодо застережень щодо безпеки цього підходу.
Едвард Брей

Який ризик безпеки використовувати це у виробництві?
Амджад

@Amjad ризик безпеки полягає в тому, що він повністю уникає будь-яких переваг використання SSL / TLS. Сервер може представити будь-який вподобаний йому сертифікат, і цей код буде ігнорувати помилку
1800 ІНФОРМАЦІЯ

18

Якщо ви використовуєте Windows 2003, ви можете спробувати це:

Відкрийте консоль управління Microsoft (Пуск -> Запуск -> mmc.exe);

Виберіть Файл -> Додати / видалити оснащення;

На вкладці Автономне виберіть Додати;

Виберіть оснащення сертифікатів та натисніть кнопку Додати;

У майстрі виберіть Обліковий запис комп’ютера та виберіть Місцевий комп'ютер. Натисніть кнопку Готово, щоб закінчити майстра;

Закрийте діалогове вікно «Додати / видалити оснащення»;

Перейдіть до Сертифікатів (локальний комп'ютер) та виберіть магазин для імпорту:

Якщо у вас є сертифікат Root CA для компанії, яка видала сертифікат, виберіть Довірені органи кореневої сертифікації;

Якщо у вас є сертифікат для самого сервера, виберіть Інші люди

Клацніть правою кнопкою миші магазин і виберіть Усі завдання -> Імпорт

Дотримуйтесь майстра та надайте файл сертифіката, який у вас є;

Після цього просто перезапустіть IIS і спробуйте зателефонувати за допомогою веб-сервісу ще раз.

Довідка: http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS- ...


2
Це перетворило мене на частину шляху, але мені потрібно було мати сертифікат у розділі Довірених кореневих органів сертифікації, щоб змусити його працювати. Відповідно до blogs.msdn.com/b/jpsanders/archive/2009/09/16/…
Jacob Ewald

17

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

public static class Ssl
{
    private static readonly string[] TrustedHosts = new[] {
      "host1.domain.com", 
      "host2.domain.com"
    };

    public static void EnableTrustedHosts()
    {
      ServicePointManager.ServerCertificateValidationCallback = 
      (sender, certificate, chain, errors) =>
      {
        if (errors == SslPolicyErrors.None)
        {
          return true;
        }

        var request = sender as HttpWebRequest;
        if (request != null)
        {
          return TrustedHosts.Contains(request.RequestUri.Host);
        }

        return false;
      };
    }
}

Тоді просто зателефонуйте до Ssl.EnableTrustedHosts, коли ваш додаток запуститься.


@thelem Так повторне читання Я думаю, що, мабуть, перечитав перший раз
Шив

Який ризик безпеки довіряти всім сертифікатам у виробництві?
Амджад

@Amjad ризик безпеки полягає в тому, що кожен клієнт і сервер можуть вставити себе в середину комунікацій, використовувати свій власний сертифікат SSL і прочитати весь трафік між клієнтом і сервером. Це ефективно скасовує SSL.
Роб Пруз

Чи повинен він працювати, коли я використовую додаток WCF для генерації класів з wsdl?
Каміль

7

Лука написав про це досить гарну статтю .. досить прямо вперед .. спробуйте

Рішення Луки

Причина (цитата з його статті (мінус проклинання)) ".. Проблема з кодом вище полягає в тому, що він не працює, якщо ваш сертифікат недійсний. Чому я розміщую повідомлення на веб-сторінці з недійсним сертифікатом SSL? Тому що Я дешевий, і мені не здавалося платити Verisign або одному з інших ** - * s за сертифікат до мого тестового вікна, щоб я підписав його самостійно. Коли я надіслав запит, на мене накинувся прекрасний виняток:

System.Net.WebException Базове з'єднання було закрито. Не вдалося встановити довірчі відносини з віддаленим сервером.

Я не знаю про вас, але для мене це виняток виглядало як щось, що було б викликано дурною помилкою в моєму коді, яка спричинила збій пошти. Тож я продовжував шукати, налаштовувати і робити всілякі дивні речі. Лише після того, як я поглянув на річ *** n, я виявив, що поведінка за замовчуванням після зустрічі з недійсним сертифікатом SSL - це викинути саме цей виняток. .. "


1
Це рішення є застарілим для .Net 4.5. Якщо ви просто хочете прийняти всі сертифікати, дивіться Себастьяна Касталді чи мою відповідь далі нижче.
Ремі

7

Інструмент діагностики SSL Microsoft може допомогти визначити проблему.

ОНОВЛЕННЯ посилання було виправлено зараз.


7
Станом на сьогодні (серпень 2012 року) це посилання зараз розірвано.
ashes999

Пошук у каталозі завантажень і більше не доступний інструмент діагностики SSL. :(
SASS_Shooter

2
Давайте виправимо посилання. Виправте мене, якщо я помиляюсь iis.net/downloads/community/2009/09/…
Amzath

3

Я щойно стикався з цим питанням. Я вирішив оновити системний час шляхом синхронізації вручну з серверами часу. Для цього ви можете:

  • Клацніть годинник правою кнопкою миші на панелі завдань
  • Виберіть Adjust Date/Time
  • Виберіть Internet Timeвкладку
  • Клацніть Change Settings
  • Виберіть Update Now

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


СВЯТА КОРОВА. Побіг примружитись до цієї саме речі. Дякуємо за просте виправлення!
TheGerm

3

Спробуйте це:

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

Зауважте, що вам потрібно працювати принаймні з 4.5 .NET рамкою


3

У мене була подібна проблема з .NETдодатком в Internet Explorer.

Я вирішив проблему, додавши сертифікат (у моєму випадку сертифікат VeriSign Class 3) до сертифікатів довірених редакторів.

Go to Internet Options-> Content -> Publishers and import it

Ви можете отримати сертифікат, якщо експортуєте його з:

Internet Options-> Content -> Certificates -> Intermediate Certification Authorities -> VeriSign Class 3 Public Primary Certification Authority - G5

Дякую


1

У мене ця помилка була запущена проти веб-сервера з таким URL-адресом:

a.b.domain.com

але сертифікату на це не було, тому мені зателефонував DNS

a_b.domain.com

Просто натякніть на це рішення тут, оскільки це з'явилося в Google.


У моєму випадку веб-сайт був налаштований за сертифікатом ssl для магістра (* .abcd.com). Після налаштування веб-сайту прив'язка виглядала як xyz-abcd.com, що спричиняло проблему.
sree

1

Для тих, хто має цю проблему через клієнтську сторону VS, як тільки успішно додав посилання на послугу та намагався виконати перший дзвінок, отримав такий виняток: "Базове з'єднання було закрито: Не вдалося встановити довірчі відносини для безпечного каналу SSL / TLS" Якщо ви використовуєте (як у моєму випадку) URL-адресу кінцевої точки з IP-адресою і отримали цей виняток, то, ймовірно, вам потрібно буде знову додати посилання служби, виконуючи такі дії:

  • Відкрийте URL-адресу кінцевої точки в Internet Explorer.
  • Натисніть на помилку сертифіката (червоний значок в адресному рядку)
  • Клацніть Переглянути сертифікати.
  • Візьміть видане на: "name" і замініть IP-адресу або будь-яке ім'я, яке ми використовували, і отримайте помилку для цього "name".

Спробуйте ще раз :). Дякую


0

У моєму випадку я намагався протестувати SSL у середовищі моєї Visual Studio за допомогою IIS 7.

Ось що я в кінцевому підсумку робив, щоб змусити його працювати:

  • Під моїм сайтом у розділі "Прив'язки ..." праворуч у IIS я повинен був додати прив'язку "https" до порту 443 та вибрати "Сертифікат розробки IIS Express".

  • Під моїм сайтом у розділі "Додаткові налаштування ..." праворуч мені довелося змінити "Увімкнені протоколи" з "http" на "https".

  • Під значком "Налаштування SSL" я вибрав "Прийняти" для клієнтських сертифікатів.

  • Тоді мені довелося переробити пул додатків.

  • Мені також довелося імпортувати сертифікат локального хоста в мій особистий магазин за допомогою mmc.exe.

Мій web.configфайл був уже налаштований правильно, тому після того, як я розібрав усе вищезазначене, я зміг продовжити тестування.


як налаштовано ваш web.config?
Chazt3n

@ Chazt3n Я не можу вам сказати, це було деякий час назад, але це було б базовим налаштуванням зв'язування http, я зазвичай використовую svcutil для генерування інформації про конфігурацію для інформації про клієнта веб-служби.
Попо

0

Моє рішення (VB.Net, версія цього додатка "staging" (UAT) повинна працювати з сертифікатом "staging", але не впливати на запити, коли вони знаходяться на веб-сайті)

    ...
        Dim url As String = ConfigurationManager.AppSettings("APIURL") & "token"
        If url.ToLower().Contains("staging") Then
           System.Net.ServicePointManager.ServerCertificateValidationCallback = AddressOf AcceptAllCertifications
        End If
    ...

    Private  Function AcceptAllCertifications(ByVal sender As Object, ByVal certification As System.Security.Cryptography.X509Certificates.X509Certificate, ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
        Return True
    End Function

-3

Якщо не працює поганий сертифікат, коли ServerCertificateValidationCallback повертає вірно; Мій серверCertificateValidationCallback код:

ServicePointManager.ServerCertificateValidationCallback += delegate
{
    LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
    return true;
};

Мій код, який перешкоджає виконанню ServerCertificateValidationCallback:

     if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
    {
        CertificateValidation certValidate = new CertificateValidation();
        certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
        ServicePointManager.CertificatePolicy = certValidate;
    }

Функція OnValidateCertificateError:

private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
    string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
    LogWriter.LogError(msg);
    //Message.ShowError(msg);
}

Я відключив сертифікати коду CertificateValidation та ServerCertificateValidationCallback дуже добре


Ніколи не слід вимикати перевірку сертифікатів. Натомість виправте проблему, яка спричинила невдалу перевірку.
Дан

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