Kestrel 可以通过编程方式配置为在生产环境中不需要开发证书吗?

问题描述 投票:0回答:1

不知道我是否愚蠢。

使用 NET 6,我有一段代码可以在我指定的端口上启动 Kestrel,并使用配置中指定的 SSL 证书。基本上这在开发机器和 UAT 服务器上工作得很好,因为它们有本地主机的开发证书,并且在 UAT 上,当外部调用站点时会加载正确的证书。

当我将其移至生产环境时,如果没有开发证书,它将无法启动并显示“无法配置 HTTPS 端点。未指定服务器证书,并且找不到默认开发人员证书...”错误。我通过删除 UAT 上的开发者证书来验证原因,然后它无法启动,以同样的方式,当我重新安装证书时,它再次启动正常。

对我来说,这是有道理的,因为它试图侦听包括环回在内的所有 IP 地址,但是我可以做些什么,以便无需在生产服务器上安装开发证书即可启动它,这似乎是一个可怕的黑客攻击?

WebApplicationBuilder builder = WebApplication.CreateBuilder(options);

builder.Host.UseWindowsService(options => options.ServiceName = "Windows Kestrel Server");

builder.WebHost.ConfigureKestrel(serverOptions =>
  {
      int Port = builder.Configuration.GetValue<int>("Port");
      
      serverOptions.ListenAnyIP(Port, listenOptions =>
      {
          listenOptions.UseHttps(httpsOptions =>
          {
              listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
              {
                  string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
                  string? CertName = builder.Configuration.GetSection("CertificateName").Value;

                  if (StoreName == null)
                    StoreName = "My";
                  if (string.IsNullOrEmpty(CertName))
                    CertName = clientHelloInfo.ServerName;
                  X509Certificate2? Cert = null;
                  try
                  {
                      Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
                  }
                  catch { };
                  try
                  {
                      if (Cert == null)
                          Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
                  }
                  catch { };
                  
                  return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions { ServerCertificate = Cert});

              }, state: null!);
              
          });
      });
  });

我尝试了各种方法将证书设置为配置中指定的证书,但它们似乎都遇到了同样的基本问题

ssl-certificate .net-6.0 startup production kestrel
1个回答
0
投票

我尝试在配置中添加默认值,但没有成功,因为我使用的是 builder.WebHost.ConfigureKestrel,并且我尝试在 serverOptions.ListenAnyAPI 中配置默认值,但失败了因为它运行得太晚了

我需要做的就是在配置监听器之前在ConfigureKestral中配置serverOptions.ConfigureHttpsDefaults!

我希望这可以帮助其他遇到类似部署问题的人。

WebApplicationBuilder builder = WebApplication.CreateBuilder(options);

builder.Host.UseWindowsService(options => options.ServiceName = "Windows Kestrel Server");

builder.WebHost.ConfigureKestrel(serverOptions =>
  {

      int Port = builder.Configuration.GetValue<int>("Port");

      //   IPGlobalProperties IPP = IPGlobalProperties.GetIPGlobalProperties();

      serverOptions.ConfigureHttpsDefaults(configureOptions =>
      {
          string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
          string? CertName = builder.Configuration.GetSection("CertificateName").Value;

          if (StoreName == null)
              StoreName = "My";
          if (string.IsNullOrEmpty(CertName))
              CertName = "localhost";

          X509Certificate2? DefaultCert = null;

          try
          {
              DefaultCert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
          }
          catch { };
          try
          {
              if (DefaultCert == null)
                  DefaultCert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
          }
          catch { };

          configureOptions.ServerCertificate = DefaultCert;
      });

      serverOptions.ListenAnyIP(Port, listenOptions =>
      {
          listenOptions.UseHttps(httpsOptions =>
          {
              listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
              {

                  string? CertName = builder.Configuration.GetSection("CertificateName").Value;
                  string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
                  
                  if (StoreName == null)
                    StoreName = "My";
                  if (string.IsNullOrEmpty(CertName))
                    CertName = clientHelloInfo.ServerName;
                  X509Certificate2? Cert = null;
                  try
                  {
                      Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
                  }
                  catch { };
                  try
                  {
                      if (Cert == null)
                          Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
                  }
                  catch { };
                  
                  return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions { ServerCertificate = Cert});

              }, state: null!);
              
          });
      });
  });
© www.soinside.com 2019 - 2024. All rights reserved.