-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Transport Layer Security (TLS) best practices with the .NET Framework #4675
Comments
@Rick-Anderson @mairaw hello. Would like to clarify the information present in the following section - https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#for-wcf-using-net-framework-35---452-using-tcp-transport-security-with-certificate-credentials.
Do I understand correctly that it covers the case with basic http binding that uses certificate for authentication on the transport level? <binding name="some-binding" >
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding> Thanks. |
Hi @RamanBut-Husaim. The section which you quoted only applies to using the TCP transport in WCF. For the HTTP transport with a WCF client doesn't do anything specific. Internally we use HttpWebRequest so we will just have the behavior that HttpWebRequest will have. For the HTTP transport with a WCF client, we have the behavior that the OS components IIS or HTTP.SYS are configured to use. |
@mconnew Understood. Thanks a lot for the quick reply! |
Hi @Rick-Anderson, the article covers enabling TLS 1.2 quite well, is it possible to extend it with information about how to enforce TLS 1.2? |
@bjorncoltof I don't believe we have mechanisms to forbid certain protocol versions via app-wide/machine-wide configuration (incl. registry). Maybe the OS has something like that? cc @davidsh |
Yes, Windows OS has registry keys you can set to enable/disable various TLS protocol versions. See: https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings For example:
|
https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/manage-ssl-protocols-in-ad-fs also has some powershell should you want to avoid the regedit. |
I am a little confused after reading your article - https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#if-your-app-targets-a-net-framework-version-earlier-than-47 In the section - If your app targets a .NET Framework version earlier than 4.7 - For .NET Framework 3.5 - 4.5.1 and not WCF it is mentioned - Set the SchUseStrongCrypto and SystemDefaultTlsVersions registry keys to 1 As per our tests with sample applications, we do not require SystemDefaultTlsVersions for going TLS 1.2. The presence of SchUseStrongCrypto is good enough for any apps which are targeting .NET 4.0 - 4.6.2 to move to TLS 1.2. The explanation of SystemDefaultTlsVersions in the same documents, only mentions the cases, when 4.7 is installed on the system. Can you please confirm the correct one? Regards, |
The difference between SchUseStrongCrypto and SystemDefaultTlsVersions is subtle. Both of them will indeed add Tls1.1 and Tls1.2 to the set of possible protocols. And doing so implies that the strongest protocol (in this case Tls1.2) would be offered first to a server. Assuming the server supported Tls1.2, the end result would be Tls1.2. The difference between those two registry entries is as follows. SchUseStrongCrypto will always drop Ssl3.0 as well as any cipher suites from Tls1.0 et. al. that are considered insecure such as RC4. SchUseStrongCrypto will also set the default ServicePointManager.SecurityProtocol property to use "Tls1.0 | Tls 1.1 | Tls1.2" as the default. However, note that this list is fixed. Using SystemDefaultTlsVersions, on the other hand, causes the same See the matrix of OS versions TLS protocols here: The guidance given in our documentation is that for new code the recommendation is to use patterns such as SystemDefaultTlsVersions to let the OS make the best decision. For new .NET Framework applications targeting 4.7 and later, these registry keys are not needed and the equivalent "SystemDefault" values are used. |
@davidsh The move to use SystemDefaultTlsVersions is not comprehensive. An application has a single config file. And if we set the application config to use System default, it will fail on Windows 7 and Windows 2008R2, where TLS 1.0 is the default protocol. Also, do you know whether the support for SystemDefaultTlsVersions is there in frameworks 4.0 - 4.6.2. I do not see any documentation which points to a Windows update, which added support for these. |
SystemDefaultTlsVersions is only supported in .NET 4.7 and above. |
I have a scenario with a Windows 7 machine with 4.7.1 installed and a WPF application that targets 4.7.1. The app isn't setting the SystemDefaultTlsVersions, and therefore should be using the OS default (which should be TLS 1.0, since 1.1 and 1.2 aren't enabled by default on Win7). The endpoint I'm calling from the WPF app has TLS1, 1.1, and 1.2 enabled. I'm getting a connection error in the WPF app unless I enable TLS 1.2 in Windows 7. Is this the expected behaviour for WPF apps running 4.7.1? |
Yes, unfortunately. If your app is targeting .NET 4.7.x, then effectively you are using 'SystemDefaultTlsVersions' regardless of you setting the registry key. The behavior default is ON when targeting .NET 4.7.x. On Windows 7 / Windows Server 2008 R2, the default set of TLS protocols in the OS doesn't include TLS 1.1 nor 1.2. So, the highest you will get then is TLS 1.0. But since your service only allows TLS 1.1 and TLS 1.2, you will thus be unable to connect with your client. The workaround in this case (if you need to run on Windows 7 / Windows Server 2008 R2) would be manually configure the TLS versions using ServicePointManager properties. And also make sure that the applicable Windows updates are used on Windows 7 to enable TLS 1.1 and 1.2. |
Hi @davidsh - My group works on an assembly which might be used in various contexts (some we don't control). This assembly makes rest calls to a server we would like to limit to accepting tls1.2 > connections. When referenced by other applications we would like to avoid hard coding TLS 1.2 and effecting future protocols for the referencing application. We are currently limited to targeting .net 4.5.2 in our assembly - but the referencing application may be a more recent .net version. Is there a way to check what protocols are currently supported by the user's machine before setting: ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; something like if(!(TLS1.2_Enabled)){
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
} Does this functionality exist in .net? |
@Rick-Anderson @mairaw hello. Would like to clarify the information present in the following section - https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#for-wcf-using-net-framework-35---452-using-tcp-transport-security-with-certificate-credentials. These versions of the WCF framework are hardcoded to use values SSL 3.0 and TLS 1.0. These values cannot be changed. You must update and retarget to NET Framework 4.6 or later versions to use TLS 1.1 and 1.2. What about WCF frameworks (3.5 to 4.5.2) that are using TCP transport security with windows authentication? This seems to be left out in the article - Does the hardcoding to use SSL3.0 and TLS 1.0 still apply? |
Not really. Support for the various TLS protocols depends on a number of factors including .NET version and Windows OS version. And "support" could mean different things, i.e. "Is TLS 1.2 the default protocol" or "Can TLS 1.2 be used if explicitly specified etc.". cc: @karelz |
In the section If your app targets .NET Framework 4.7 or later versions
What does this mean:
So first 1.2, then 1.1 then finally 1.0 is tried? Or maximum TLS 1.0 and above versions 1.1 and 1.2 are not tried? |
Next question, from unittesting 4.7.0 code on a client machine (win10) it looks like WCF client code targeting 4.7.0 still uses ssl3, tls as default. You need to target 4.7.1 to be able to be able to use tls 1.2 when using the wcf generated client stub to access a TLS 1.2 only service.? Is this assumption correct or do we need to have a better look at our code why it keeps defaulting |
It means TLS 1.0 and lower. In other words, do not set the AppContext switch to @mconnew can you look at the second question? The doc is a bit confusing also to me - this section talks about both 4.7.1 and 4.7 - which one is it? |
I'm missing information about "If your app targets a .NET Framework version earlier than 4.7" and using WCF without certificate credentials. I wrote a very simple test application targeting .net framework 4.0, which just simple writes the default value of "ServicePointManager.SecurityProtocol". Tls, Tls11, Tls12 So in my case I don't see that I should rebuild all of my applications targeting the new framework. Actually this is a little confusing for me how the build target could affect the application runtime. Does the runtime check the build target version and modify its behaviour depends on it? Could you point to this in reference source? |
Yes. We have code in the .NET Framework runtime that checks the build target version (called the Target Framework Moniker, TFM). The code logic is complicated because in addition to checking that we also check a bunch of other registry keys, AppContext values etc. Some of the logic for that is here: |
would like to clarify if there is a possibility to set up different protocols in the client app.config to use for example:
using .NET Framework 4.5.2 Thanks. |
This is not possible. There are no settings at per-request granularity for that. It you need that level of control you will have to do it in code. |
Thanks for your fast answer. We got this exception before TLS 1.2 was disabled by default in registry(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2), but after this was set to 0 it became working.
|
@mconnew Can you help comment on this WCF stack trace? |
Sorry, I missed a couple of questions in this issue previously. |
Hello! |
I have a WCF client and server which are all developed in .Net Framework 4.8. |
Because you use |
@Shirley59 You might need to know the TLS handshake process |
Hi all, I have read through https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls document, and I can see recommendations that for TLS 1.2 .NET Framework 4.7 should be used and for TLS 1.3 .NET Framework 4.8 should be used. My question is if TLS 1.3 is possible with .NET Framework 4.7. My understanding is that .NET Framework 4.7+ will let the OS choose the TLS version. So if the OS is Windows 11 or Windows Server 2022 .NET Framework 4.7 should be able to use TLS 1.3? If this is correct, why is the recommendation that .NET Framework 4.8 be used if TLS 1.3 is needed? |
Hi @JameelKhan9 , |
Hi @chucklu, Thanks for the quick reply. Is there any documentation of how to get TLS 1.3 working for 4.7.x? |
@JameelKhan9 : Import OpenSSL. Or P/Invoke the native APIs on newer Windows versions. (There's a breaking ABI change between TLS 1.2 and TLS 1.3 on Windows so adding the enum value doesn't cut it.) You can opportunistically enable TLS 1.3 while compiling for .NET Framework 4.7 by probing for the enum value with reflection. It will work if present (which means .NET 4.8 is installed). |
Hi @JameelKhan9 ,
|
You cannot @JameelKhan9, @jhudsoncedaron is right. There is more than just the enum. to get TLS 1.3 callers of The only one way you can succeed IMHO while targeting 4.7 is to use actual 4.8 runtime on the new machines. 4.7 does not have the enum, but the |
Concerning the recommendation:
If yes, how is this accomplished when the underlying mechanism, schannels, does not seem to support it? If no, then dependencies should be made more clear in the recommendation. Also a path to add TLS v1.3 support without upgrading the OS should be mentioned (IE: switching the broker to openssl ). |
@upsampled You guessed correctly. Enabling TLS 1.3 won't actually work unless the OS supports it. The idea is something like Enable TLS 1.3 and 1.2 and hope for the best. In .net runtime (starting with 5 or 6), you're best off just never touching the SSL Versions property on anything because doing nothing inherits the OS settings, which is what you actually want. |
@jhudsoncedaron does the table below correctly summarize the compatibility matric for TLS v1.3?
|
@upsampled : Not at all. More like:
|
@jhudsoncedaron I just used .Net 6 to use a TLSv1.3 client on Windows 2016, this compatibility matrix is not correct |
@upsampled : Windows 2016 does not have working TLSv1.3. I tried it. The registry hack turns on a beta version that doesn't actually work because the protocol is not implemented correctly yet (works in 2022, don't know about 2019). Unless there's some service pack I don't know about that makes it work, it just won't work. Source https://learn.microsoft.com/en-us/answers/questions/958442/how-to-enable-tls-1-3-in-windows-server-2016 |
Supported version matrix was posted earlier: https://learn.microsoft.com/en-us/windows/win32/secauthn/protocols-in-tls-ssl--schannel-ssp- |
@wfurt the issue is that page is at best incomplete. I have gotten TLS 1.3 client working with .Net Framework 4.8 on a 2016 server (though not on 2012), which should be impossible according to those tables*. I feel like knowing the highest supported version of TLS given Runtime/OS/Compile Flags is definitely within the scope of best practice. It certainly should be in a page referenced by best practices. *Unless those tables just apply to Win32 Apps as it is a child page of the Win 32 App documentation. In which case we need a separate page for 64 bit targets. |
There is difference between "supported" and "make work" @upsampled. As @jhudsoncedaron mentioned there is some support for TLS 1.3 in earlier Windows version but that has different levels of completeness and correctness. As far as I know you would be on your own if you hit troubles with Tls 1.3 on Server 2016. So I would be hesitant to put it up as best practice. |
@wfurt I think documenting this is the first step to any discussion on the matter.
Is there anywhere I can read more about this? |
I managed to "make it work" (TLS 1.3 on something Windows from 2019) as well but it later broke by accident because support was incomplete and things stopped working (without me knowing) because it tried to use TLS 1.3 with unsupported ciphers (which are all fine in the supported versions). Cost me days to analyze. So I second @wfurt , just hold on to 1.2 or use a supported windows version. |
Is there any chance to force use net framework 4.8 app (hosted on win10) to use tls13 during wcf calls to third-party? I turned on tls13 support in windows, but each request throws "The request was aborted: Could not create SSL/TLS secure channel" |
According to the documentation, the Schannel provider doesn't support it. The latest commit is pretty clear:
|
@kapsiR it is not clear, as @krabobobr you can get likely get TLS 1.3 working with the following. I understand that 'support' and 'get working' are not the same. Same for 'TLS 1.3 Draft' and 'TLS 1.3' (though they are seemingly compatible). I think it is more accurate to replace |
@upsampled : That code sample is messed up. What you should do is check the Enum with reflection for the values you want. This is the equivalent dynamically detecting .NET Framework version and enabling support in your application when the host has it. |
@jhudsoncedaron agreed, I am mainly pointing to it to show TLS 1.3 connections are possible (though maybe not supported) when documentation suggest otherwise. |
@upsampled I don't agree here. While Microsoft had some support from Windows 10 1903 ("for testing purposes only, not production environment."), this information has been removed almost everywhere. We should not rely on any draft support, if there is an incomplete implementation that probably doesn't work in some cases. This causes to much pain for everyone involved. Even
|
If we were to follow the recommended best practice for specifying protocol versions by not specifying protocol versions and let the OS take care of things, would it be possible to have a method/property to invoke that would list the protocol versions that are currently supported? The recommendation is to use ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault but something like ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; is more discoverable when doing a code review. If I come back to my app which has been running quietly and uninterrupted on a server in some forgotten closet for the past 5 years, I wouldn't want to have go digging through registry keys and all manner of outdated and sometimes contradictory blog posts to figure out which protocols it's running. |
Use this issue to ask questions about the Transport Layer Security (TLS) best practices with the .NET Framework document.
The text was updated successfully, but these errors were encountered: