1

I've standart project HelloWorld in .net 5 to send grpc request and show in console the result.

This is my GrpcHelloWorldServer :

Program.cs :

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseKestrel(options =>
                    {
                        options.ListenLocalhost(5001, o => 
                        {
                            o.Protocols = HttpProtocols.Http2;
                            o.UseHttps(Get());
                         });

                        options.ListenLocalhost(5000, o =>
                        {
                            o.Protocols = HttpProtocols.Http2;
                        });
                    });

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

My method Get Get certificate :

 public static X509Certificate2 Get()
        {
            var assembly = typeof(Program).GetTypeInfo().Assembly;

            using (var stream = assembly.GetManifestResourceStream("GrpcHelloWorldServer.Certificate.translator.pfx"))
            {
                return new X509Certificate2(ReadStream(stream), "secret", X509KeyStorageFlags.MachineKeySet);
            }
        }

In startup in ConfigureSerices method I use services.AddGrpc(); and in Configure method I've

app.UseEndpoints(endpoints =>
            {
                endpoints.MapGrpcService<TestMyService>();
            });

On client side main method is simple :

 static async Task Main(string[] args)
        {
            try
            {
                // wait for grpc server is running
                Console.WriteLine("Waiting for server is running");
                Thread.Sleep(2000);

                var httpClientHandler = new HttpClientHandler();
                httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;


                var pem = File.ReadAllText(@"my certificate.pem");
                var certData = GetBytesFromPem(pem, "CERTIFICATE");
                var cert = new X509Certificate2(certData);

                httpClientHandler.ClientCertificates.Add(cert);


                var httpClient = new HttpClient(httpClientHandler);


                var grpcChannel = GrpcChannel.ForAddress("https:myserverName:5001",
                    new GrpcChannelOptions { HttpClient = httpClient });

                var client = new TestService.TestServiceClient(grpcChannel);

                var response = await client.TestHelloAsync(new TestRequest { Name = "Julien" });


                Console.WriteLine("Press any key to exit...");
                Console.WriteLine(response.Message);
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

On local on my machine it's works perfectly. But on my Windows Server 2019 grpc request throw 2 exceptions :

For http request :

quote Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1)." quote

And for https request :

quote Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch", DebugException="System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch quote

My IIS configuration is :

enter image description here

So I don't understand why it's working fine on local and not on IIS ?

UPDATE

I add certificate on server and client side, but on my server error is :

Exception Info: System.InvalidOperationException: Application is running inside IIS process but is not configured to use IIS server.

So if I remove UseKestrel in Program.cs and add

webBuilder.UseStartup<Startup>().ConfigureKestrel((context, options) =>
                    {
                        options.ListenLocalhost(5001, o =>
                        {
                            o.Protocols = HttpProtocols.Http2;
                            o.UseHttps(Get());
                        });

                        options.ListenLocalhost(5000, o =>
                        {
                            o.Protocols = HttpProtocols.Http2;
                        });
                    });

, IIS throw another exception :

System.InvalidOperationException: Trailers are not supported for this response. The server may not support gRPC.

Julien Martin
  • 197
  • 2
  • 15
  • It looks like the client is connecting to http (not https) - is this intentional? Also: what certificate is IIS using, and what is the host/cn on the cert? Is it "localhost"? (I'm actually surprised the client code works at all; I seem to recall needing to enable an obscure feature flag to connect http/2 without TLS) – Marc Gravell Feb 12 '22 at 08:59
  • Yes it's intentional, I wanted to check if it's working on my server in http. For certificate the cn is server name. – Julien Martin Feb 12 '22 at 09:03
  • re the name part: but you're connecting to "localhost", so the certificate needs to be for "localhost"; if the cert is "yourservername", then you need to *connect* to "yourservername" - that's how server identity works. You can suppress this by overriding the server name validation at the client, but honestly: don't do that. The mystery, though, is: why is TLS even a thing here? That sounds like an IIS config issue. – Marc Gravell Feb 12 '22 at 09:19
  • I update my post :) , no error about certificate but about Kestrel and Grpc not supported... – Julien Martin Feb 12 '22 at 09:51
  • I think that problem is my Windows Server Build, this [link](https://stackoverflow.com/questions/66100752/net-5-hosting-asp-net-core-grpc-service-in-iis-10-at-windows-server-2019) explain that. So waiting for update my server, we can use grpc-web [link](https://devblogs.microsoft.com/dotnet/grpc-web-for-net-now-available/) and it's works fine on my server :) – Julien Martin Feb 13 '22 at 07:33
  • it wouldn't surprise me if IIS is having difficulty with that; http.sys usage means the features are implemented by the OS, and lacking "trailer" support is a known problem in http.sys - I *believe* that is now resolved but only on very up to date OS. Perhaps the reality here is "don't use IIS for this"? Is there a reason you want to use IIS here? The gRPC call status code is reported in a trailer, so without full trailer support: gRPC is very unlikely to work well, if at all – Marc Gravell Feb 13 '22 at 09:40
  • You’re right ! The best way I think is to host my grpc as Windows service like this: [link](https://learn.microsoft.com/fr-fr/dotnet/architecture/grpc-for-wcf-developers/self-hosted) – Julien Martin Feb 13 '22 at 15:48

0 Answers0