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
我们正在 运行 在我们的远程开发集群上安装一个 Service Fabric 应用程序。它由几个有状态和无状态服务组成,并以几个 front-end APIs 运行ning on Kestrel 为前端。
到目前为止,由于未用于生产,Kestrel 配置为使用 self-signed 证书,该证书也用于反向代理和集群本身,服务为 运行直接在 Azure 提供的默认域上,<app>.<region>.cloudapp.azure.com
.
我们现在正处于 self-signed 证书错误成为问题的发展阶段,第三方回调拒绝连接,因此现在是时候开始使用正确的域和证书了为此。
到目前为止,我做了以下事情:
- 为
devcluster.somexampledomain.com
添加了一条 A 记录 -> 我们的 public 服务 IP。
- 为
*.someexampledomain.com
创建了通配符 Azure 应用程序证书。
- 已将证书导入 Azure Key Vault。
- 将证书绑定到集群的 Vault Secrets,将证书拉到
Cert:/LocalMachine/My/
- 修改了应用程序配置以在初始化 Kestrel 时使用此证书,并验证在初始化时可以找到它。
- 尝试过使用和不使用
UseHsts()
和 UseHttpsRedirection()
- Kestrel 在选项 object.
上配置了 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 对此进行研究,但我并没有从中得到多少,session 仅以 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 虚拟机上安装 Fiddler 运行我的集群是一个可行的解决方案。
深入研究 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
,但名称不同。他们都指的是同一个证书,所以它有效。不得不将它们加倍感觉不是特别干净,但这是我现在的解决方案。
我们正在 运行 在我们的远程开发集群上安装一个 Service Fabric 应用程序。它由几个有状态和无状态服务组成,并以几个 front-end APIs 运行ning on Kestrel 为前端。
到目前为止,由于未用于生产,Kestrel 配置为使用 self-signed 证书,该证书也用于反向代理和集群本身,服务为 运行直接在 Azure 提供的默认域上,<app>.<region>.cloudapp.azure.com
.
我们现在正处于 self-signed 证书错误成为问题的发展阶段,第三方回调拒绝连接,因此现在是时候开始使用正确的域和证书了为此。
到目前为止,我做了以下事情:
- 为
devcluster.somexampledomain.com
添加了一条 A 记录 -> 我们的 public 服务 IP。 - 为
*.someexampledomain.com
创建了通配符 Azure 应用程序证书。 - 已将证书导入 Azure Key Vault。
- 将证书绑定到集群的 Vault Secrets,将证书拉到
Cert:/LocalMachine/My/
- 修改了应用程序配置以在初始化 Kestrel 时使用此证书,并验证在初始化时可以找到它。
- 尝试过使用和不使用
UseHsts()
和UseHttpsRedirection()
- Kestrel 在选项 object. 上配置了
UseUrls(string)
与默认 Url 一起使用,即https://+:<port>
但尝试手动添加https://*:<port>
甚至实际主机名本身。
Listen(IPAddress.IPv6Any, endpoint.Port, ...)
和UseHttps(X509Certificate2)
- 尝试过使用和不使用
无论我如何尝试,都无法与服务器建立HTTPS 连接。尝试仍然使用旧证书的其他登台服务器的端点,它按预期工作。
使用 openssl s_client -connect devcluster.someexampledomain.com:<port> -prexit
,我得到:
---
no peer certificate available
---
No client certificate CA names sent
---
ETW 上没有记录任何错误或异常,一切似乎都井井有条。我怀疑这可能与证书的 CN 有关,但我 运行 没有想法尝试找出发生了什么以及如何修复它。
一直在尝试使用 Fiddler 对此进行研究,但我并没有从中得到多少,session 仅以 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 虚拟机上安装 Fiddler 运行我的集群是一个可行的解决方案。
深入研究 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
,但名称不同。他们都指的是同一个证书,所以它有效。不得不将它们加倍感觉不是特别干净,但这是我现在的解决方案。