HADotNet icon indicating copy to clipboard operation
HADotNet copied to clipboard

TLS 1.3 - Authentication failed because the remote party sent a TLS alert: 'ProtocolVersion'.

Open VivantSenior opened this issue 2 years ago • 2 comments

Environment

  • Home Assistant Version: 2023.1.6
  • HADotNet Library Version: compiled from the source (06cc98c)
  • Visual Studio Version: 17.4.4
  • API call or endpoint that is failing: authentication

Describe the Problem

My HA instance forces to use TLS 1.3 and I'm trying to use HASS.Agent which uses this library but during initial connection I got an error: The SSL connection could not be established, see inner exception.

Code Sample

ClientFactory.Initialize("https://my-home-assistant-url/", "AbCdEf0123456789...");
var configClient = ClientFactory.GetClient<ConfigClient>();
var config = await configClient.GetConfiguration(); //error

Exception logs:

System.Net.Http.HttpRequestException
  HResult=0x80131501
  Message=The SSL connection could not be established, see inner exception.
  Source=System.Net.Http
  Stack tracek:
   w System.Net.Http.ConnectHelper.<EstablishSslConnectionAsync>d__2.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.HttpConnectionPool.<ConnectAsync>d__98.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.HttpConnectionPool.<CreateHttp11ConnectionAsync>d__100.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.HttpConnectionPool.<AddHttp11ConnectionAsync>d__74.MoveNext()
   w System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.<WaitWithCancellationAsync>d__1.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.<WaitForConnectionAsync>d__5.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__84.MoveNext()
   w System.Threading.Tasks.ValueTask`1.get_Result()
   w System.Net.Http.RedirectHandler.<SendAsync>d__4.MoveNext()
   w System.Net.Http.HttpClient.<<SendAsync>g__Core|83_0>d.MoveNext()
   w HADotNet.Core.BaseClient.<Get>d__6`1.MoveNext() w C:\Users\user\Desktop\HADotNet-master\HADotNet.Core\BaseClient.cs:wiersz 38
   w HADotNet.Core.Clients.ConfigClient.<GetConfiguration>d__1.MoveNext() w C:\Users\user\Desktop\HADotNet-master\HADotNet.Core\Clients\ConfigClient.cs:wiersz 22
   w Program.<<Main>$>d__0.MoveNext() w C:\Users\user\Desktop\HADotNet-master\ConsoleApp1\Program.cs:wiersz 10

Inner Exception 1:
AuthenticationException: Authentication failed because the remote party sent a TLS alert: 'ProtocolVersion'.

Inner Exception 2:
Win32Exception: The message received was unexpected or badly formatted.

VivantSenior avatar Jan 22 '23 19:01 VivantSenior

I'm sorry, this project does not currently support TLS 1.3. Support could be added, but I do not have a timeframe on when that would be or how much effort it would take.

qJake avatar Mar 09 '23 23:03 qJake

.NET 6 (which HASS.Agent runs on), as well as .NET Standard 2.0 (which this library is built on) should both support TLS 1.3 out of the box, as far as I know.

I was having the same issue as @VivantSenior, as my Traefik reverse proxy also forces TLS 1.3 - but the authentication worked just fine on my Windows 11 laptop, while it failed with the above error on my desktop PC, running Windows 10.

That sent me down a rabbit hole...and it turns out that Windows 10 apparently "doesn't support" TLS 1.3, according to Microsoft - even the latest version, 22H2.

That was mind boggling to me, but anyway...it seems that there is a registry workaround to enable TLS 1.3 on Windows 10 - or at least, it worked on my PC, which is running 22H2. This is purely a guess, but maybe the inner dependencies needed for the TLS 1.3 client are present in the later versions of Windows 10, since 21H2 was the first build of Windows 11? 🤷‍♂️

Anyway, this link helped me out a lot - basically, I just created a registry key called TLS 1.3\Client under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols, and then added two DWORD values:

  • DisabledByDefault: Value of 0
  • Enabled: Value of 1

After that, reboot the system, and it should work fine. :)

@qJake You might be able to set TLS 1.3 as the default security protocol in your ClientFactory class, but it's been a while since I've done .NET professionally, so I don't know if you'd still need the registry key on a Windows 10 system. I vaguely recall having to do something like this in my last .NET job, but it was years ago, heh.

Here's a quick snippet (two methods of setting it) I whipped up - I don't have time to add it myself, test it, and create a PR, but this should help you. ;)

// usings
using System.Net;
using System.Net.Http;
using System.Security.Authentication;

// EXAMPLE 1 - Set SecurityProtocol globally
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

// EXAMPLE 2 - Add an HttpClientHandler to your HttpClient to set non-globally
var handler = new HttpClientHandler()
{
    SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};

var client = new HttpClient(handler);

CaptainStealthy avatar Jul 12 '24 17:07 CaptainStealthy