简体   繁体   English

配置 ASP.NET Core gRPC 以在服务器和客户端上使用 SSL/TLS

[英]Configure ASP.NET Core gRPC to use SSL/TLS on both the server and client

I am going to repost this once again.我要重新发布一次。 If you don't like my question, there are tons of other posts here that you can apply your personal (and incorrect) judgement to.如果您不喜欢我的问题,这里还有大量其他帖子,您可以根据自己的(和错误的)判断对其进行判断。 There is only one issue here: How do you use the ASP.NET Core APIs for gRPC to establish SSL/TSL on BOTH the server and the client ... How else can it be stated???这里只有一个问题:你如何使用 ASP.NET Core APIs for gRPC 在服务器和客户端上建立 SSL/TSL ......还能怎么说???

I have searched the ends of the internet for documentation on how to configure gRPC to use TLS.我在互联网的尽头搜索了有关如何配置 gRPC 以使用 TLS 的文档。 I can find some people who have posted a "solution" but I personally feel they are hacking it to make it work.我可以找到一些发布“解决方案”的人,但我个人觉得他们正在破解它以使其工作。 When I look at the Microsoft gRPC documentation along with the relative ASP.NET Core documentation, I know there are many APIs that do what I need to have them do... I just can't find any documentation on how to use them.当我查看 Microsoft gRPC 文档以及相关的 ASP.NET Core 文档时,我知道有很多 API 可以完成我需要它们做的事情……我只是找不到任何关于如何使用它们的文档。 I know the WHAT, just not the HOW.我知道什么,只是不知道如何。

I have two types of servers to deploy.我有两种类型的服务器要部署。 One of the "servers" will also be a client in a mesh network topology.其中一个“服务器”也将是网状网络拓扑中的客户端。 One server will be outward-facing with a public IP address.一台服务器将使用公共 IP 地址向外。 The other servers will be deployed on an individual's personal computer.其他服务器将部署在个人的个人计算机上。 I am totally lost as to what types of certificates I need to use.我完全不知道我需要使用什么类型的证书。 I think I got it to work, sort of, using one of the hacks I found.我想我可以使用我发现的其中一种技巧让它工作。 The other servers, I don't know quite what to do.其他服务器,我不知道该怎么办。

I used a Microsoft-posted tutorial: "Create a gRPC client and server in ASP.NET Core" and "gRPC services with ASP.NET Core" and was able to get the simple, localhost, Kestrel SSL configuration to work.我使用了 Microsoft 发布的教程:“在 ASP.NET Core 中创建 gRPC 客户端和服务器”和“使用 ASP.NET Core 的 gRPC 服务”,并且能够使简单的本地主机 Kestrel SSL 配置工作。 Now, I need to put on my big boy pants and use real certificates.现在,我需要穿上我的大男孩裤子并使用真正的证书。

RANT MODE ON咆哮模式开启

In my attempts to find a solution, I have found Google searches to be nothing but snipe hunts.在我试图找到解决方案的过程中,我发现 Google 搜索只不过是狙击狩猎。 Then, in this forum, people find it upon themselves to disparage those who ask questions by asking more stupid questions or spewing unnecessary judgement because a question wasn't asked to their liking.然后,在这个论坛上,人们发现自己可以通过提出更愚蠢的问题或发表不必要的判断来贬低提出问题的人,因为问题不是他们喜欢的。 These holier-than-thous don't seem to understand that these people who are doing the asking are asking BECAUSE THEY DON'T KNOW THE ANSWER OR IN MOST CASES, EVEN HOW TO ASK A "PROPER" QUESTION.这些比你更神圣的人似乎不明白,这些提问的人之所以提问,是因为他们不知道答案,或者在大多数情况下,甚至不知道如何提出“正确”的问题。 If you are one of those people, go find something else to do as you are simply wasting your time and the time of people who are also seeking answers.如果你是这些人中的一员,那就去找点别的事情做,因为你只是在浪费你的时间和那些也在寻求答案的人的时间。

I have asked several questions over time in this forum.随着时间的推移,我在这个论坛上问了几个问题。 Never once has this forum ever answered one of my questions... I had to solve them on my own so basically, this forum is about 97% useless.这个论坛从来没有回答过我的问题……我不得不自己解决这些问题,所以基本上,这个论坛大约 97% 没用。 But, in the interest of saving someone else time, I am posting a solution.但是,为了节省其他人的时间,我发布了一个解决方案。

RANT MODE OFF咆哮模式关闭

My issue was how to configure a gRPC server to use TLS.我的问题是如何配置 gRPC 服务器以使用 TLS。 Using OpenSSL, there are a myriad of ways to create certificate files, but you have to know exactly which set of commands to use to get the type of certificate you need.使用 OpenSSL,有无数种方法可以创建证书文件,但您必须确切地知道使用哪一组命令来获取您需要的证书类型。 In my case, I am using Ubuntu 20.04 Server, Visual Studio 2022, C#, ASP.NET Core 6, and gRPC.就我而言,我使用的是 Ubuntu 20.04 Server、Visual Studio 2022、C#、ASP.NET Core 6 和 gRPC。 The base issue was how to configure Kestrel to use a certificate and listen to a set of specific ports.基本问题是如何配置 Kestrel 以使用证书并侦听一组特定端口。 The Microsoft documentation is pitiful in that it will give you the signature of an API call, but almost NEVER will show even a minute code snippet.微软的文档很可怜,因为它会给你一个 API 调用的签名,但几乎从不显示哪怕是一分钟的代码片段。 I could find no examples in this or any other Google search.我在这个或任何其他谷歌搜索中找不到任何例子。 I basically brute forced my way to success.我基本上是蛮力强迫我的成功之路。

I have two profiles in launchSettings.json:我在 launchSettings.json 中有两个配置文件:

{
    "profiles": {
        "OperationsServicesDev": {
            "commandName": "Project",
            "dotnetRunMessages": true,
            "launchBrowser": false,
            "applicationUrl": "https://localhost:30051",
            "environmentVariables": {
                "ASPNETCORE_ENVIRONMENT": "Development",
                "ASPNETCORE_PREVENTHOSTINGSTARTUP": "true"
            }
        },
        "OperationsServicesProd": {
            "commandName": "Project",
            "dotnetRunMessages": true,
            "launchBrowser": false,
            "applicationUrl": "https://some.node.com:30051",
            "environmentVariables": {
                "ASPNETCORE_ENVIRONMENT": "Production",
                "ASPNETCORE_PREVENTHOSTINGSTARTUP": "true"
            }
        }
    }
}

I use the various profiles to control things that are different in the Linux versus Windows worlds such as log folders, ports, etc. I also make use of appsettigns.Development.json adn appsettings.Production.json to further control the differences in environments.我使用各种配置文件来控制 Linux 与 Windows 世界中不同的东西,例如日志文件夹、端口等。我还使用 appsettings.Development.json 和 appsettings.Production.json 来进一步控制环境的差异。 The development profile always worked as I was testing in a development environment using a dev cert.当我使用开发证书在开发环境中进行测试时,开发配置文件始终有效。 When I deployed the published works to my server, the wheels stopped turning.当我将发布的作品部署到我的服务器时,车轮停止转动。 I would get a denial of service, or a timeout, or a vague error about the certificate not passing the parsing stage.我会收到拒绝服务、超时或关于证书未通过解析阶段的模糊错误。

I have a valid set of certs from Godaddy.com.我有一组来自 Godaddy.com 的有效证书。 I will come back to this in a bit.稍后我会回到这个话题。

Since projects in .NET 6 have had their templates changed, this added more time brute-forcing stuff, but I figured that out.由于 .NET 6 中的项目已经更改了它们的模板,这增加了更多的时间蛮力的东西,但我想通了。 Startup.cs is no longer used (I guess you can still create one and use it, but all of the configuration is now done in Program.cs. Startup.cs 不再使用(我猜你仍然可以创建一个并使用它,但所有配置现在都在 Program.cs 中完成。

I start off getting access to the various builders:我开始访问各种构建器:

// Start the app configuration.  Enlist the help of the various
// .Net Core builders.
var builder = WebApplication.CreateBuilder (args);
var webHostBuilder = builder.WebHost;

// What environment are we running?  It could be either Development
// or Production.  This is used to get the correct configuration from
// the appsettings.Development.json or appsettings.Production.json
// files.
var environment = builder.Environment.EnvironmentName;

Then, using NLog, I configure the loggers:然后,使用 NLog,我配置记录器:

// Configure logging.
_ = webHostBuilder.ConfigureLogging (options => {

    // Get the correct appsettigns.environment.json file.
    var config = new ConfigurationBuilder ()
        .SetBasePath (Directory.GetCurrentDirectory ())
        .AddJsonFile ($"appsettings.{environment}.json", optional: true, reloadOnChange: true).Build ();

    _ = options.AddNLog (config);

    // Get the logger.
    LogManager.Configuration = new NLogLoggingConfiguration (config.GetSection ("NLog"));

    logger = NLogBuilder.ConfigureNLog (LogManager.Configuration).GetCurrentClassLogger () as NLog.ILogger;
});

Next it's time to configure Kestrel:接下来是配置 Kestrel 的时候了:

// Configure Kestrel, the .NET Core web server.
var hostBuilder = webHostBuilder.ConfigureKestrel (kestrelServerOptions => {

    kestrelServerOptions.ConfigureHttpsDefaults (httpsConnectionAdapterOptions => httpsConnectionAdapterOptions.SslProtocols = SslProtocols.Tls12);

    // Read in the X.509 certificate file.
    var certPath = Path.Combine (builder.Environment.ContentRootPath, "Certs", $"xxx-{environment}.pfx");

    kestrelServerOptions.ConfigureEndpointDefaults (listenOptions => {

        _ = listenOptions.UseHttps (certPath, password);

        logger.Debug ($"Using {certPath} as the cert file.");
        logger.Debug ("Configuring host to use HTTP/2 protocol.");

        listenOptions.Protocols = HttpProtocols.Http2;
    });

    logger.Debug ("Reading config values for the server name and port.");

    // Get the host name and port number to bind the service to.
    var port = builder.Configuration.GetValue<int> ("AppSettings:OperationsServerPort");
    var address = IPAddress.Parse ("0.0.0.0");

    if (address != null) {
        logger.Debug ($"Host will listen at https://{address}:{port}");

        kestrelServerOptions.Listen (address, port);
    } else {
        logger.Error ("DNS address for service host cannot be determined!  Exiting...");

        Environment.Exit (-1);
    }
});

When errors occur on the server side, it is helpful for the gRPC pipeline to give some clues on exceptions thrown:当服务器端发生错误时,gRPC 管道提供一些关于抛出异常的线索是有帮助的:

// Configure gRPC exception handling.
_ = builder.Services.AddGrpc (grpcServiceOptions => {

    grpcServiceOptions.Interceptors.Add<ServerLoggerInterceptor> ();

    _ = grpcServiceOptions.EnableDetailedErrors = true;
});

The rest is boilerplate.其余的是样板。

Now, the crucial thing is in creating the .pfx cert file.现在,关键是创建 .pfx 证书文件。 I had originally been including the Godaddy CA bundle file, typically named gd_bundle-g2-g1.crt.我最初一直在包含 Godaddy CA 包文件,通常命名为 gd_bundle-g2-g1.crt。 When I added several certs to the Ubuntu trust store (and this Godaddy bundle was one of the files I loaded into the trust store) I noticed an error when I did a当我将几个证书添加到 Ubuntu 信任库(这个 Godaddy 包是我加载到信任库中的文件之一)时,我注意到一个错误

sudo update-ca-certificates  --fresh

I got this extremely helpful clue:我得到了这个非常有用的线索:

Clearing symlinks in /etc/ssl/certs... done.清除 /etc/ssl/certs 中的符号链接...完成。 Updating certificates in /etc/ssl/certs... rehash: warning: skipping gd_bundle-g2-g1.pem,it does not contain exactly one certificate or CRL 131 added, 0 removed;正在更新 /etc/ssl/certs 中的证书... rehash:警告:跳过 gd_bundle-g2-g1.pem,它不包含完全一个证书或 CRL 131 添加,0 删除; done.完毕。 Running hooks in /etc/ca-certificates/update.d... done.在 /etc/ca-certificates/update.d 中运行钩子...完成。

This was the OpenSSL command I used to create the bad certificate file:这是我用来创建错误证书文件的 OpenSSL 命令:

openssl pkcs12 -export -out certificate.pfx -inkey server.key -in 1baa5781b0db93d3.crt -certfile gd_bundle-g2-g1.crt

The last bit, the -certfile, was the issue.最后一点,-certfile,是问题所在。 When I regenerated the certificate using the following command:当我使用以下命令重新生成证书时:

openssl pkcs12 -export -out certificate.pfx -inkey server.key -in 1baa5781b0db93d3.crt

everything started to work like a charm.一切都开始像魅力一样工作。

Key takeaways:关键要点:

  • Be tenacious顽强
  • Don't listen to the naysayers不要听那些反对者的话
  • Don't be distracted by forum hacks who just want to hear their own voice不要被只想听到自己声音的论坛黑客分心
  • Read the documentation and then read it again and then read it again阅读文档,然后再阅读,然后再阅读
  • Download the source and read that, too.下载源代码并阅读它。

Somewhere along the way, you will find a way to be successful.一路走来,你会找到通往成功的道路。

There's a Mutual-SSL/TLS-Example how to use a gRPC-AspNetCore-Server with a native Grpc.Core.Client and a managed Grpc.Net.Client in my OpenSource Project .有一个 Mutual-SSL/TLS-Example 如何在我的 OpenSource Project 中使用带有本机Grpc.Core.Client和托管Grpc.Net.Client的 gRPC-AspNetCore-Server 。

Just navigate to .\\SiLA2.gRPC.CSharp\\Examples\\TlsConfig .只需导航到.\\SiLA2.gRPC.CSharp\\Examples\\TlsConfig

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何配置IIS / Asp.Net以将客户端证书用于TLS连接到服务器 - How to configure IIS/Asp.Net to use a client Certificate for TLS connection to a server gRPC 服务器 .net 框架 - 如何配置使用 TLS 证书 - gRPC server .net framework - how to configure to use a TLS certificate 如何在ASP.NET Core中获取TLS / SSL相关信息? - How to get TLS/SSL related information in ASP.NET Core? gRpc Unity3D 客户端和 ASP.Net 核心服务器中的异常“无法连接到所有地址” - Exception “failed to connect to all addresses” in gRpc Unity3D client and ASP.Net core server 如何在 gRPC 和 ASP Net Core 3.0 中使用 ssl 证书? - how to use ssl certificates with gRPC and ASP Net Core 3.0? .NET Core:如何为服务和客户端之间的 gRpc 通信禁用 TLS/SSL? - .NET Core: How to disable TLS/SSL for gRpc communication between service and client? 使用 ASP.NET 核心 DI 容器注册“类型化”gRPC 客户端 - Registering a “typed” gRPC client with the ASP.NET Core DI container 如何在ASP.NET Core 2.0中使用TLS 1.2 - How to use TLS 1.2 in ASP.NET Core 2.0 Grpc.Net 客户端无法使用 SSL 连接到服务器 - Grpc .Net client fails to connect to server with SSL 在两个ASP.NET Core 2.1 Razor Web应用程序中将SignalR既用作集线器又用作客户端 - Use SignalR as both a Hub and a Client in two ASP.NET Core 2.1 Razor web apps
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM