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

У меня есть простой вызов веб-службы, созданный приложением Windows.NET(С#) 2.0 через прокси-сервер веб-службы, созданный Visual Studio, для веб-службы, также написанной на С# (2.0). Это проработало несколько лет и продолжает делать это в дюжине мест, где он работает.

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

Не удалось установить доверительные отношения для безопасного SSL/TLS Канал

URL-адрес веб-службы использует SSL (https://) - но это работает долгое время (и продолжает делать это) из многих других мест.

Где я смотрю? Может ли это быть проблемой безопасности между Windows и .NET, которая уникальна для этой установки? Если да, то где мне установить доверительные отношения? Я потерян!

Ответ 1

Мысли (основанные на боли в прошлом):

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

Ответ 2

Следующие фрагменты исправят ситуацию, когда что-то не так с сертификатом 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;
}

Ответ 3

Самое простое решение "поймать все":

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

Решение от sebastian-castaldi немного более подробно.

Ответ 4

Мне больше всего нравится следующее решение:

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

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

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

Обнаружено это после консультации Luke Solution

Ответ 5

Если вы используете Windows 2003, вы можете попробовать следующее:

Откройте консоль управления Microsoft (Пуск → Выполнить → mmc.exe);

Выберите "Файл" → "Добавить/удалить оснастку";

На вкладке "Автономная" выберите "Добавить";

Выберите оснастку "Сертификаты" и нажмите "Добавить";

В мастере выберите компьютер Аккаунт, а затем выберите Локальный Компьютер. Нажмите Finish, чтобы закончить Мастер;

Закройте диалоговое окно "Добавить/удалить оснастку";

Перейдите к сертификатам (Local Компьютер) и выберите магазин для импорт:

Если у вас есть сертификат Root CA для компании, которая выпустила сертификат, выберите Trusted Root Органы сертификации;

Если у вас есть сертификат для сервер, выберите "Другие люди"

Щелкните правой кнопкой мыши магазин и выберите "Все". Задачи → Импорт

Следуйте указаниям мастера и файл сертификата, который у вас есть;

После этого просто перезапустите IIS и попробуйте снова вызвав веб-службу.

Ссылка: http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS-...

Ответ 6

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

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, когда ваше приложение запустится.

Ответ 8

Люк написал довольно хорошую статью об этом. довольно прямо вперед.. дайте это попробовать

Решение Luke

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

System.Net.WebException Подключенное соединение было закрыто. Не удалось установить доверительные отношения с удаленным сервером.

Я не знаю о вас, но для меня это исключение было похоже на то, что было бы вызвано глупой ошибкой в ​​моем коде, которая вызывала ошибку POST. Поэтому я продолжал искать, настраивать и делать всевозможные странные вещи. Только после того, как я нашел googled ***, я узнал, что поведение по умолчанию после столкновения с недействительным сертификатом SSL - это исключение. .. "

Ответ 9

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

  • Щелкните правой кнопкой мыши часы на панели задач
  • Выберите Adjust Date/Time
  • Выберите вкладку Internet Time
  • Нажмите Change Settings
  • Выберите Update Now

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

Ответ 10

У меня была похожая проблема в приложении .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

Спасибо

Ответ 11

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

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

Обратите внимание, что вы должны работать как минимум с 4.5.NET Framework

Ответ 12

У меня была эта ошибка, протекающая против веб-сервера с url вроде:

a.b.domain.com

но для него не было сертификата, поэтому я получил DNS под названием

a_b.domain.com

Просто наведите намек на это решение здесь, так как это появилось в Google.

Ответ 13

Для тех, кто имеет эту проблему через клиентскую сторону VS после успешного добавления ссылки на службу и пытается выполнить первый вызов, получил это исключение: "Основное соединение было закрыто: не удалось установить доверительные отношения для безопасного канала SSL/TLS" Если вы используете (например, мой случай) URL-адрес конечной точки с IP-адресом и получили это исключение, то вам, вероятно, потребуется повторно добавить ссылку на службу, выполнив следующие шаги:

  • Откройте URL-адрес конечной точки в Internet Explorer.
  • Нажмите на ошибку сертификата (красный значок в адресной строке)
  • Нажмите "Просмотреть сертификаты".
  • Возьмите выделенное имя: "имя" и замените IP-адрес или другое имя, которое мы использовали, и получим ошибку для этого "имени".

Попробуйте еще раз:). Благодаря

Ответ 14

В моем случае я пытался протестировать SSL в моей среде Visual Studio с помощью IIS 7.

Вот что я сделал, чтобы заставить его работать:

  • Под моим сайтом в разделе "Bindings..." справа в IIS мне пришлось добавить привязку "https" к порту 443 и выбрать "Сертификат разработки IIS Express".

  • Под моим сайтом в разделе "Дополнительные настройки..." справа мне пришлось изменить "Включенные протоколы" с "http" на "https".

  • В значке "Настройки SSL" я выбрал "Принять" для клиентских сертификатов.

  • Затем мне пришлось перезапустить пул приложений.

  • Мне также пришлось импортировать сертификат локального хоста в свой личный магазин, используя mmc.exe.

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

Ответ 15

В нашем случае эта проблема возникла из-за нехватки дискового пространства. Очистка дискового пространства в дополнение к утилизации пула приложений устранила проблему.

Проверьте место на диске перед выполнением любых других действий по устранению неполадок!

Ответ 16

Мое решение (VB.Net, "промежуточная" (UAT) версия этого приложения должна работать с "промежуточным" сертификатом, но не влиять на запросы, когда они находятся на действующем сайте):

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

Ответ 17

Если не работает плохой сертификат, когда ServerCertificateValidationCallback возвращает true, Мой код ServerCertificateValidationCallback:

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 очень хорошо работает