Nie można utworzyć bezpiecznego kanału SSL / TLS, pomimo ustawienia ServerCertificateValidationCallback


85

Próbuję nawiązać połączenie SSL / TLS z serwerem testowym z certyfikatem z podpisem własnym . Komunikacja przez niezabezpieczony kanał działała bez problemów.

Oto mój przykładowy kod, który napisałem w oparciu o następujące rozwiązania: Zezwalanie na niezaufane certyfikaty SSL z HttpClient C # Ignorować błędy certyfikatu? Klient .NET łączący się z interfejsem API sieci Web 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));
}

również próbowałem tego:

var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = delegate { return true; };
var c = new HttpClient(handler);
...

i to

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

ale za każdym razem mam wyjątek:

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: 

Co robię źle? Dlaczego nie mogę połączyć się z tym serwerem (który ma nieprawidłowy certyfikat z podpisem własnym)

Odpowiedzi:


166

Robisz to dobrze z ServerCertificateValidationCallback. To nie jest problem, z którym się borykasz. Problem, z którym się spotykasz, to najprawdopodobniej wersja protokołu SSL / TLS.

Na przykład, jeśli twój serwer oferuje tylko SSLv3 i TLSv10, a twój klient potrzebuje TLSv12, otrzymasz ten komunikat o błędzie. Musisz upewnić się, że zarówno klient, jak i serwer mają wspólną wersję protokołu.

Kiedy potrzebuję klienta, który jest w stanie połączyć się z jak największą liczbą serwerów (zamiast być tak bezpiecznym, jak to tylko możliwe), używam tego (razem z ustawieniem wywołania zwrotnego walidacji):

  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

1
Mam podobny problem. Z powodu ataku POODLE jesteśmy zmuszeni wyłączyć TLS 1.0 na naszym serwerze. Kiedy to robię, aplikacja innej firmy przestaje działać. Dekompilacja asamblicznie pokazuje kod podobny do twojego. Używa webclientc.SendAsync zamiast GetAsync. Jeśli skopiuję kod do aplikacji consoleapp w celu przetestowania, mogę odtworzyć błąd, a dodając ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 działa. Pomyślałem, że będzie jakiś rodzaj uzgadniania między serwerem a klientem, aby odkryć, której wersji TLS użyć? Dlaczego nie wybiera automatycznie wersji 1.1, gdy wersja 1.0 jest wyłączona?
Engern

3
Dzięki! Walczył z tym przez 3 godziny. Dodanie tej linii zrobiło to dla mnie:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thomas T

1
Zauważ, że nowsza wersja .NET ma to włączone domyślnie, wszystko, co musieliśmy zrobić, to ustawić wersję .NET na 4.6.1
martinh_kentico

1
To dokładnie oznacza, że, ważne czy nie, nie obchodzi cię to. To wywołanie zwrotne pozwala po prostu uniknąć wszelkich kontroli bezpieczeństwa tego certyfikatu.
Wapac

1
Świetna odpowiedź, wydaje mi się, że ta ServicePointManager.SecurityProtocolwartość może być domyślna. A przynajmniej powinno być więcej wglądu bezpośrednio w rzucony Wyjątek.
Czad

28

Właśnie dzisiaj rozwiązaliśmy ten sam problem i wszystko, co musisz zrobić, to zwiększyć wersję środowiska wykonawczego .NET

4.5.2 nie działało dla nas z powyższym problemem, podczas gdy 4.6.1 było OK

Jeśli chcesz zachować wersję .NET, ustaw

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

1
Którego z wariantów użyłeś i jak dokładnie?
martinh_kentico

1
Mam aplikację .NET 4.5, która od dzisiaj nie będzie działać z określoną witryną SSL. Jeśli zmienię na 4.6.1, działa dobrze, ale tak naprawdę nie mogę tego zmienić. Nie jestem pewien, co mam zrobić: |
Tsury

16

Jako kontynuacja dla każdego, kto nadal ma problem - dodałem opcje ServicePointManager.SecurityProfile, jak zauważono w rozwiązaniu:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Mimo to nadal otrzymywałem ten sam błąd „Żądanie zostało przerwane: nie można utworzyć bezpiecznego kanału SSL / TLS”. Próbowałem połączyć się z niektórymi starszymi serwerami głosowymi z interfejsami HTTPS SOAP API (np. Poczta głosowa, systemy telefoniczne IP itp.… Zainstalowane lata temu). Obsługują one tylko połączenia SSL3, ponieważ były ostatnio aktualizowane lata temu.

Można by pomyśleć, że włączenie SSl3 do listy SecurityProtocols załatwiłoby sprawę, ale tak się nie stało. Jedynym sposobem, w jaki mogłem wymusić połączenie, było włączenie TYLKO protokołu Ssl3 i żadnych innych:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Potem następuje połączenie - wydaje mi się, że to błąd, ale dopiero niedawno zaczęło to powodować błędy w narzędziach, które udostępniam dla tych serwerów, które istnieją od lat - uważam, że Microsoft zaczął wprowadzać zmiany systemowe, które to zaktualizowały zachowanie wymuszające połączenia TLS, chyba że nie ma innej alternatywy.

W każdym razie - jeśli nadal napotykasz to na niektóre stare witryny / serwery, warto spróbować.


1
Mamy moduł CUCMPowerShell do korzystania z interfejsu API Cisco Unified Communications AXL za pośrednictwem PowerShell, a Twoja odpowiedź pomogła nam to naprawić, dodając [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Ssl3. Dziękuję Ci! Pełny kod można zobaczyć w funkcji Invoke-CUCMSOAPAPIFunction
Chris Magnuson

2
@Jeff - Sprawdź powiązany artykuł. Myślę, że może to wyjaśniać, dlaczego Ssl3 nie działa i sugeruje dwa sposoby ponownego włączenia Ssl3. docs.microsoft.com/en-us/dotnet/framework/migration-guide/…
Scott

4

przenieś tę linię: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Przed tym wierszem: HttpWebRequest request = (HttpWebRequest) WebRequest.Create (uri);

Oryginalny post: Aktualizacja zabezpieczeń KB4344167 łamie kod TLS


1
Po wypróbowaniu wszystkich powyższych bezskutecznie, oto odpowiedź: przed utworzeniem HttpWebRequest należy ustawić ServicePointManager.
Henry Rusted

2

W moim przypadku TLS1_2 był włączony zarówno na kliencie, jak i na serwerze, ale serwer używał MD5, podczas gdy klient go wyłączył. Przetestuj więc zarówno klienta, jak i serwer na http://ssllabs.com lub użyj openssl / s_client, aby zobaczyć, co się dzieje. Sprawdź również wybrany szyfr za pomocą Wireshark.


1

Protokół TLS 1.0 i 1.1 dobiegł końca. Pakiet na naszym serwerze internetowym Amazon został zaktualizowany i zaczęliśmy otrzymywać ten błąd.

Odpowiedź jest wyżej, ale nie powinno się używać tlslub tls11więcej.

W szczególności w przypadku ASP.Net dodaj to do jednej z metod uruchamiania.

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

ale jestem pewien, że coś takiego zadziała w wielu innych przypadkach.


0

Jeśli używasz nowej nazwy domeny i wykonałeś wszystkie powyższe czynności, ale nadal pojawia się ten sam błąd, sprawdź, czy wyczyściłeś pamięć podręczną DNS na swoim komputerze. Wyczyść swój DNS, aby uzyskać więcej informacji.

Windows® 8

Aby wyczyścić pamięć podręczną DNS, jeśli używasz systemu Windows 8, wykonaj następujące czynności:

Na klawiaturze naciśnij Win + X, aby otworzyć menu WinX.

Kliknij prawym przyciskiem myszy Wiersz polecenia i wybierz Uruchom jako administrator.

Uruchom następujące polecenie:

ipconfig / flushdns

Jeśli polecenie się powiedzie, system zwraca następujący komunikat:

Konfiguracja adresu IP systemu Windows pomyślnie opróżniła pamięć podręczną mechanizmu rozpoznawania nazw DNS.

Windows® 7

Aby wyczyścić pamięć podręczną DNS, jeśli używasz systemu Windows 7, wykonaj następujące czynności:

Kliknij Start.

Wpisz cmd w polu tekstowym wyszukiwania w menu Start.

Kliknij prawym przyciskiem myszy Wiersz polecenia i wybierz Uruchom jako administrator.

Uruchom następujące polecenie:

ipconfig / flushdns

Jeśli polecenie się powiedzie, system zwróci następujący komunikat: Konfiguracja protokołu IP systemu Windows pomyślnie opróżniła pamięć podręczną mechanizmu rozpoznawania nazw DNS.


ipconfig /flushdnsw C #?
Kiquenet

0

Natknąłem się na ten wątek, ponieważ wystąpił również błąd Nie można utworzyć bezpiecznego kanału SSL / TLS. W moim przypadku próbowałem uzyskać dostęp do interfejsu API REST konfiguracji Siebel z programu PowerShell przy użyciuInvoke-RestMethod i żadna z powyższych sugestii nie pomogła.

W końcu natknąłem się na przyczynę mojego problemu: serwer, z którym się kontaktowałem, wymagał uwierzytelnienia certyfikatu klienta.

Aby wywołania zadziałały, musiałem podać certyfikat klienta (w tym klucz prywatny) z -Certificateparametrem:

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

Mam nadzieję, że moje doświadczenie pomoże komuś, kto ma mój szczególny smak tego problemu.

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.