We have a WCF client and server which communicate over a WCF NetTcpBinding with Streamed Transfermode where the client sets up the WCF NetTcpBInding with these relevant settings:
TransferMode = TransferMode.Streamed
Security.Mode = SecurityMode.Transport
Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate
Security.Transport.SslProtocols = System.Security.Authentication.SslProtocols.None
According to https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls, SslProtocols.None ensures that WCF uses the operating system default setting when using the NetTcp transport.
All our Windows hosts are configured to only allow TLS 1.2. This has been configured using the Windows registry and setting all server and client keys to disabled for SSL 2.0, SSL 3.0n TLS 1.0 and TLS 1.1 and enabled only for TLS 1.2 at location: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols, as described at https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings.
Additionally, the app.config files of our WCF client and server contain this runtime entry (as documented on https://docs.microsoft.com/en-us/configmgr/core/plan-design/security/enable-tls-1-2):
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
</runtime>
</configuration>
When the WCF client is running on Windows 10 (build 1809), and the server on Windows Server 2019 LTSC, .NET version 4.7.2, WCF communication works fine.
When both the WCF client and server are running on Windows Server 2019 LTSC, .NET 4.7.2, communication fails with this exception:
Message: A call to SSPI failed, see inner exception.
Title:The file information could not be gathered.
Inner Exception 1: A call to SSPI failed, see inner exception.
Inner Exception 2: The client and server cannot communicate, because they do not possess a common algorithm
Server stack trace:
at System.ServiceModel.Channels.SslStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream stream)
at System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.StreamedFramingRequestChannel.SendPreamble(IConnection connection, TimeoutHelper& timeoutHelper, ClientFramingDecoder decoder, SecurityMessageProperty& remoteSecurity)
at System.ServiceModel.Channels.StreamedFramingRequestChannel.StreamedConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
at System.ServiceModel.Channels.StreamedFramingRequestChannel.StreamedFramingRequest.SendRequest(Message message, 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)
We were able to resolve the problem by explicitly setting Security.Transport.SslProtocols when setting up the client NetTcpBinding instead of letting the Operating System decide, as such:
Security.Transport.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 Or System.Security.Authentication.SslProtocols.Tls11 Or System.Security.Authentication.SslProtocols.Tls Or System.Security.Authentication.SslProtocols.Ssl3
We don't understand why this solution works, as we expect this fix to have the same effect as letting the operating system choose.
With only TLS 1.2 allowed on all hosts, how can communication fail when both client and server are running on Windows Server 2019 and not chen the client runs on Windows 10? There is nothing else than TLS 1.2 to default to. How can it be investigated which protocol Windows defaults to?