C#中GRPC的TLS支持

7
我对C#还比较陌生,需要使用GRPC来进行TLS通信。
作为试运行,我正在修改主grpc代码库中提供的示例以使用TLS。为此,我找到了另一个stackoverflow问题,其中有一个看起来很好的答案:如何启用gRPC服务器端SSL?。然而,我遇到了错误未处理的异常:Grpc.Core.RpcException:状态(StatusCode = Unavailable,Detail =“ Connect Failed”)(完整跟踪如下)。
如果在原始的非TLS代码中指定不正确的端口或仅不启动服务器,则会出现相同的错误。我正在Ubuntu上使用dotnet core。
以下是代码的重要部分,也可以在github上的fork中找到完整代码。
客户端:
  var cacert = File.ReadAllText(@"../ca.crt");
  var clientcert = File.ReadAllText(@"../client.crt");
  var clientkey = File.ReadAllText(@"../client.key");
  var ssl = new SslCredentials(cacert, new KeyCertificatePair(clientcert, clientkey));
  var channel = new Channel("localhost", 555, ssl);
  var client = new Greeter.GreeterClient(channel);

  String user = "you";

  var reply = client.SayHello(new HelloRequest {Name = user});
  Console.WriteLine("Greeting: " + reply.Message);

  channel.ShutdownAsync().Wait();
  Console.WriteLine("Press any key to exit...");
  Console.ReadKey();

服务器:

  var cacert = File.ReadAllText(@"../ca.crt");
  var servercert = File.ReadAllText(@"../server.crt");
  var serverkey = File.ReadAllText(@"../server.key");
  var keypair = new KeyCertificatePair(servercert, serverkey);
  var sslCredentials = new SslServerCredentials(new List<KeyCertificatePair>() {keypair}, cacert, false);

  var server = new Server
  {
    Services = {Greeter.BindService(new GreeterImpl())},
    Ports = {new ServerPort("0.0.0.0", 555, sslCredentials)}
  };
  server.Start();


  Console.WriteLine("Greeter server listening on port " + Port);
  Console.WriteLine("Press any key to stop the server...");
  Console.ReadKey();

  server.ShutdownAsync().Wait();

程序的完整输出:

$ cd GreeterClient
$ dotnet run -f netcoreapp1.0

Unhandled Exception: Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Connect Failed")
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg)
   at Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request)
   at Grpc.Core.Internal.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request)
   at Helloworld.Greeter.GreeterClient.SayHello(HelloRequest request, CallOptions options)
   at Helloworld.Greeter.GreeterClient.SayHello(HelloRequest request, Metadata headers, Nullable`1 deadline, CancellationToken cancellationToken)
   at GreeterClient.Program.Main(String[] args)

还有服务器:

$ cd GreeterServer/
$ dotnet run -f netcoreapp1.0
Greeter server listening on port 50051
Press any key to stop the server...

我是否犯了一些愚蠢的错误,或者这个程序不能在非Windows机器上运行?有没有办法调试问题以找出发生了什么?

1个回答

7
您的代码正确实现了使用自签名证书的双向传输层安全性(MTLS)- 我在Windows netcore上运行时没有进行任何更改。
我确实需要微调证书生成脚本:
  • 为客户端/CN(通用名称)添加环境变量定义CLIENT-COMPUTERNAME
  • 添加-config选项以消除“无法在配置中找到‘distinguished_name’”错误(可能是Windows上的openssl问题)
我故意不匹配客户端连接的主机(127.0.0.1而不是localhost),从而能够复制您遇到的相同错误消息。所以,也许你只需要重新生成密钥,例如将localhost作为客户端的公共名称。

2
是的,您连接的主机名称需要与客户端通道目标匹配(因此您可能需要重新生成证书以使它们匹配)。您可以通过设置环境变量GRPC_VERBOSITY=debug来启用更多日志记录以获得更多信息。 - Jan Tattermusch

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