Die gesicherte Verbindung zu einem Server ist nach einem Zertifikatswechsel nicht mehr möglich. Es kommt der Fehler „The request was aborted: Could not create SSL/TLS secure channel“ bzw. „Die Anfrage wurde abgebrochen: Es konnte kein geschützter SSL/TLS-Kanal erstellt werden.“
Problem
Nachdem Zertifkatswechsel bei einem Server, ist die Verbindung von einem dotNet Programm, das auf einem Windows Server 2012R2 läuft, nicht mehr möglich. Es kommt immer der Fehler „Die Anfrage wurde abgebrochen: Es konnte kein geschützter SSL/TLS-Kanal erstellt werden.“ bzw. „The request was aborted: Could not create SSL/TLS secure channel“ Bei den Verbindungsmöglichkeiten ist nur mehr das Verschlüsselungsprotokoll TLS1.2 erlaubt.
Code
HttpWebRequest webReq = null; byte[] buffer = Encoding.UTF8.GetBytes(jsonData); ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; webReq = (HttpWebRequest)WebRequest.Create(webServiceUrl + "/fibu/daten/"); webReq.ContentType = "application/json"; webReq.Method = WebRequestMethods.Http.Post; webReq.Headers["Authorization"] = Convert.ToString(authResult.token_type) + " " + Convert.ToString(authResult.access_token); webReq.ContentLength = buffer.LongLength; Stream reqstr = webReq.GetRequestStream(); reqstr.Write(buffer, 0, buffer.Length); reqstr.Close();
Code nach Recherche
Wenn man die Fehlermeldung bei Google eingibt kommen unzählige Lösungsvorschläge, somit habe ich den Code geändert. Wobei es anscheinend auch wichtig ist, dass die Angaben zum ServicePointManager vor der Erstellung von WebRequest.Create gehören.
HttpWebRequest webReq = null; byte[] buffer = Encoding.UTF8.GetBytes(jsonData); ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; webReq = (HttpWebRequest)WebRequest.Create(webServiceUrl + "/fibu/daten/"); webReq.ContentType = "application/json"; webReq.Method = WebRequestMethods.Http.Post; webReq.Headers["Authorization"] = Convert.ToString(authResult.token_type) + " " + Convert.ToString(authResult.access_token); webReq.ContentLength = buffer.LongLength; webReq.Timeout = 20 * 1000; Stream reqstr = webReq.GetRequestStream(); reqstr.Write(buffer, 0, buffer.Length); reqstr.Close();
Leider war das aber nicht die Lösung, der Fehler bestand weiter.
Lösung Teil 1 – TLS 1.2 Protokoll am Server aktiviert?
Nachdem bei der Änderung des Zertifikat nur mehr TLS1.2 Verbindungen erlaubt wurden, implementierte ich die Einschränkungen auf das Security Protokolls auf TLS12 im Code. Des Weiteren muss kontrolliert werden, ob der Computer bzw. Server, auf dem das Programm läuft, überhaupt TLS12 aktiviert hat.
Ein Anhaltspunkt ist einmal die Aufstellung der Liste „TLS protocol version support“ bei Microsoft, die hier zu finden ist. Des Weiteren ist noch das gratis Tool IIS Crypto für Recherchen, aber auch für Änderungen, wichtig. So kann man schon mal heraus finden, ob TLS12 überhaupt möglich ist, und was generell aktiviert ist.
Es ist auch möglich, das Protokoll in der Registry zu aktivieren.
- HLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols
- Einträge:
- DisabledByDefault => 0,
- Enabled => 0XFFFFFFFFF oder Enabled => 1
Leider half das auch alles nichts, es kam kein TLS Handshake zusammen.
Lösung Teil 2 – Recherche im EventVwr
Im Eventviewer gab es bei jedem Versuch einen Eintrag von einem Schannel Fehler. Wobei der Schannel Code 40 lt. Microsoft, folgendes bedeutet:
- SSL3_ALERT_HANDSHAKE_FAILURE.
SSL3 obwohl im C# Code auf TLS12 eingeschränkt wurde, und schlussendlich auch am Server in der RegEdit auf Enabled=0 gesetzt wurde. Diese Fehlermeldung war einfach nicht weg zu bekommen.
Lösung Teil 3 – TLS Ciphersuit Missmatch
Ein Kollege, der sich gut bei Server und Netzwerk auskennt, hat sich dann der Sache angenommen und ist auf einen „TLS Ciphersuit Missmatch“ gestoßen. D.h. soviel wie, dass zwei Computer sich nicht auf einen Algorithmus zum Aufbau einer gesicherten Datenverbindung einigen konnten. Die beiden Computer hatten kein übereinstimmendes Verfahren konfiguriert.
Am eigenen Computer kann man wie folgt nachschauen, welche Ciphersuits aktiviert sind:
- Powershell: Command Get-TlsCipherSuite
- gpedit.msc:
Administrative Vorlagen > Netzwerk > SSL-Konfigurationseinstellungen
rechte Maustaste bei „Reihenfolge der SSL-Verschlüsselung“ und bearbeiten
Leider ist zum Beispiel unter Windows 10 dort nichts zu finden, unter Windows 2021R2 gibt es eine Liste von Verfahren - Tool IIS Crypto
Welche Verfahren der entfernte Server konfiguriert hat, kann man auf verschiedenste Weise erfahren, zum Beispiel:
- FireFox unter Seiteninformation und Reiter Sicherheit (Technische Details,Verbindung verschlüsselt)
- Google Chrome unter Entwickler Tools (F12) und Reiter Security/Sicherheit
- TestSSLServer auf GitHub (leider schon etwas älter)
- Python Skript sslyze auf GitHub
- SSL Server Test auf sssllabs.com (Server muss natürlich öffentlich erreichbar sein)
- Bash Skripte (verschiedenste Versionen im Forum unter folgenden Eintrag bei superuser.com zu finden)
Lösung und Fazit
Gott sei Dank war auch der entfernte Server unter der Kontrolle vom Kollegen, so konnte er dort 2 Ciphersuits hinzufügen, bei denen er gewusst hat, dass es der Server (2012 R2), auf dem unser Programm gelaufen ist, auch konfiguriert hat. Danach war sofort eine Verbindung möglich! Der Fehler gehörte der Vergangenheit an.
Leider ist es manchmal nicht möglich, die Lösung programmiertechnisch zu lösen. Es muss auch der Server/Computer von Sender und Empfänger aufeinander abgestimmt sein.
Links
- Micorosft – TLS protocol version Support
- Microsoft – Schannel Error Codes for TLS and SSL Alerts
- NARTAC Software – IIS Crypto Download
- Wikipedia (de) – Cipher Suite
- Wikipedia (en) – Cipher Suite
- venafi.com – Validate Cipher Suites Offered To Servers From Windows
- Microsoft – Windows Server 2012 R2 TLS 1.2 Cipher Suites
Alle Angaben ohne Gewähr!