1

I have gRPC client / server code happily working on my local machine with the client using ChannelCredentials.Insecure but need to switch to a secure mode. I dont need any certificate checks just encrypted traffic. Ive been unable to find any configuration of client server that talks to each other. Running c# core server (gRPC 2.27.0), & c# .net framework client (gRPC 2.28.1).

The server says it publishing on http & https as below:

[20:12:58 DBG] Using development certificate: CN=localhost (Thumbprint: 3EDA2E5BD559D75C9DCF058E0A6994EED859CD34)
[20:12:58 INF] Now listening on: https://localhost:5001
[20:12:58 INF] Now listening on: http://localhost:5000

and client works with:

 ChannelBase channel = new Channel("localhost:5000", ChannelCredentials.Insecure);
 var client = new MyApp.MyAppClient(channel);
 var response = client.Test(request)

If I switch client to SslCredentials as below

 ChannelBase channel = new Channel("localhost:5001", new SslCredentials());
 var client = new MyApp.MyAppClient(channel);
 var response = client.Test(request)

I get the following errors.

server error

[19:32:53 DBG] Failed to authenticate HTTPS connection.
System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)

client error

Grpc.Core.RpcException: 'Status(StatusCode=Unavailable, Detail="failed to connect to all addresses")'

I've also tried adding (server) with no change in errors.

   services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
      .AddCertificate(options =>
      {
          options.RevocationMode = X509RevocationMode.NoCheck;
          options.ValidateCertificateUse = false;
          options.AllowedCertificateTypes = CertificateTypes.SelfSigned;
      });

Any suggestions as to what i need to do to make them talk.

  • I found a way to display all the client side grpc debug statements (GRPC_TRACE & GRPC_VERBOSITY) - but that only recorded abandonded. Need to find similar for server. – user2177118 Apr 08 '20 at 16:34

3 Answers3

2

So you need to specify roots.pem that correspond to the dev certificate you're using on your server when creating SslCredentials.

If you use parameterless SslCredentials(), it will use the default trust roots which only work for certificates that have been signed by publicly trusted certificate authorities (e.g. if you're talking "official" servers such as googleapis.com etc, definitely not the case for your development certificates that you are using on your server). So you need to use SslCredentials(yourCustomTrustRootsPem).

Btw, with SSL/TLS, there's no such thing as "no certificate checks". The client will ALWAYS check that it connected to the right server (server's certificate are verifiable by their trust roots) - without that the secure communication would make no sense because it would be too susceptible to man-in-the-middle attack. (the server checking authenticity of client is optional though).

Feel free to refer to https://github.com/jtattermusch/grpc-authentication-kubernetes-examples for extra resources.

Jan Tattermusch
  • 1,515
  • 9
  • 9
  • It would be really interesting to know exactly what makes Grpc.Net read a self-signed cert from the certificate store, while Grpc.Core does not (and requires a pem input). What is Grpc.Core filtering on (since it does read official CAs from the trusted cert store but not self-signed ones)? Maybe there's some ssl extension that can be set to get through that filter? – sevenam Apr 21 '23 at 08:12
1

I had a similar problem and finally found a solution to establish HTTPs connection between

  • .NET Framework 4.7.2 client (WPF app) and
  • ASP .NET Core 3.1 gRPC Server (Console).

Indeed the answer of Jan Tattermusch is correct. You need to supply the server side certificate as PEM to the constructor of SslCredentials and in addition, the certificate has to contain the DNS name or IP of the url you are contacting the server through. In your case, I suggest to manually create a self-signed certificate for each server instead of using the developer certificate. This one can be downloaded by your client and then be passed as SslCredentials. Works like a charm.

See my more details on how to do all the details in my answer to a similar question here:

https://stackoverflow.com/a/63565090/378415

JanW
  • 1,799
  • 13
  • 23
0

Try to check on which port Grpc Service is running after deployment in any way either windows service or other , then give the same in client to consume the service. Eg: If your service is running on https://localhost:5000 then give the same in client. It will work for sure.

Mostly you will get the above issue when you make a mistake of mismatching the address of service to client.

Pierre.Vriens
  • 2,117
  • 75
  • 29
  • 42