Nie można ustanowić relacji zaufania dla bezpiecznego kanału SSL / TLS - SOAP


325

Mam proste wywołanie usługi internetowej, wygenerowane przez aplikację systemu Windows .NET (C #) 2.0, za pośrednictwem proxy usługi internetowej wygenerowanej przez Visual Studio, dla usługi internetowej napisanej również w C # (2.0). Działało to od kilku lat i nadal działa w kilkunastu miejscach, w których działa.

Wystąpił problem z nową instalacją w nowej witrynie. Podczas próby wywołania usługi sieci Web komunikat nie powiedzie się:

Nie można ustanowić relacji zaufania dla bezpiecznego kanału SSL / TLS

Adres URL usługi internetowej korzysta z protokołu SSL (https: //) - ale działa to od dłuższego czasu (i nadal działa) z wielu innych lokalizacji.

Gdzie patrze Czy może to być problem bezpieczeństwa między Windows i .NET, który jest unikalny dla tej instalacji? Jeśli tak, to gdzie mam skonfigurować relacje zaufania? Zgubiłem się!


W moim przypadku ten błąd został spowodowany przez przekierowanie adresu IP.
cja

Odpowiedzi:


166

Myśli (oparte na bólu w przeszłości):

  • czy masz DNS i linię wzroku do serwera?
  • czy używasz poprawnej nazwy z certyfikatu?
  • czy certyfikat jest nadal ważny?
  • czy źle skonfigurowany moduł równoważenia obciążenia psuje rzeczy?
  • robi nowe serwer ma poprawnie ustawiony zegar (tj. aby czas UTC był poprawny [zignoruj ​​czas lokalny, jest to w dużej mierze nieistotne]) - to z pewnością ma znaczenie dla WCF, więc może wpłynąć na zwykłe SOAP?
  • czy występuje problem z łańcuchem zaufania certyfikatów? jeśli przejdziesz z serwera do usługi mydła, czy możesz uzyskać SSL?
  • związane z powyższym - czy certyfikat został zainstalowany we właściwej lokalizacji? (może być potrzebna kopia w Zaufanych głównych urzędach certyfikacji)
  • czy serwer proxy na poziomie komputera jest ustawiony poprawnie? (który różni się od proxy użytkownika); zobacz proxycfg dla XP / 2003 (nie jestem pewien co do Vista itp.)

2
1) Usługa internetowa jest dostępna w Internecie. Możemy przejść do niego za pomocą przeglądarki. 2) Nowa maszyna nie jest serwerem - jest to komputer stacjonarny z moją aplikacją, który zbiera informacje o zamówieniach i przesyła je za pośrednictwem usługi SOAP 3) Tak, możemy na nią przejść. 4) To dla mnie nowość: proxy na poziomie komputera?
Rob Schripsema

2
Tak; kod nie korzysta z ustawień proxy IE; używa oddzielnego sklepu ... ważne jest, aby to skonfigurować (jeśli używasz proxy). W systemie XP najłatwiejszą opcją jest (IIRC) „proxycfg -i”, aby zaimportować ustawienia IE.
Marc Gravell

11
Dzięki Marc. Pomogło mi to, a problem polegał na tym, że serwer miał certyfikat podpisany przez inny urząd certyfikacji, któremu jeszcze nie ufałem. Rozwiązaniem było dodanie tego urzędu certyfikacji do listy zaufanych głównych urzędów certyfikacji.
p.campbell

1
Komputer z tym wyjątkiem nie mógł zsynchronizować czasu systemowego przy użyciu serwerów czasu. Musiałem wejść i ręcznie zsynchronizować czas, zanim zadziałało.
Chris - Haddox Technologies

4
Możesz to uzyskać, jeśli używasz Fiddlera do debugowania połączeń serwisowych i używałeś jego trybu przechwytywania certyfikatów. Po prostu usuń przechwycenie opcji skrzypka i powinieneś być dobry
Ruskin

363

Poniższe fragmenty naprawią przypadek, w którym coś jest nie tak z certyfikatem SSL na serwerze, do którego dzwonisz. Na przykład może być samopodpisany lub nazwa hosta między certyfikatem a serwerem może być niezgodna.

To jest niebezpieczne jeśli dzwonisz do serwera poza bezpośrednią kontrolą, ponieważ nie możesz być już tak pewien, że rozmawiasz z serwerem, z którym myślisz, że jesteś podłączony. Jeśli jednak masz do czynienia z serwerami wewnętrznymi i uzyskanie „poprawnego” certyfikatu jest niepraktyczne, skorzystaj z poniższych instrukcji, aby poinformować serwis internetowy o zignorowaniu problemów z certyfikatem i odważnym żołnierzu.

Pierwsze dwa używają wyrażeń lambda, trzeci używa kodu regularnego. Pierwszy akceptuje dowolny certyfikat. Co najmniej dwa ostatnie sprawdzają, czy nazwa hosta w certyfikacie jest tą, której się spodziewasz.
... mam nadzieję, że okaże się to pomocne

//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
Moje doświadczenie z ServicePointManager. Każda zmiana miałaby wpływ na całą domenę aplikacji. Chociaż odpowiedź jest bardzo jasno wyjaśniona, w jaki sposób można to zastosować, chciałbym rzucić ten punkt.
Amzath,

Ustawienie oddzwaniania działa w .NET 4.5 dla mnie, ale nie .NET 4.6
RJB

@Amzath Wszelkie sugestie, jak to zresetować po zakończeniu określonego żądania? Może być konieczne wysłanie jednej prośby do niecertyfikowanego serwera, a następnie przywrócenie poprzedniego stanu rzeczy.
Isaac Lyman,

1
@Isaac Lyman: ServicePointManager.ServerCertificateValidationCallback = null;powinien przywrócić domyślne zachowanie.
Mike Chamberlain

1
@MikeChamberlain Jedyny problem z twoją sugestią polega na tym, że jednoczesne żądania mogą stać się niepewne, ponieważ masz do czynienia z globalnym ustawieniem aplikacji.
Isaac Lyman

178

Bardzo proste rozwiązanie „złap wszystko” jest następujące:

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

Rozwiązanie od Sebastian-Castaldi jest nieco bardziej szczegółowe.


21
Po prostu wstawiłem to do #If CONFIG = "Debug"instrukcji, aby było aktywowane tylko w trybie debugowania. Działa świetnie!
cjbarth,

1
Szczegóły mogą być dobre, ale można też powiedzieć coś o szybkiej, krótkiej i łatwej linii kodu. Ten kod jest krótki i załatwia sprawę.
allen1

czy będzie to działać tylko w przypadku bieżącej akcji (np. używana jest ASP MVC)? czy będzie ustawiony jako domyślne zachowanie aplikacji ASP.NET?
JeeShen Lee,

2
Powinno to być wykorzystywane wyłącznie do celów testowych, to rozwiązanie ufa każdemu certyfikatowi, nawet niepoprawnemu /
wygasłem

1
Jak wyjaśniono w komentarzach powyżej, nie weryfikuje to, czy połączenie SSL jest już prawidłowe. Tak więc połączenie między twoim systemem a innymi systemami może zostać naruszone. Zawsze chodzi o to, do czego tego potrzebujesz.
Remy

35

Osobiście najbardziej podoba mi się następujące rozwiązanie:

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

... następnie zanim poprosisz o uzyskanie błędu, wykonaj następujące czynności

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

Znalazłem to po konsultacji z rozwiązaniem Luke'a


4
Zobacz odpowiedź Sebastiana Castaldiego, by zapoznać się z zastrzeżeniami bezpieczeństwa dotyczącymi tego podejścia.
Edward Brey

Jakie jest ryzyko bezpieczeństwa związane z użyciem tego w produkcji?
Amjad

@Amjad ryzyko związane z bezpieczeństwem polega na tym, że całkowicie pomija wszelkie korzyści wynikające z używania SSL / TLS. Serwer może przedstawić dowolny certyfikat, który mu się podoba, a ten kod zignoruje błąd
1800 INFORMACJE

18

Jeśli używasz systemu Windows 2003, możesz spróbować:

Otwórz Microsoft Management Console (Start -> Uruchom -> mmc.exe);

Wybierz Plik -> Dodaj / Usuń przystawkę;

Na karcie Samodzielny wybierz Dodaj;

Wybierz przystawkę Certyfikaty i kliknij Dodaj;

W kreatorze wybierz konto komputera, a następnie wybierz komputer lokalny. Naciśnij Zakończ, aby zakończyć działanie kreatora;

Zamknij okno dialogowe Dodaj / Usuń przystawkę;

Przejdź do Certyfikatów (komputer lokalny) i wybierz sklep do zaimportowania:

Jeśli masz certyfikat głównego urzędu certyfikacji dla firmy, która go wydała, wybierz Zaufane główne urzędy certyfikacji;

Jeśli masz certyfikat dla samego serwera, wybierz Inne osoby

Kliknij sklep prawym przyciskiem myszy i wybierz Wszystkie zadania -> Importuj

Postępuj zgodnie z instrukcjami kreatora i podaj posiadany plik certyfikatu;

Następnie ponownie uruchom IIS i spróbuj ponownie wywołać usługę sieci Web.

Odniesienie: http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS- ...


2
To mi pomogło, ale musiałem mieć certyfikat w sekcji Zaufane główne urzędy certyfikacji, aby działał. Zgodnie z blogs.msdn.com/b/jpsanders/archive/2009/09/16/…
Jacob Ewald

17

Jeśli nie chcesz ślepo ufać wszystkim i zrobić wyjątek zaufania tylko dla niektórych hostów, bardziej odpowiednie jest następujące rozwiązanie.

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;
      };
    }
}

Następnie po prostu wywołaj Ssl.EnableTrustedHosts podczas uruchamiania aplikacji.


@ thelem Tak ponowne czytanie Myślę, że musiałem źle odczytać za pierwszym razem
Shiv

Jakie ryzyko wiąże się z zaufaniem do wszystkich certyfikatów w produkcji?
Amjad

@Amjad ryzyko związane z bezpieczeństwem polega na tym, że każdy między klientem a serwerem może wstawić się w środek komunikacji, użyć własnego certyfikatu SSL i odczytać cały ruch między klientem a serwerem. W ten sposób skutecznie unieważnia SSL.
Rob Prouse

Czy powinno działać, gdy iam używa dodatku WCF do generowania klas z wsdl?
Kamil

7

Łukasz napisał całkiem niezły artykuł na ten temat .. całkiem prosto .. spróbuj tego

Rozwiązanie Luke'a

Powód (cytat z jego artykułu (bez przekleństwa)) „Problem z powyższym kodem polega na tym, że nie działa on, jeśli twój certyfikat nie jest prawidłowy. Dlaczego miałbym publikować na stronie internetowej z nieprawidłowym certyfikatem SSL? Jestem tani i nie chciałem płacić Verisign ani jednemu z pozostałych ** - * s za certyfikat do mojego testu, więc podpisałem go sam. Kiedy wysłałem prośbę, otrzymałem piękny wyjątek:

System.Net.WebException Połączenie podstawowe zostało zamknięte. Nie można ustanowić relacji zaufania ze zdalnym serwerem.

Nie wiem o tobie, ale dla mnie ten wyjątek wyglądał jak coś, co byłoby spowodowane głupim błędem w moim kodzie, który powodował niepowodzenie testu POST. Więc ciągle szukałem, poprawiałem i robiłem różne dziwne rzeczy. Dopiero po przejrzeniu wyszukiwarki *** n dowiedziałem się, że domyślnym zachowaniem po napotkaniu nieprawidłowego certyfikatu SSL jest zgłoszenie tego wyjątku. .. ”


1
To rozwiązanie jest przestarzałe dla .Net 4.5. Jeśli chcesz zaakceptować wszystkie certyfikaty, zobacz Sebastian Castaldi lub moją odpowiedź poniżej.
Remy


3

Właśnie napotkałem ten problem. Moim rozwiązaniem było zaktualizowanie czasu systemowego poprzez ręczną synchronizację z serwerami czasu. Aby to zrobić, możesz:

  • Kliknij prawym przyciskiem myszy zegar na pasku zadań
  • Wybierz Adjust Date/Time
  • Wybierz Internet Timezakładkę
  • Kliknij Change Settings
  • Wybierz Update Now

W moim przypadku synchronizacja była niepoprawna, więc musiałem ją kliknąć kilka razy, aby poprawnie zaktualizować. Jeśli nadal będzie się niepoprawnie aktualizować, możesz nawet spróbować użyć innego serwera czasu niż lista rozwijana serwera.


ŚWIĘTA KROWA. Wpadłem na to dokładnie. Dzięki za łatwą naprawę!
TheGerm

3

Spróbuj tego:

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

Zauważ, że musisz pracować co najmniej z 4.5 .NET Framework


3

Miałem podobny problem z .NETaplikacją w Internet Explorerze.

Rozwiązałem problem dodając certyfikat (certyfikat VeriSign Class 3 w moim przypadku) do certyfikatów zaufanych redaktorów.

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

Możesz uzyskać certyfikat, jeśli eksportujesz go z:

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

dzięki


1

Ten błąd działał na serwerze sieci Web z adresem URL takim jak:

a.b.domain.com

ale nie było na to certyfikatu, więc dostałem DNS o nazwie

a_b.domain.com

Po prostu podpowiedź do tego rozwiązania, ponieważ znalazło się na pierwszym miejscu w Google.


W moim przypadku witryna została skonfigurowana przy użyciu certyfikatu SSL z symbolem wieloznacznym (* .abcd.com). Po skonfigurowaniu powiązanie witryny było jak xyz-abcd.com, które było przyczyną problemu.
sree

1

Dla tych, którzy mają ten problem po stronie klienta VS, po pomyślnym dodaniu odwołania do usługi i próbie wykonania pierwszego połączenia, otrzymano następujący wyjątek: „Podstawowe połączenie zostało zamknięte: nie można ustanowić relacji zaufania dla bezpiecznego kanału SSL / TLS” Jeśli używasz (podobnie jak w moim przypadku) adresu URL punktu końcowego z adresem IP i otrzymałeś ten wyjątek, prawdopodobnie prawdopodobnie będziesz musiał ponownie dodać odwołanie do usługi, wykonując następujące kroki:

  • Otwórz adres URL punktu końcowego w przeglądarce Internet Explorer.
  • Kliknij błąd certyfikatu (czerwona ikona na pasku adresu)
  • Kliknij Wyświetl certyfikaty.
  • Złap wydane do: „nazwa” i zastąp adres IP lub dowolną nazwę, której używaliśmy, i pojawi się błąd dla tej „nazwy”.

Spróbuj ponownie :). Dzięki


0

W moim przypadku próbowałem przetestować SSL w moim środowisku Visual Studio przy użyciu IIS 7.

Tak właśnie skończyłem, aby to zadziałało:

  • Pod moją witryną w sekcji „Wiązania ...” po prawej stronie w IIS musiałem dodać powiązanie „https” do portu 443 i wybrać „IIS Express Development Development Certificate”.

  • W mojej witrynie w sekcji „Ustawienia zaawansowane ...” po prawej stronie musiałem zmienić „Włączone protokoły” z „http” na „https”.

  • Pod ikoną „Ustawienia SSL” wybrałem „Akceptuj” dla certyfikatów klientów.

  • Potem musiałem ponownie przetworzyć pulę aplikacji.

  • Musiałem również zaimportować certyfikat lokalnego hosta do mojego osobistego sklepu za pomocą mmc.exe.

Mój web.configplik został już poprawnie skonfigurowany, więc po rozwiązaniu wszystkich powyższych problemów mogłem kontynuować testowanie.


jak skonfigurowano twój web.config?
Chazt3n

@ Chazt3n Nie mogłem powiedzieć, że to było dawno temu, ale byłoby to podstawowe ustawienie wiązania http, zwykle używam svcutil do generowania informacji o konfiguracji dla informacji o kliencie usługi WWW.
Popo

0

Moje rozwiązanie (VB.Net, wersja „staging” (UAT) tej aplikacji musi współpracować z certyfikatem „staging”, ale nie może wpływać na żądania, gdy znajdą się w aktywnej witrynie):

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

Jeśli nie działa zły sertertyfikat, gdy ServerCertificateValidationCallback zwraca true; My ServerCertificateValidationCallback code:

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

Mój kod, który uniemożliwił wykonanie ServerCertificateValidationCallback:

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

Funkcja 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);
}

Wyłączyłem bardzo dobrze działający kod CertificateValidation i ServerCertificateValidationCallback


Nigdy nie należy wyłączać sprawdzania poprawności certyfikatu. Zamiast tego napraw problem powodujący niepowodzenie sprawdzania poprawności.
Dan

Jakie jest ryzyko bezpieczeństwa związane z użyciem tego w produkcji?
Amjad
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.