如何将.NET框架中的gRPC客户端与安全的.NET Core服务器连接?

6
我是使用protobuf-net.Grpc在.NET Core服务器上,并尝试从.NET Framework(4.7.2)gRPC客户端进行调用。完整示例在这里:https://github.com/angelagyang/GRPCProtobufExample 以下是我的客户端片段:
var channelCreds = new SslCredentials(GetRootCertificates());
var channel = new Channel("localhost", 5001, channelCreds);
var greeter = channel.CreateGrpcService<IGreeterService>();

使用这个配置时,当调用服务器时会出现错误StatusCode="Unknown", Detail="Stream removed"...。如果我在服务器上设置ClientCertificateMode = ClientCertificateMode.NoCertificate,则可以连接到服务器。然而,我希望服务器需要客户端证书并通过指纹验证证书

例如,在.NET Core中,我可以使用Grpc.Net.Client来配置我的通道,如下所示:

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
var channel2 = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
      HttpHandler = handler
});

有没有办法在.NET Framework中配置客户端证书,就像这样?我对gRPC/.NET还不太熟悉,希望得到建议!

2
我找到了一个与你的类似但有些不同的示例,也许可以帮助你:https://grpc.io/docs/guides/auth/(查找文本 **C#**)。 - Peter B
1
非常有趣的问题。我明天会尝试挖掘一下。 - Marc Gravell
GRPC 是 HTTP/2。Peter 的链接仅涉及在使用 TCP 进行连接时在连接开始时完成的 SSL/TLS 安全性,而不是整个解决方案。OP 帖子顶部的链接并非始终有效。当客户端和服务器位于同一台计算机上时,它将无法工作,因为两者都使用 localhost。如果机器将环回 IP 127.0.0.1 作为 localhost,则代码也不会工作。建议进行 TCP 连接的方法是,服务器始终使用 IPAddress.Any 作为端点地址。客户端应该连接到服务器的 IP 或使用 DNS.GetHost 然后使用地址数组的索引 1。 - jdweng
2个回答

4

已解决并更新了原始示例:https://github.com/angelagyang/GRPCProtobufExample

您可以通过创建一个KeyCertificatePair并将其传递给SslCredentials来配置客户端证书。您需要 PEM 编码的证书链和 PEM 编码的私钥。

var keyCertPair = new KeyCertificatePair(File.ReadAllText($"{rootDir}/cert.pem"), File.ReadAllText($"{rootDir}/cert.key")); 
var channelCreds = new SslCredentials(GetRootCertificates(), keyCertPair);

为了测试目的,我在这里使用了自签名证书:https://github.com/grpc/grpc/tree/master/src/core/tsi/test_creds
调试时,设置 GRPC_VERBOSITY = DEBUGGRPC_DEBUG = ALL。这可以帮助澄清模糊的错误消息。例如,我发现我用来配置 HTTPS 的服务器证书没有包含 localhost。

我在我的gRPC服务上有一个带有私钥的证书,但是我需要在客户端使用pfx吗?为什么不使用没有私钥转换成PEM的cer文件呢?我必须使用keyCertPair吗?如何在Visual Studio和C#中设置这些变量? - Hrvoje Batrnek

0

从我尝试并实现的情况来看,您可以省去阅读 cert.pemcert.key 的麻烦。另外,GetRootCertificate() 只有在服务器系统托管在知名可信网站(如 google.commsdn.com 或类似网站以及本地主机)时才会起作用。您可以在 此处此处 找到更详细的答案。

如果我们打算使用自己的主机 DNS 与 SSL,请生成一个分配给您的 DNS 的 pfx 服务器证书,并将其转换为客户端应用程序的 pem。使用 openssl 等工具可以帮助转换证书编码。

openssl pkcs12 -in "<DiskLocationOfPfx>\ProjectName.pfx" -out "<TargetLocation>\certifcate.pem" -clcerts

一旦您将服务器证书转换为pem格式,您就可以使用它了。

var channelCreds = new SslCredentials(File.ReadAllText($"{rootDir}/cert.pem"));
var channel = new Channel("www.youdns.com", 5001, secureCredentials);

我在我的gRPC服务上有一个带有私钥的证书,但是我需要在客户端使用pfx吗?为什么不使用没有私钥转换成PEM的.cer文件呢? - Hrvoje Batrnek
在客户端中使用pem。或者将证书安装到根证书存储中,并从存储中读取。 - Jins Peter
已经尝试过了。您可以查看我的示例:https://github.com/hovek/grpc_certifier_example - Hrvoje Batrnek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接