HTTPS 不适用于在具有自定义域的 Service Fabric 上运行的 Kestrel 3.2.187/ASPNET Core 2.1.5
Posted
技术标签:
【中文标题】HTTPS 不适用于在具有自定义域的 Service Fabric 上运行的 Kestrel 3.2.187/ASPNET Core 2.1.5【英文标题】:HTTPS not working with Kestrel 3.2.187/ASPNET Core 2.1.5 running on the Service Fabric with a custom domain 【发布时间】:2019-03-27 21:24:42 【问题描述】:我们正在远程开发集群上运行 Service Fabric 应用程序。它由多个有状态和无状态服务组成,并由多个在 Kestrel 上运行的前端 API 构成。
到目前为止,由于没有用于生产,Kestrel 被配置为使用自签名证书,该证书也用于反向代理和集群本身,并且服务直接在 Azure 提供的默认域上运行, <app>.<region>.cloudapp.azure.com
.
我们现在正处于开发阶段,自签名证书错误成为问题,第三方回调拒绝连接,因此现在被视为开始使用适当的域和证书的时候了。
到目前为止,我做了以下工作:
为devcluster.somexampledomain.com
添加了一条 A 记录 -> 我们的服务公共 IP。
为*.someexampledomain.com
创建了通配符 Azure 应用程序证书。
已将证书导入 Azure Key Vault。
将证书绑定到集群的Vault Secrets,拉取证书到Cert:/LocalMachine/My/
修改了应用程序配置以在初始化 Kestrel 时使用此证书,并验证在初始化时已找到它。
尝试使用和不使用UseHsts()
和UseHttpsRedirection()
Kestrel 在选项对象上配置了Listen(IPAddress.IPv6Any, endpoint.Port, ...)
和UseHttps(X509Certificate2)
。
UseUrls(string)
与默认 Url 一起使用,即 https://+:<port>
,但尝试手动添加 https://*:<port>
甚至是实际主机名本身。
无论我如何尝试,都无法与服务器建立 HTTPS 连接。尝试仍然使用旧证书的其他登台服务器的端点,它按预期工作。
使用openssl s_client -connect devcluster.someexampledomain.com:<port> -prexit
,我得到:
---
no peer certificate available
---
No client certificate CA names sent
---
ETW 上没有记录任何错误或异常,一切似乎都井然有序。我怀疑这可能与证书的 CN 有关,但我已经没有办法尝试找出发生了什么以及如何修复它。
一直在尝试使用 Fiddler 对此进行研究,但我并没有从中得到太多,会话以 fiddler.network.https> HTTPS handshake to <myhost> (for #191) failed. System.IO.IOException Authentication failed because the remote party has closed the transport stream.
结束
有人知道如何在 Kestrel 端添加一些日志记录吗?我不认为在运行我的集群的 Azure VM 上安装 Fiddler 是一个可行的解决方案。
【问题讨论】:
【参考方案1】:深入研究 Kestrel 源代码后,我发现它记录在 "Microsoft-AspNetCore-Server-Kestrel"
和 "Microsoft-Extensions-Logging"
下,因此添加了这些我发现发生了什么的传输。
连接因以下异常而终止:
System.ComponentModel.Win32Exception (0x8009030D): The credentials supplied to the package were not recognized
at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED scc)
at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED secureCredential)
at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)
at System.Net.Security.SecureChannel.AcquireServerCredentials(Byte[]& thumbPrint, Byte[] clientHello)
at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ApplyConnectionAdaptersAsync()
这使它成为Certificate problem with a new machine - credentials supplied to package not recognized的体现。
我花了一些时间试图弄清楚解决这个问题的最佳方法是什么,Service Fabric documentation 有一个脚本可以修改权限,但这听起来不对。
事实证明,这可以直接在 ApplicationManifest 中完成,如下所示:
<Principals>
<Users>
<User Name="NETWORK SERVICE" AccountType="NetworkService" />
</Users>
</Principals>
<Policies>
<SecurityAccessPolicies>
<SecurityAccessPolicy ResourceRef="HttpsCert2" PrincipalRef="NETWORK SERVICE" ResourceType="Certificate" />
</SecurityAccessPolicies>
</Policies>
<Certificates>
<SecretsCertificate X509FindValue="[HttpsCertThumbprint]" Name="HttpsCert" />
</Certificates>
对于SecurityAccessPolicy
,要找到ResourceRef
,它必须是SecretsCertificate
,而不是EndpointCertificate
。由于EndpointBindingPolicy
需要EndpointCertificate
,我只添加了SecretsCertificate
和EndpointCertificate
,但名称不同。他们都指的是同一个证书,所以它起作用了。不得不将它们加倍感觉不是特别干净,但这是我目前的解决方案。
【讨论】:
以上是关于HTTPS 不适用于在具有自定义域的 Service Fabric 上运行的 Kestrel 3.2.187/ASPNET Core 2.1.5的主要内容,如果未能解决你的问题,请参考以下文章