Search code examples
linuxssl.net-6.0.net-8.0kestrel-http-server

ERR_SSL_PROTOCOL_ERROR generated using X509 certificate with Kestrel hosting in .NET 8 on Linux


I am currently working through upgrading a C#/.NET app from .NET 6.0 to .NET 8.0 on a Linux virtual machine (I'm working on a PC), and I am having some issues with getting HTTPS endpoints to work. I stumbled across this article while looking for solutions, but I'm not 100% sure that is actually the issue, and if it is I'm not sure how to fix it :). I am retrieving a X509Certificate2 crt/key pair from the local file system and using that to create a IHostBuilder object that uses HTTPS. Below is the current code I'm working with:

var certContents = File.ReadAllText(<local filepath>);
var certKeyContents = File.ReadAllText(<local key filepath>);
var cert = X509Certificate2.CreateFromPem(certContents, certKeyContents);

return Host.CreateDefaultBuilder(args)
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseKestrel(options =>
            {
                options.AddServerHeader = false;
                options.Listen(IPAddress.Any, port, ops =>
                {
                    ops.UseHttps(cert);
                }); 
            }
        })
        .UseStartup<Startup>();
    })
    .ConfigureLogging(logging => 
    {
    })
    .UseNLog();

The result of this is generally an error page that just shows "This site can’t provide a secure connection". I have primarily been using Google Chrome v122.0 and Postman v9.31 to test these calls. I have set breakpoints in code and it seems like I'm not even able to get to the backend with these errors since those breakpoints are never hit. Interestingly, I did find that I can get a little bit farther when I use FireFox (as in, it seems to be able to get access to the backend); it does not throw SSL errors, but will instead attempt to access our app's Keycloak instance (not locally hosted) to verify our SSO token and throws a IDX20803 error. Below is further exception code from that:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '<Keycloak URL>'.
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

I have also noticed some IDX20803 errors that more follow this pattern. This code works just fine in .NET 6, but I must be missing something in the updated .NET versions - any guidance is appreciated!

What I've already tried

  • In the options.Listen() callback, attempted to add the below code block.
    • Result: no change in error
opt.AllowAnyClientCertificate();
opt.ClientCertificateValidation = (certif, chain, policyErrors) => true;
opt.ClientCertificateMode = Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode.AllowCertificate;
opt.ServerCertificate = cert;
opt.SslProtocols = System.Security.Authentication.SslProtocols.Tls12
    | System.Security.Authentication.SslProtocols.Ssl3
    | System.Security.Authentication.SslProtocols.Tls
    | System.Security.Authentication.SslProtocols.None
    | System.Security.Authentication.SslProtocols.Tls11
    | System.Security.Authentication.SslProtocols.Tls13
    | System.Security.Authentication.SslProtocols.Default;
  • In the options.Listen() callback, tried removing the ops.UseHttps(cert) call

    • Result: was able to make API calls to an HTTP URL, but HTTPS remained unavailable
  • In the beginning of my Program.cs and Startup.cs files, attempted adding this line: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Tls13;

    • Result: no change in error
  • In the Configure method of the Startup.cs file, add app.UseHttpsRedirection();

    • Result: no change in error

Solution

  • Might be related to this: https://github.com/dotnet/aspnetcore/issues/54366

    See if this helps:

    options =>
    {
        options.Listen(System.Net.IPAddress.Loopback, your-port, httpnOptions =>
        {
            httpOptions.UseHttps(new HttpsConnectionAdapterOptions { SslProtocols = SslProtocols.Tls12 });
        }
    }))
    

    if it helps, there's an issue with TLS 1.3 . Looks like they might put a patch out in May.

    https://github.com/dotnet/runtime/pull/99670