How to connect Grpc (netstandard 2.0) with Grpc.Asp.NetCore server (.NET 5.0) using HTTPS and my own certificate? [duplicate]
Asked Answered
O

1

0

I get this exception on the client:

Grpc.Core.RpcException: 'Status(StatusCode="Unavailable", Detail="failed to connect to all addresses", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1606620349.107000000","description":"Failed to pick subchannel","file":"T:\src\github\grpc\workspace_csharp_ext_windows_x86\src\core\ext\filters\client_channel\client_channel.cc","file_line":4166,"referenced_errors":[{"created":"@1606620349.107000000","description":"failed to connect to all addresses","file":"T:\src\github\grpc\workspace_csharp_ext_windows_x86\src\core\ext\filters\client_channel\lb_policy\pick_first\pick_first.cc","file_line":398,"grpc_status":14}]}")'

Client channel:

        private Channel GetChannel()
    {
        return new Channel(
            _settings.FileServiceUri
            , CertificatePEM == null ? ChannelCredentials.Insecure :
                new SslCredentials(
                    CertificatePEM
                    , new KeyCertificatePair(CertificatePEM, File.ReadAllText("Syrilium.FileUpdater.cer.key"))
                )
            , new[] {
                new ChannelOption(ChannelOptions.MaxReceiveMessageLength,int.MaxValue),
                new ChannelOption(ChannelOptions.MaxSendMessageLength,int.MaxValue),
                }
            );
    }

Server config:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())

            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.ConfigureKestrel(kestrelOptions =>
                {
                    var sslCertificate = LoadSSLCertificate();
                    kestrelOptions.ListenAnyIP(/*IPAddress.Parse("127.0.0.1"),*/ 5001
                       , listenOptions =>
                       {
                           listenOptions.UseHttps(
                             sslCertificate,
                              httpsOptions =>
                              {
                                  //httpsOptions.SslProtocols = SslProtocols.Tls12;
                                  httpsOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
                                  httpsOptions.ClientCertificateValidation = (certificate, chain, errors) =>
                                  {
                                      return true /*certificate.Thumbprint.Equals(_clientThumbprint, StringComparison.OrdinalIgnoreCase)*/;
                                  };
                              }
                             );
                           listenOptions.Protocols = HttpProtocols.Http2;
                       }
                       );

                });

                webBuilder.UseStartup<Startup>();
            });

When I just remove

listenOptions.UseHttps...

on the server and use

ChannelCredentials.Insecure

on the client, it works.

How to make those two communicate with HTTPS and my own certificate? Just a simple example of both client and server that work on these newest versions of libraries.

I get a call to

   httpsOptions.OnAuthenticate = (ctx, auth) => {     };

on service but I don't know what, if anything useful I can do with it? It fails on a handshake.

Olden answered 22/11, 2020 at 5:36 Comment(10)
the source project 127.0.0.1:5001 is listening? you can start multiple projects in VS when debugging, however, I find it easier to have 2 instances of vs using the same, or use 2 solutions referencing the same projects. Sometimes the client is ready to communicate before the service is ready to answer. If your client is .Net 5 it will be faster and you might have a race condition. Also make sure the port is accurate, normally it's localhost:5001 and not the IP of local hostMetonym
disable the firewall and try again, make sure the port is accurate, right now you are connecting to port 5001, the server must be listening on that. have a look in your event log and see if there are any hints. Also can you connect using PostMan or Fiddler?Metonym
Also confirmed that the problem is in Grpc (2.33.1) because without any code change other client with Grpc.Net.Client (2.33.1) connects to that same server.Olden
are you seeing the request in fiddler? if so look if the headers are compatible V1.1 or V2 etc if so scroll down to this post and look at the header section devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-6Metonym
There is no Fiddler activity with Grpc (2.33.1), but there is with Grpc.Net.Client (2.33.1).Olden
Found the problem, you were right. I was constantly running both projects from the same solution, after I've run the server from one solution and client from another it works. Oh, what pain and a huge waste of time. It's probably some VS limitation or a bug when using diff frameworks?Olden
No has nothing to do with the frameworks, it's just that .net 5 is faster and you had a race condition that you did not have on the other framework. That's why I use 2 solutions, one with the Server projects and one with the client projects. would be nice if VS would have a delayed start when debugging but ... how much delay do you need. and when you start solving issues with altering production code you have to get a coffee and re-think you actions... There are a lot of "what the fxxx" features in visual studioMetonym
the important thing is that you know this now and you can tell others that have the same issueMetonym
"net 5 is faster and you had a race condition that you did not have on the other framework." for sure it was not that because I had Thread.Sleep(5000) on the client and I clearly saw that server was running and telnet connecting.Olden
generate sole logging points and have a look at how your multi-threaded application ignores the thread you block.... The compilation IL of your runtime does not care about the 2.0 code in the 5.0 as long as you have compatible dll on disk, if it did not you would get FileNotFound errors when starting the application and the dependent libs are loaded and linkedMetonym
M
0

I write the solution here after the comments contained the solution as who reads the comments...

The issue is that .net 5.0 client is faster and the client can't connect as the server is not ready to accept connections. When developing Client and Server best to have 2 solutions with the shared projects so you can debug both at the same time using 2 instances of visual studio. YOu can open the same solution with several instances of VS however you will start running into different issues for example in the intermediate window and output window.

Metonym answered 22/11, 2020 at 9:44 Comment(3)
Tested again with Thread.Sleep(10000) and connecting with telnet in that time, speed is not the issue, the problem is in: mixed frameworks, VS, or Grpc package.Olden
if that's the case 2 instances would not solve the issue as the code generated is the same. Write a batch file and start the exe of the service without VS and it will connect. Include logging and log to console what it does and set break points in your client code so that you can see how the connections between your client and server are executed. also, use Fiddler and live record the communication so you see the time-outsMetonym
I've done with the fiddler, he does not catch anything. If you want I'll send you the example project. Don't know what is the issue but I am certain it's not the speed because I've tested that. The most obvious is the VS problem, after all, I am using the preview version.Olden

© 2022 - 2024 — McMap. All rights reserved.