Skip to content
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

Open
Rick-Anderson opened this issue Mar 15, 2018 · 153 comments
Open
Labels
discussion Indicates issues that are being discussed doc-enhancement Improve the current content [org][type][category] help wanted Good for community contributors to help [up-for-grabs] mvp-docs-sprint For tracking purposes (used for the MVP summit docs sprint hack). Pri3
Milestone

Comments

@Rick-Anderson
Copy link
Contributor

Use this issue to ask questions about the Transport Layer Security (TLS) best practices with the .NET Framework document.

@RamanBut-Husaim
Copy link

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

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.

@mconnew
Copy link
Member

mconnew commented Apr 13, 2018

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.

@RamanBut-Husaim
Copy link

@mconnew Understood. Thanks a lot for the quick reply!

@bjorncoltof
Copy link
Contributor

bjorncoltof commented May 25, 2018

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?

@karelz
Copy link
Member

karelz commented May 25, 2018

@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

@davidsh
Copy link
Contributor

davidsh commented May 25, 2018

Maybe the OS has something like that?

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:

Registry path: HKLM SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols

To disable the TLS 1.0 protocol, create an Enabled entry in the appropriate subkey. This entry does not exist in the registry by default. After you have created the entry, change the DWORD value to 0. To enable the protocol, change the DWORD value to 1.

Subkey | Description
Client | Controls the use of TLS 1.0 on the TLS client.
Server | Controls the use of TLS 1.0 on the TLS server.
DisabledByDefault | Flag to disable TLS 1.0 by default.

@blowdart
Copy link
Contributor

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.

@coolzsunil
Copy link

coolzsunil commented Jun 29, 2018

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.
For all other cases, where the machine has 4.5.2 to 4.6.2, but with apps targeting .NET 4.0 - 4.6.2, the presence of SchUseStrongCrypto is the only entry, we require.
Our understanding is also mentioned here - https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/manage-ssl-protocols-in-ad-fs#enabling-strong-authentication-for-net-applications

Can you please confirm the correct one?

Regards,
Sunil Bhaskar

@davidsh
Copy link
Contributor

davidsh commented Jul 4, 2018

Can you please confirm the correct one?

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 ServicePointManager.SecurityProtocol property to use a default of SecurityProtocolType.SystemDefault. That means that the operating system will select the set of TLS protocols for the default set. And this default set will change over time depending on the OS version. For example, as the OS version moves forward in the future, TLS 1.3 will be added and other protocols will be removed.

See the matrix of OS versions TLS protocols here:
https://support.microsoft.com/en-us/help/3154518/support-for-tls-system-default-versions-included-in-the-net-framework

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.

@coolzsunil
Copy link

@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.
This makes it difficult to support multiple operating system using a single config file.

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.

@davidsh
Copy link
Contributor

davidsh commented Jul 5, 2018

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.

@marcroussy
Copy link

marcroussy commented Aug 14, 2018

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?

@davidsh
Copy link
Contributor

davidsh commented Aug 14, 2018

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.

@mjkkirschner
Copy link

mjkkirschner commented Oct 6, 2018

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?

@ngzhiying
Copy link

@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?

@davidsh
Copy link
Contributor

davidsh commented Oct 15, 2018

Is there a way to check what protocols are currently supported by the user's machine before setting. Does this functionality exist in .net?

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

@henkmeulekamp
Copy link

In the section If your app targets .NET Framework 4.7 or later versions

For WCF Message Security with certificate credentials
.NET Framework 4.7 and later versions by default uses the protocol specified in the SecurityProtocol property. When the AppContextSwitch Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols is set to true, WCF chooses the best protocol, up to TLS 1.0.

What does this mean:

WCF chooses the best protocol, up to TLS 1.0.

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?

@henkmeulekamp
Copy link

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 System.Net.ServicePointManager.SecurityProtocol using ssl3, tls?

@karelz
Copy link
Member

karelz commented Oct 19, 2018

@henkmeulekamp

What does this mean:

WCF chooses the best protocol, up to TLS 1.0.

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?

It means TLS 1.0 and lower. In other words, do not set the AppContext switch to true unless you have really good reasons and you know what you're doing - see its description.

@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?
https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#for-wcf-tcp-transport-using-transport-security-with-certificate-credentials

@gaborlaczo
Copy link

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".
In case of a computer runs .net framework 4.7 and the registry also set for enabling all TLS versions and SSL was disabled the result was:

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?

@davidsh
Copy link
Contributor

davidsh commented Dec 10, 2018

Does the runtime check the build target version and modify its behaviour depends on it?

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:
https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/ServicePointManager.cs

@apiliuhin
Copy link

Hi @Rick-Anderson @mairaw

would like to clarify if there is a possibility to set up different protocols in the client app.config to use for example:

  1. url 1 set to use TLS 1.2
  2. url 2 set to Ssl3 (Ssl3 only)

using .NET Framework 4.5.2

Thanks.

@davidsh
Copy link
Contributor

davidsh commented Jan 25, 2019

would like to clarify if there is a possibility to set up different protocols in the client app.config to use for example:
url 1 set to use TLS 1.2
url 2 set to Ssl3 (Ssl3 only)
using .NET Framework 4.5.2

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.

@gaborlaczo
Copy link

gaborlaczo commented Feb 26, 2019

Some of the logic for that is here: https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/ServicePointManager.cs

Thanks for your fast answer.
Actually we did a lot view on that code before I askeed my question earlier and I still don't find where and what role here the TFM does.

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.

System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority '...'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.


   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---


Server stack trace:

   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)

   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)

   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)

   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)

   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)

   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

 

Exception rethrown at [0]:

   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)

   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

@davidsh
Copy link
Contributor

davidsh commented Feb 26, 2019

Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)

@mconnew Can you help comment on this WCF stack trace?

@mconnew
Copy link
Member

mconnew commented Feb 27, 2019

Sorry, I missed a couple of questions in this issue previously.
@henkmeulekamp, in your question here, the section you are quoting is about using certificate authentication when using message security. In that scenario, we just use whatever value is set in ServicePointManager.SecurityProtocols as we didn't have a public class that we could expose an explicit property on. This isn't not related to the TLS protocol used for HTTPS but is a different usage of the TLS protocol used by message security.
In response to the question from @karelz here. The section linked is talking about the WCF TCP transport (net.tcp) using certificate authentication (as opposed to windows authentication). We have different behavior on 4.7 and 4.7.1. On 4.7 our behavior is not dependent on which version you target and we default to TLS1.2, TLS1.1 and TLS1.0 all being allowed. Starting from 4.7.1, we made a change based on which version of the framework you are targeting. If you target 4.7.1 or above, the default is now SslProtocols.None which means you will get the OS default. If you target 4.7 or earlier, but are running on 4.7.1 or later, you will get the 4.7 behavior of the default being TLS1.2, TLS1.1 and TLS1.0.
For HTTPS, we don't do anything special and just let HttpWebRequest do whatever has been configured.
@davidsh, that call stack is where we process any exception thrown from calling HttpWebRequest.GetResponse(). The specific WCF exception message is used when WebException.Status has a value of WebExceptionStatus.SecureChannelFailure. If disabling TLS1.2 made things work, I suspect really old certificates are being used. TLS1.2 does NOT work if your certificate has been signed using md5. In this scenario, when both ends are configured to use TLS1.2 if available, they negotiate TLS1.2 but then can't complete the handshake because the certificate isn't usable. Disabling TLS1.2 on one end causes TLS1.1 to be negotiated instead and now the certificate can be used. That's my best guess to what's happening.

@yahiac-aug
Copy link

yahiac-aug commented Mar 11, 2019

Hello!
Can someone help me? I made this: https://support.microsoft.com/en-us/help/3206898/enabling-iis-manager-and-web-deploy-after-disabling-ssl3-and-tls-1-0
but i still can't use iis manager after disabling tls 1.0 :( (on windows 2008 r2 sp1 core)
note: they talking about this patch: windows6.1-kb3154518-x64 but if i try to install it, i have the message: "the update is not applicable to your computer"

@wfurt
Copy link
Member

wfurt commented May 29, 2022

What is your server @sahin52? The trouble with SPM is that it is global property. Sometimes different components can write to it and they can override each other. You can also try the other direction e.g. connect outside and use Wireshark to look at the handshake. When you enforce Tls12 you should see only that in the outgoing handshake.

@Shirley59
Copy link

Shirley59 commented Jun 14, 2022

I have a WCF client and server which are all developed in .Net Framework 4.8.
Client code is :
NetTcpBinding Bindings = new NetTcpBinding;
Bindings.Security.Mode = SecurityMode.Transport;
Bindings.Security.Transport.SslProtocols = SslProtocols.None;
Bindings.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
Server side is :
NetTcpBinding Bindings = new NetTcpBinding;
Bindings.Security.Mode = SecurityMode.Transport;
Bindings.Security.Transport.SslProtocols = SslProtocols.None;
Bindings.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
And my question is if the Client PC1 only enables TLS 1.2 and the Server PC2 only enables TLS 1.1.
How does the OS select the TLS version when communicating between these two PCs ? Can the transmitted messages be parsed correctly in this case?

@wfurt
Copy link
Member

wfurt commented Jun 14, 2022

Because you use SslProtocols.None then the decision is left to OS. The negotiation is part of TLS handshake - where TLS Client Hello contains supported algorithms and versions and server picks one or fails if there is no overlap.

@chucklu
Copy link

chucklu commented Jun 14, 2022

@Shirley59 You might need to know the TLS handshake process
https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.3
You will get a protocol mismatch error in socket packet when you catch the packet via Wireshark for your case

@Shirley59
Copy link

@chucklu @wfurt Thanks I see.

@JameelKhan9
Copy link

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?

@chucklu
Copy link

chucklu commented Sep 1, 2022

Hi @JameelKhan9 ,
.net framework 4.7.2 does not support tls 1.3, https://docs.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype?view=netframework-4.7.2#system-net-securityprotocoltype-systemdefault. The SecurityProtocolType Enum does not have the value of tls 1.3 in .net framework 4.7.2.
And tls 1.3 was added since .net framework 4.7.8 https://docs.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype?view=netframework-4.8#system-net-securityprotocoltype-systemdefault.

@JameelKhan9
Copy link

Hi @chucklu,

Thanks for the quick reply. Is there any documentation of how to get TLS 1.3 working for 4.7.x?

@jhudsoncedaron
Copy link

jhudsoncedaron commented Sep 1, 2022

@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).

@chucklu
Copy link

chucklu commented Sep 1, 2022

Hi @JameelKhan9 ,
Not sure, you might try this Using TLS 1.3 from .NET 4.0 Application.
I have not tried the above solution for tls 1.3, and from my experience we can make tls 1.2 work with .net 4.0 as following https://stackoverflow.com/a/28333370/13338936.

However, an application targeting .NET 4.0 can still support up to TLS 1.2 if .NET 4.5 is installed in the same environment. .NET 4.5 installs on top of .NET 4.0, replacing System.dll.

@wfurt
Copy link
Member

wfurt commented Sep 1, 2022

You cannot @JameelKhan9, @jhudsoncedaron is right. There is more than just the enum. to get TLS 1.3 callers of schannel need to call different API. If the "normal"/"legacy" API is used schannel will negotiate only up to 1.2.

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 None should still work.

@IEvangelist IEvangelist added the help wanted Good for community contributors to help [up-for-grabs] label Oct 27, 2022
@IEvangelist IEvangelist added the mvp-docs-sprint For tracking purposes (used for the MVP summit docs sprint hack). label Apr 4, 2023
@upsampled
Copy link

upsampled commented May 12, 2023

Concerning the recommendation: For TLS 1.3, target .NET Framework 4.8 or later.:

  • Does this apply to all Windows version which .NET Framework 4.8 can run?

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

@jhudsoncedaron
Copy link

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

@upsampled
Copy link

@jhudsoncedaron does the table below correctly summarize the compatibility matric for TLS v1.3?

dotnet version OS Version Note
4.0-4.7 >=Windows Server 2022 or >=Windows 10 Requires following explicit actions to enable
4.8+ >=Windows Server 2022 or >=Windows 10 Will be enabled by default via OS
5-6 Not OS dependent

@jhudsoncedaron
Copy link

jhudsoncedaron commented May 12, 2023

@upsampled : Not at all. More like:

dotnet version OS Version Note
4.0-4.7 >=Windows Server 2022 or >=Windows 10 Not available; explicit actions will enable if target machine has 4.8 (they're supposed to always have 4.8 but I've seen weird things)
4.8+ >=Windows Server 2022 or >=Windows 10 Will be enabled by default via OS in SslStream; explicit actions required to enable in higher level components
5+ >=Windows Server 2022 or >=Windows 10  Will be enabled by default via OS

@upsampled
Copy link

@jhudsoncedaron I just used .Net 6 to use a TLSv1.3 client on Windows 2016, this compatibility matrix is not correct

@jhudsoncedaron
Copy link

@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

@wfurt
Copy link
Member

wfurt commented May 12, 2023

Supported version matrix was posted earlier: https://learn.microsoft.com/en-us/windows/win32/secauthn/protocols-in-tls-ssl--schannel-ssp-
I don't think we should try to duplicate it here.
And everything is OS dependent. If someone fiddles with registry the behavior will change.

@upsampled
Copy link

upsampled commented May 12, 2023

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

@wfurt
Copy link
Member

wfurt commented May 12, 2023

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.

@upsampled
Copy link

upsampled commented May 12, 2023

@wfurt I think documenting this is the first step to any discussion on the matter.

there is some support for TLS 1.3 in earlier Windows version

Is there anywhere I can read more about this?

@simonthum
Copy link

simonthum commented May 19, 2023

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.

@krabobobr
Copy link

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"

@kapsiR
Copy link
Contributor

kapsiR commented Sep 29, 2023

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:

TLS 1.3 is not supported before Windows 11. Updating to correctly reflect this for Windows 10 20H1 and 21H1, and adding 21H2.

@upsampled
Copy link

@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 Not Supported with Draft Support for dotnet/windows combinations that are in this grey area.

@jhudsoncedaron
Copy link

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

@upsampled
Copy link

@jhudsoncedaron agreed, I am mainly pointing to it to show TLS 1.3 connections are possible (though maybe not supported) when documentation suggest otherwise.

@kapsiR
Copy link
Contributor

kapsiR commented Oct 2, 2023

@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 Not Supported with Draft Support for dotnet/windows combinations that are in this grey area.

@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 curl has a check for that because of the broken implementations in previous versions:

Windows Server 2022 and newer (including Windows 11) support TLS 1.3
built-in. Previous builds of Windows 10 had broken TLS 1.3
implementations that could be enabled via registry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Indicates issues that are being discussed doc-enhancement Improve the current content [org][type][category] help wanted Good for community contributors to help [up-for-grabs] mvp-docs-sprint For tracking purposes (used for the MVP summit docs sprint hack). Pri3
Projects
None yet
Development

No branches or pull requests