C# 中对 GRPC 的 TLS 支持
TLS support for GRPC in C#
我是 C# 的新手,我需要使用 GRPC over TLS。
作为干货-运行,我正在修改main grpc repo to use TLS. To do this, I found another SO question with what seemed like a good answer: 中提供的示例。但是,我得到一个错误 Unhandled Exception: Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Connect Failed")
(下面的完整跟踪)。
如果我在原始的非 tls 代码中指定了不正确的端口或只是不启动服务器,我会得到同样的错误。我在 Ubuntu.
上使用 dotnet 核心
代码的重要部分在下面,也可以在 github.
上的一个分支上找到完整的代码
客户:
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 机器上吗?有什么方法可以调试问题以弄清楚发生了什么吗?
您的代码使用自签名证书正确实施了相互 TLS - 我能够在 windows netcore 上 运行 它而无需任何更改。
我确实需要稍微调整一下证书生成脚本:
- 为
CLIENT-COMPUTERNAME
添加环境变量定义,用于客户端 /CN
(通用名称)
- 添加
-config
选项以消除 unable to find 'distinguished_name' in config
错误(可能是 Windows 上的 openssl)
我能够通过故意不匹配客户端连接到的主机(127.0.0.1
而不是 localhost
)来重现相同的错误消息。所以也许你只需要用例如重新生成你的密钥localhost
作为客户的常用名。
我是 C# 的新手,我需要使用 GRPC over TLS。
作为干货-运行,我正在修改main grpc repo to use TLS. To do this, I found another SO question with what seemed like a good answer: Unhandled Exception: Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Connect Failed")
(下面的完整跟踪)。
如果我在原始的非 tls 代码中指定了不正确的端口或只是不启动服务器,我会得到同样的错误。我在 Ubuntu.
上使用 dotnet 核心代码的重要部分在下面,也可以在 github.
上的一个分支上找到完整的代码客户:
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 机器上吗?有什么方法可以调试问题以弄清楚发生了什么吗?
您的代码使用自签名证书正确实施了相互 TLS - 我能够在 windows netcore 上 运行 它而无需任何更改。
我确实需要稍微调整一下证书生成脚本:
- 为
CLIENT-COMPUTERNAME
添加环境变量定义,用于客户端/CN
(通用名称) - 添加
-config
选项以消除unable to find 'distinguished_name' in config
错误(可能是 Windows 上的 openssl)
我能够通过故意不匹配客户端连接到的主机(127.0.0.1
而不是 localhost
)来重现相同的错误消息。所以也许你只需要用例如重新生成你的密钥localhost
作为客户的常用名。