hass-agent / HASS.Agent

Unofficial development project for the HASS.Agent platform.
https://hass-agent.io
MIT License
295 stars 7 forks source link

PSA: Windows 10 machines running HASS.Agent will not connect to HA instances behind a reverse proxy requiring TLS 1.3 #120

Open CaptainStealthy opened 1 month ago

CaptainStealthy commented 1 month ago

Describe the bug I am posting this to avoid a DenverCoder9 situation, in case someone ever has this issue, and attempts to find out why it's happening in a future Google or GitHub search...

This should be a discussion thread, but Discussions are not enabled on this repo, so it's an issue instead, lol.

This is actually a "bug" (air quotes...) in the HADotNet library - and it's not even a bug, more so just a quirk of Windows 10. There might be a way for @qJake to address it in his code, but if he can't, then there is a workaround.

When running HASS.Agent on Windows 10 for the first time, if you try to connect to a Home Assistant install that is behind a reverse proxy (Traefik, in my case) that enforces TLS 1.3, you'll receive a generic connection error. I didn't get this error on my Windows 11 laptop, because (as I found out) Windows 11 has TLS 1.3 enabled by default, so that sent me down a rabbit hole.

After delving into the HASS.Agent logs (thank god for those...), and some Google searches, I found this issue by @VivantSenior in the HADotNet repo, and I also found out that for some mind numbing reason, Windows 10 doesn't actually support TLS 1.3?! šŸ¤Æ (at least not out of the box...)

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? šŸ¤·ā€ā™‚ļø

Long story short, I believe it's possible to set TLS 1.3 as the default protocol in the HADotNet library, which I outlined in this comment in the aforementioned issue thread. But that's something @qJake has to do - or if someone wants to submit a PR to his repo. šŸ˜‰

TL;DR - Enough talk! What's the workaround for those of us on Windows 10 that aren't programmers?!

As long as you're running Windows 10 21H2 or later, the registry workaround in this link should help - 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:

After that, reboot the system, and it should work fine. šŸ˜

To Reproduce Steps to reproduce the behavior:

  1. Install and run HASS.Agent on a Windows 10 machine
  2. Connect to an HA instance behind a proxy that requires TLS 1.3 on client connections
  3. Receive error saying could not connect, check URI and connection settings, etc.

Expected behavior Self-explanatory...

Misc info (please complete the following information):

Please check what's applicable (multiple answers possible):

Additional context N/A - although I did notice that HADotNet is referenced as a DLL file in the repo itself, rather than via the NuGet package - any reason for that? šŸ¤”

Logs

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: Authentication failed because the remote party sent a TLS alert: 'ProtocolVersion'.
 ---> System.ComponentModel.Win32Exception (0x80090326): The message received was unexpected or badly formatted.
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at HADotNet.Core.BaseClient.Get[T](String path)
   at HADotNet.Core.Clients.ConfigClient.GetConfiguration()
   at HASS.Agent.HomeAssistant.HassApiManager.CheckHassConfigAsync(String uri, String apiKey, Boolean automaticClientCertificate, Boolean allowUntrustedCertificates, String clientCertificate) in D:\a\HASS.Agent\HASS.Agent\src\HASS.Agent\HASS.Agent\HomeAssistant\HassApiManager.cs:line 331
amadeo-alex commented 1 month ago

This should be framed and put as an example of perfect ticket :D Thank you for all the info!

This should be a discussion thread, but Discussions are not enabled on this repo, so it's an issue instead, lol.

I take this on me, it will be a good idea to enable them.

although I did notice that HADotNet is referenced as a DLL file in the repo itself, rather than via the NuGet package - any reason for that?

The original HADotNet repository wasn't updated in some time and the published nuget even in longer - original HASS.Agent creator - Sam - opted to build the dll and include in the project. I assume that it was to have some of the bug fixes and features that weren't included in the published nuget. I don't really like that so I've forked the HADotNet, published the nuget and it's used as a dependency for HASS.Agent 2.1.0-betaX versions and up - https://github.com/amadeo-alex/HADotNet

I think I even saw one of the other issues that you've created and did a bit of research on the topic but not enough to implement anything yet. I wonder if it's possible to force TLS1.3 on the HADotNet side even if the OS registry might have it disabled.

CaptainStealthy commented 1 month ago

Hahah, no problem. I was glad to be able to solve a .NET problem again! šŸ˜‰

And makes sense re: why you forked the library. In that case, you should be able to add TLS 1.3 to your custom HTTP client handler that you've already added. I posted a snippet in the other thread I mentioned.

https://github.com/hass-agent/HASS.Agent/blob/main/src/HASS.Agent/HASS.Agent/HomeAssistant/HassApiManager.cs#L143

handler.SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls

Like I said, I don't know if you'd still need the OS registry key or not, but it's worth a try.