-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.Net 6/Win11 HttpClient HandshakeFailure TLS issue #77393
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsDescriptionI recently updated my laptop to Windows 11 and while developing a ASP.Net Core application running on .Net 6, I ran into an issue with an HttpClient service that had been working fine on Windows 10. It appears that Windows 11 prefers TLS 1.3 while the server (Pivotal Cloud Foundry/Tanzu) is limited to TLS 1.2. I was able to force TLS1.2 with the following code:
I hate hard coding to TLS 1.2, because eventually the server environment will support TLS 1.3. Reproduction StepsSee descrption Expected behaviorWindows 11 HttpClient should be able to down shift to TLS 1.2 Actual behaviorHandshakeFailure exception when HttpClient makes a request to a server limited to TLS 1.2 Regression?This works on Windows 10/Linux clients. Known WorkaroundsForce SslProtocols.Tls12 ConfigurationWindows 11, .Net 6.0.10 Other informationNo response
|
Tagging subscribers to this area: @dotnet/ncl, @vcsjones Issue DetailsDescriptionI recently updated my laptop to Windows 11 and while developing a ASP.Net Core application running on .Net 6, I ran into an issue with an HttpClient service that had been working fine on Windows 10. It appears that Windows 11 prefers TLS 1.3 while the server (Pivotal Cloud Foundry/Tanzu) is limited to TLS 1.2. I was able to force TLS1.2 with the following code:
I hate hard coding to TLS 1.2, because eventually the server environment will support TLS 1.3. Reproduction StepsSee descrption Expected behaviorWindows 11 HttpClient should be able to down shift to TLS 1.2 Actual behaviorHandshakeFailure exception when HttpClient makes a request to a server limited to TLS 1.2 Regression?This works on Windows 10/Linux clients. Known WorkaroundsForce SslProtocols.Tls12 ConfigurationWindows 11, .Net 6.0.10 Other informationNo response
|
Can you share packet captures @awdorrin? This should work as long as there is overlap. It is the server who picks the version and cipher suite. |
Wireshark kept locking up on me but I believe I have the exchange captured. |
Hello offers 4 versions in |
I captured packets for a successful request, after adding back the CofnigurePrimaryHttpMessageHandler code that specifies the SslProtocol as Tls12. In that exchange, it appears the server and client negotiate That same protocol is listed in the exchange where the handshake fails. |
Do you know what OS and SSL is running on the server? And if you can check, is there any error? The handshake fails immediately after client sends the ClientHello (and server response with fatal alert) This looks like general interop issue with Schannel. Since the failure is on the server, I don't think collecting Schannel traces on client client would help. |
The server app is implemented by another team within my company. I may be able to find out more details, but all I know it is running within a Pivotal Cloud Foundry server instance. I believe it is a Linux buildpack. If it were something in the server configuration, I just don't understand how setting the SslProtocol in the client would make it work cleaner? What I did just notice, is in the second 'Client Hello' packet, which the package capture claims is TLSv1.2 protocol. That when you drill into the TLSv1.2 record, it still states that the Version is TLS 1.0 (0x0301) This makes me think that .Net is not building the 'Client Hello' packet correctly when negotiating after the first TLSv1 ClientHello packet fails, as I would expect that internal version to read TLS 1.2 (0x0303)
In the capture where I enable the SslProtocol.Tls12, that section of the packet reads:
I'm thinking that those bytes (03 01) are wrong, and should be (03 03) but something isn't populating the field correctly in the second attempt. |
The hello is not created by .NET. We only call Windows functions to make it happen. The versions are more complicated. There is version in the frame header, then the handshake as well as there is extension showing all supported versions. Typically all the versions would be set low as much as practical and server picks the stronger option. I don't know how the posted capture correspond to the text. But the second hello is on different TCP connection. And according to the capture it happens before first one fails. It may be worth of creating simples possible repro with just HttpClient for the experiments and investigation. Unless you can reproduce it agains some generic Linux or public server this is really not actionable for us. If the server is reachable from Internet you can try something like https://www.ssllabs.com/ssltest/ to gather more information about supported capabilities. |
Here are two more capture files. One that works with SslProtocol.Tls12 set, and the other without that setting, that fails. It doesn't jump IPs (which I think may have been caused by a load balancer, not sure though...) If .net is not building the packets being sent for the Hello, then I guess this may be a bug in the lower level windows functions that are building the packets. |
When I compare the "bad" capture with capture to e.g. https://microsoft.com, I get almost exactly the same ClientHello. The only difference seems to be server_name (obviously) and that the bad capture adds two more cipher suites (TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f) and TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)). But that should not make any difference. As far as I can tell, this is a problem on the server side. When you explicitly specify TLS 1.2 only, the client does not send supported_versions extension, which is the only thing I can imagine makes difference here. When client offers TLS 1.3, the server panics and fails the handshake instead of picking the lower version. |
To clarify, in the captures above, my laptop is 147.170.184.176 and the remote server is either 146.69.2.26 or 146.60.2.126. |
Win10 does not support TLS 1.3, so the client will not offer it, don't know about the PCF Linux. As a test, you can try disabling TLS 1.3 via registry by setting |
as @rzikm mentioned, it should work ... but obviously it does not. You also mentioned load balancer. Is there anything in the middle inspecting traffic. You may run to something like https://knowledge.broadcom.com/external/article/185069/cannot-access-ssl-sites-using-tlsv3.html @awdorrin. While peers should not be overwhelmed by new ciphers and versions they sometimes do. |
I created the registry key that @rzikm mentioned and removed the code to set the protocol to TLS1.2, and the TLS handshake worked from my Windows 11 system. Looking at the packet captures, when things work, I don't see any exchange of 'supported_versions', it seems to already know that it needs to use TLS 1.2 - and I do not understand how that knowledge is being exchanged. When I'm not forcing TLS 1.2 (either by not having that registry key, or by using the Ssl12 flag in code), I do see that the TLS 'client hello' that has the remote server IP as the source, is listing TLS 1.3 (even though I've been told that the remote servers do not yet support TLS 1.3...) So, I am coming around to this being a server side issue. I just seem to be missing something before that first 'Client Hello' packet that must be giving a hint or information that it should default to TLS 1.2. I do recall there is some means of getting the encryption key from your browser and providing that to Wireshark so that it can decode the HTTPS packets, but for some reason, Wireshark is incredibly unstable on my laptop, and quickly stops responding while I'm trying to capture these packets. As thing happen, I just received a new laptop to replace my current one, so once I get up and running on the new system (which I'm not sure if it will be Win10 or 11 yet) I'll have to do some more testing. Thanks |
The
Some browser (firefox, chrome) support exporting session keys by setting a Since this seems not to be a .NET issue, I will close this issue. |
Thank you! This issue is still there. I can reproduce it in latest VS2022 with .NET 7. Windows 11 Pro 22000.1219. It also no longer work to do "ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;" instead of suggested solution. Stacktrace:
Messages: The SSL connection could not be established, see inner exception. The message received was unexpected or badly formatted. Authentication failed because the remote party sent a TLS alert: 'HandshakeFailure'. |
|
I believe it depends on how the HttpClient is created in old .NET Framework. |
the comment about |
Description
I recently updated my laptop to Windows 11 and while developing a ASP.Net Core application running on .Net 6, I ran into an issue with an HttpClient service that had been working fine on Windows 10.
It appears that Windows 11 prefers TLS 1.3 while the server (Pivotal Cloud Foundry/Tanzu) is limited to TLS 1.2.
Attempts to connect from the code running on Windows 11 results in a HandshakeFailure exception during the service's query via HttpClient.
I was able to force TLS1.2 with the following code:
I hate hard coding to TLS 1.2, because eventually the server environment will support TLS 1.3.
I did try setting the SslProtocols to:
SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
however that brought back the HandshakeFailure exception.
Reproduction Steps
See descrption
Expected behavior
Windows 11 HttpClient should be able to down shift to TLS 1.2
Actual behavior
HandshakeFailure exception when HttpClient makes a request to a server limited to TLS 1.2
Regression?
This works on Windows 10/Linux clients.
Known Workarounds
Force SslProtocols.Tls12
Configuration
Windows 11, .Net 6.0.10
Other information
No response
The text was updated successfully, but these errors were encountered: