Jak rozwiązać problem „Nie można ustanowić relacji zaufania dla bezpiecznego kanału SSL / TLS z uprawnieniami”

135

Naprawdę myślałem, że naprawiłem ten problem, ale wcześniej był on tylko zamaskowany.

Mam usługę WCF hostowaną w usługach IIS 7 przy użyciu protokołu HTTPS. Kiedy przejść do tej strony w przeglądarce Internet Explorer, to działa jak czar, to dlatego, że nie dodaje certyfikat do lokalnego sklepu urzędzie certyfikacji korzeń.

Programuję na 1 maszynie, więc klient i serwer to ta sama maszyna. Certyfikat jest samopodpisywany bezpośrednio z przystawki zarządzania usługami IIS 7.

Ciągle otrzymuję ten błąd teraz ...

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

... przy wywołaniu z konsoli klienta.

Ręcznie nadałem sobie uprawnienia i usługę sieciową do certyfikatu, używając findprivatekeyi używając cacls.exe.

Próbowałem połączyć się z usługą za pomocą SOAPUI i to działa, więc musi to być problem w mojej aplikacji klienckiej, która jest kodem opartym na tym, co kiedyś działało z http.

Gdzie indziej mogę szukać. Wydaje mi się, że wyczerpałem wszystkie możliwości, dlaczego nie mogę się połączyć?

J L.
źródło
Jeśli masz kontrolę nad tworzeniem certyfikatów, nie zapomnij o „Alternatywnej nazwie podmiotu”. Na przykład możesz umieścić dziką kartę w „* .full.domainname.com”. Zobacz digicert.com/subject-alternative-name.htm
granadaCoder

Odpowiedzi:

198

Jako obejście można dodać do obsługi ServicePointManager„s ServerCertificateValidationCallbackpo stronie klienta:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

należy jednak pamiętać, że nie jest to dobra praktyka, ponieważ całkowicie ignoruje certyfikat serwera i informuje menedżera punktu usług, że każdy certyfikat jest prawidłowy, co może poważnie zagrozić bezpieczeństwu klienta. Możesz to udoskonalić i przeprowadzić niestandardowe sprawdzenie (nazwy certyfikatu, skrótu itp.). przynajmniej możesz ominąć problemy podczas programowania, używając certyfikatów testowych.

Joachim Kerschbaumer
źródło
9
Myślę, że większość publicznych instalacji będzie używać zakupionego certyfikatu, ale podczas tworzenia używaj powyższego kodu w warunkowych instrukcjach #if. Twórcy korporacyjni powinni generalnie skonfigurować wewnętrzny serwer CA >> technet.microsoft.com/en-us/library/cc875810.aspx
Luke Puplett
2
Pomógł mi dowiedzieć się, jak uzyskać moje wywołanie WCF SSL działające z Fiddler2 w celu debugowania.
Roger Willcocks,
2
@karank Rozważ umieszczenie go w metodzie Application_Start w Global.asax (patrz stackoverflow.com/a/12507094/1175419 ). Zdecydowanie polecam użycie dyrektywy kompilatora #if DEBUG lub czegoś podobnego, jak wspomniano w komentarzu Luke'a.
Rich C
4
Niesamowite! możesz użyć wyrażenia lambda jako System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777
Trochę dodatkowych wyjaśnień można znaleźć tutaj: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder
40

Kiedy mam ten problem, to dlatego, że client.config miał swoje punkty końcowe takie jak:

 https://myserver/myservice.svc 

ale certyfikat się spodziewał

 https://myserver.mydomain.com/myservice.svc

Zmiana punktów końcowych, aby pasowały do ​​nazwy FQDN serwera, rozwiązuje mój problem. Wiem, że to nie jedyna przyczyna tego problemu.

Mike Cheel
źródło
Po prostu znowu miałem ten problem i tym razem musiał to być zły certyfikat. Wygląda na to, że w obu przypadkach ma to związek z poprawnym dopasowaniem nazw.
Mike Cheel
3
W mojej automatycznie wygenerowanej konfiguracji <endpoint address = " localhost / myservice.svc " zmienił to na <endpoint address = " mymachine.mydoman.com/myservice.svc ".
knightscharge
To był absolutnie mój problem i znalezienie odpowiedzi zajęło mi dwa dni. +1, dałbym ci +1000, gdybym mógł.
AussieJoe
20

pierwsze dwa używają lambdy, trzeci używa zwykłego kodu ... mam nadzieję, że uznasz to za 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 = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }
Sebastian Castaldi
źródło
1
// Ufaj wszystkim certyfikatom System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // zaufany nadawca System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild
1
Każdy cracker mógłby sfałszować certyfikat, który przeszedłby wszystkie powyższe testy. To jest niebezpieczne.
Bjartur Thorlacius
19

Twój problem pojawia się, ponieważ używasz klucza z podpisem własnym. Klient nie ufa temu kluczowi, ani sam klucz nie zapewnia łańcucha do weryfikacji ani listy odwołania certyfikatów.

Masz kilka opcji - możesz

  1. wyłącz walidację certyfikatu na kliencie (zły ruch, obfitują ataki man in the middle)

  2. użyj makecert, aby utworzyć główny ośrodek certyfikacji i utworzyć z niego certyfikaty (ok, ruch, ale nadal nie ma CRL)

  3. utwórz wewnętrzny główny urząd certyfikacji za pomocą serwera certyfikatów systemu Windows lub innego rozwiązania PKI, a następnie zaufaj temu certyfikatowi głównemu (zarządzanie to trochę uciążliwe)

  4. kupić certyfikat SSL od jednego z zaufanych urzędów certyfikacji (drogie)

strzałka do dmuchawki
źródło
3
Jeśli chodzi o (4), StartSSL faktycznie da ci bezpłatny certyfikat klasy 1, który działa we wszystkich głównych przeglądarkach. Działają świetnie w przypadku moich pół tuzina witryn o niskiej przepustowości.
moodboom
Myślę, że # 2 na tej liście ... ten adres URL może pomóc: blogs.technet.microsoft.com/jhoward/2005/02/02/ ... „Jak używać MakeCert do zaufanego głównego urzędu certyfikacji i wydawania certyfikatów SSL”
granadaCoder
1
Uwaga: StartCom nie jest już godny zaufania - i właśnie została usunięta z Chrome en.wikipedia.org/wiki/StartCom
Simon_Weaver
16

Rozwiązanie w jednej linii. Dodaj to w dowolnym miejscu przed wywołaniem serwera po stronie klienta:

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

Powinno to być używane tylko do celów testowych, ponieważ klient pominie testy bezpieczeństwa SSL / TLS.

Gaspa79
źródło
2
Doskonałe obejście do testowania. Korzystamy z usługi, której dostawca sprawił, że bezpieczeństwo stało się piekłem dzięki zawiłemu łańcuchowi certyfikatów bezpieczeństwa i dopóki nie będziemy w stanie uzyskać ich wątpliwych certyfikatów i łańcucha do prawidłowego działania, to obejście jest jedyną rzeczą, która pozwala nam kontynuować rozwój.
markaaronky
12

Napotkałem ten sam problem i mogłem go rozwiązać dwoma rozwiązaniami: Najpierw użyłem przystawki MMC „Certyfikaty” dla „Konta komputera” i przeciągnąłem certyfikat z podpisem własnym do folderu „Zaufane główne urzędy certyfikacji” . Oznacza to, że komputer lokalny (ten, który wygenerował certyfikat) będzie teraz ufał temu certyfikatowi. Po drugie, zauważyłem, że certyfikat został wygenerowany dla jakiejś wewnętrznej nazwy komputera, ale usługa internetowa była dostępna przy użyciu innej nazwy. Spowodowało to niezgodność podczas walidacji certyfikatu. Wygenerowaliśmy certyfikat dla computer.operations.local, ale uzyskaliśmy dostęp do usługi internetowej przy użyciu https://computer.internaldomain.companydomain.com . Kiedy zmieniliśmy adres URL na ten używany do generowania certyfikatu, nie było więcej błędów.

Może samo przełączenie adresów URL by zadziałało, ale dzięki zaufaniu certyfikatu unikniesz również czerwonego ekranu w programie Internet Explorer, który informuje, że nie ufa certyfikatowi.

Jeroen-bart Engelen
źródło
11

Jeśli używasz .net core, spróbuj tego:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };
Grzegorz J
źródło
1
Dzięki, działa. Ale to nie ma nic wspólnego z .net core. To uniwersalny przepis :)
Alexander
7

Wykonaj następujące kroki:

  1. Otwórz łącze serwisowe w IE.

  2. Kliknij wzmiankę o błędzie certyfikatu na pasku adresu i kliknij Wyświetl certyfikaty.

  3. Czek wystawiony na: nazwisko.

  4. Weź wystawioną nazwę i zastąp wzmiankę localhost w nazwie adresu podstawowego punktu końcowego usługi i klienta na w pełni kwalifikowaną nazwę domeny (FQDN).

Na przykład: https: // localhost : 203 / SampleService.svc Do https: // INL-126166-.groupinfra.com : 203 / SampleService.svc

Rahul Rai
źródło
Świetnie, dzięki za tę odpowiedź! Rozwiązano problemy bez wprowadzania zmian w kodzie.
Vipin Dubey
6

Oprócz powyższych odpowiedzi możesz napotkać ten błąd, jeśli Twój klient ma niewłaściwą wersję TLS, na przykład jeśli serwer działa tylko z TLS 1.2.

Możesz to naprawić, używając:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
NMrt
źródło
w moim przypadku zaakceptowana odpowiedź mi nie pomogła, ale ta nie pomogła
Siergiej
To jedyna odpowiedź, która poprawiła błąd w moim przypadku.
Tolga
5

Miałem ten sam problem. Dodałem też certyfikaty CA w lokalnym sklepie, ale zrobiłem to w NIEPRAWIDŁOWY sposób.

Używając konsoli mmc (Start -> Uruchom -> mmc ) należy dodać przystawkę Certyfikaty jako konto usługi (wybierając konto usługi IIS) lub konto komputera (dodaje się do każdego konta na komputerze)

Tutaj obraz tego, o czym mówię Dodaj przystawkę dla konta usługi lub konta komputera

Od teraz możesz dodawać certyfikaty urzędów certyfikacji ( zaufane główne urzędy certyfikacji i pośrednie urzędy certyfikacji ) i wszystko będzie działać dobrze

dar0x
źródło
4

Miałem podobny problem z certyfikatem z podpisem własnym. Mogłem rozwiązać ten problem, używając nazwy certyfikatu takiej samej jak FQDN serwera.

W idealnym przypadku część SSL powinna być zarządzana po stronie serwera. Klient nie musi instalować żadnego certyfikatu SSL. Ponadto niektóre posty wspomniały o omijaniu SSL z kodu klienta. Ale całkowicie się z tym nie zgadzam.

Umesh Bhavsar
źródło
3

Po prostu przeciągnąłem certyfikat do folderu „Zaufane główne urzędy certyfikacji” i wszystko działało dobrze.

O. I najpierw dodałem następujące z wiersza polecenia administratora:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

Nie jestem pewien, jakiej nazwy potrzebujesz dla użytkownika (moja jest norweska, jak widzisz!) user=NT-AUTHORITY/INTERACTIVE:?

Możesz zobaczyć wszystkie istniejące adresy URL, wydając polecenie: netsh http show urlacl

Haguna
źródło
0

Wystąpiło to podczas próby nawiązania połączenia z usługą WCF za pośrednictwem. IP np. https://111.11.111.1:port/MyService.svcpodczas używania certyfikatu powiązanego z nazwą np. mysite.com.

Przełączam się na https://mysite.com:port/MyService.svcrozwiązany.

lko
źródło
0

Właśnie rozwiązałem podobny problem.

Uświadomiłem sobie, że mam pulę aplikacji działającą na koncie, które miało tylko uprawnienia do odczytu certyfikatu, którego było używane.

Aplikacja .NET mogła poprawnie pobrać certyfikat, ale ten wyjątek został zgłoszony tylko wtedy, gdy wywołano GetRequestStream ().

Uprawnieniami do certyfikatów można zarządzać za pomocą konsoli MMC

Alberto
źródło
0

W przypadku korzystania z .net core podczas programowania można ominąć sprawdzanie poprawności certyfikatu przy użyciu dyrektyw kompilatora. W ten sposób zweryfikuje certyfikat tylko do wydania, a nie do debugowania:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif
Panayiotis Hiripis
źródło
-6

Dodaj to do swojego kodu klienta:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });
user662285
źródło
4
Ta odpowiedź nie jest zbyt dobra, ponieważ nie wyjaśnia zagrożeń związanych z kodem.
daveD