我正在寻找与 Web 服务断开连接的原因的建议。
在网络浏览器中,我得到
ERR_CONNECTION_CLOSED
或者在 Fiddler Classic 中:
与 myserver.mydomain.com(针对 #82)的 HTTPS 握手失败。 System.IO.IOException 身份验证失败,因为远程方已关闭传输流。
操作系统是 Windows Server 2019(我了解不支持 TLS 1.3) 我已在服务器上设置 TLS 1.2 注册表项:
Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2
对于 Client
和 Server
键:
Enabled = 1
DisabledByDefault = 0
它是一个 ASP.Net 8 Web API。 它由运行 Kestrel 的 Windows 服务托管(无 IIS)。
它使用非标准端口(8000)。防火墙规则允许通过该端口的流量。
我的证书的主题备用名称中有
DNS Name=mydomain.myserver.com
。
证书有效且未过期。
我附上此证书
options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.SslProtocols = SslProtocols.Tls12;
httpsOptions.ServerCertificate = cert;
});
该服务似乎认为运行良好。 日志说:
现在收听:https://[::]:8000
我本来期待看到
https://myserver.mydomain.com:8000
,但是哦,好吧。
如果我通过同一主机上的同一端口切换到 HTTP,则工作正常。
好吧,我认为这归结为服务帐户没有从证书中读取私钥的权限,我们使用一些神奇的 PowerShell 来修复此问题,它会查找证书文件并调整其访问控制列表:
# First put certificate into $certificate, 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```