asp.net-web-apihttpstls1.2kestrel-http-server

HTTPS disconnected - Kestrel


I'm looking for suggestions why I get disconnected from my Web Service.

In a web browser, I get

ERR_CONNECTION_CLOSED

Or in Fiddler Classic:

HTTPS handshake to myserver.mydomain.com (for #82) failed. System.IO.IOException Authentication failed because the remote party has closed the transport stream.

The Operating System is Windows Server 2019 (I understand TLS 1.3 is not supported) I have set the TLS 1.2 registry keys on the server: Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2 for both the for both Client and Server keys:

It is an ASP.Net 8 Web API. It is hosted by a Windows Service running Kestrel (no IIS).

It uses a non-standard port (8000). A firewall rule permits traffic over that port.

My certficiate has DNS Name=mydomain.myserver.com in its Subject Alternative Name. The certificate is valid and has not expired. I attach this certificate with

options.ConfigureHttpsDefaults(httpsOptions =>
  {
    httpsOptions.SslProtocols = SslProtocols.Tls12;
    httpsOptions.ServerCertificate = cert;
  });

The service seems to think it is working fine. The log says:

Now listening on: https://[::]:8000

I was expecting to see https://myserver.mydomain.com:8000, but oh well.

If I switch to HTTP over the same port on the same host, it works fine.


Solution

  • Ok, I think this came down to the service account not having permission to read the private key out of the certificate, which we fix with some magic PowerShell, which finds the certificate file and adjusts its Access Control List:

    # First put certificate into $certificate, and the account into $userName then...
    
    $rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
    
    # Find the certificate file.  
    # It should be under .\Keys or .\RSA\MachineKeys within ($env:ALLUSERSPROFILE + "\Microsoft\Crypto")        
    $machineKeysRoot = $env:ALLUSERSPROFILE + "\Microsoft\Crypto"
    $fileName = $rsaCert.key.UniqueName
    $fileRelativePath = (Get-ChildItem -Path $machineKeysRoot -Name $fileName -Recurse) # Get-ChildItem returns a string if using the -Name parameter
    if (-not $fileRelativePath) {
        throw "Could not find $fileName under $machineKeysRoot"
    }       
    $path = [System.IO.Path]::Combine($machineKeysRoot, $fileRelativePath)
    
    # Get, modify, and store ACL.
    $permissions = Get-Acl -Path $path
    $access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$userName", 'Read', 'None', 'None', 'Allow')
    $permissions.AddAccessRule($access_rule)
    Set-Acl -Path $path -AclObject $permissions```