datalust / seq-forwarder

Local collection and reliable forwarding of log data to Seq
Apache License 2.0
57 stars 15 forks source link

TLS 1.2 Support #46

Closed mason-mcglothlin closed 4 years ago

mason-mcglothlin commented 4 years ago

The forwarder is built with .NET Framework 4.5.2. This does not have TLS 1.2 enabled out of the box. In systems where anything less than TLS 1.2 is not allowed, this makes it so that the forwarder can't communicate with Seq. An error will be in the forwarder logs like this one:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.ComponentModel.Win32Exception: The client and server cannot communicate, because they do not possess a common algorithm
   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)
   at System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)
   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
   at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
   at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback asyncCallback, Object asyncState)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
   at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Seq.Forwarder.Shipper.HttpLogShipper.<OnTickAsync>d__20.MoveNext()

You can add TLS 1.2 support by running this line of code:

ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;

before any HTTP calls the forward makes to Seq. Might be best to put it very early in the pipeline, such as OnStart for the Windows service

I'm no security expert, but it looks like TLS 1.1 itself isn't insecure, so I don't think you want to disable that, though you may consider disabling TLS 1.0.

Another possible option would be to update the forward to use a newer version of .NET Framework. .NET 4.7 and later will automatically negotiate the highest level of TLS support, including TLS 1.2. Of course, that means anywhere this app is installed it will need a newer version of the framework.

Related Stack Overflow discussion Microsoft Guidance on TLS

nblumhardt commented 4 years ago

Thanks for the PR. A pre-release build is at:

https://ci.appveyor.com/project/datalust/seq-forwarder/build/artifacts

If this works successfully for you, we'll send a new master build through the pipeline.

mason-mcglothlin commented 4 years ago

@nblumhardt Thanks Nick for the quick turnaround! Yes, the CI build is now negotiating TLS 1.2 correctly for us.