0

I made two small console applications in .NET 6 (ASP.NET Core 6), one that implements a gRPC service, and one that uses a gRPC client to make calls to that service.

The original appsettings.json for the server looked like this:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    },
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:50000"
      }
    }
  }
}

and the client would setup its channel using this code

using var channel = GrpcChannel.ForAddress("https://localhost:50000");

This works perfectly fine using .NET self-signed developer certificates (created then trusted via .NET SDK commands dotnet dev-certs https [--trust]) when both the server and the client run on the same machine.


I now want to move the server to a different machine. That machine has a known, fixed local IP address such as 192.168.0.120. But I'm having trouble to sort out what I need to do regarding the certificates so that the SSL connection can actually be established.

What I "naively" did was to change the appsettings.json into

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    },
    "Endpoints": {
      "Https": {
        "Url": "https://0.0.0.0:50000"
      }
    }
  }
}

and then copy the compiled program over to the other machine. Without the dev-certs added on that machine, the server won't event start up. Unfortunately the error message only contains information on how to use dev-certs, not how to deploy using proper certificates. But I gave dev-certs a try anyway, and sure enough, with that created and trusted, the launch triggered a Windows Firewall dialog whether I want to allow communication for the server program, which I confirmed. The server then started up and showed Now listening on: https://0.0.0.0:50000. This seems to be about right, I guess?

I then went ahead and changed the code that opens the channel into

using var channel = GrpcChannel.ForAddress("https://192.168.0.120:50000");

and launched the program on my computer. This gives an exception the first time I try to use a client created using that channel:

Grpc.Core.RpcException
HResult=0x80131500
Message = 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, RemoteCertificateChainErrors",
[DebugException (identical text) and callstack elided]

I'm not entirely sure, but what I think I understand from the error messages is that the dev-certs are only for the name "localhost" which is resolved to the loop-back adapter, and the certificate is not for the machine that "localhost" was in the moment of certificate creation. So doing everything on the same machine is fine as long as everything uses "localhost" as host name for bind and connect, because there is a certificate for a machine called "localhost". But when I go to IP addresses it all falls apart, because the machine the server is running on has no matching certificate.

I tried to find information on how to create a certificate for the server, but I'm stuck in a mass of information and can't quite figure out what I even need to do let alone how to do that then.

Here's all the links to the sites I found so far:

  • Enforce HTTPS in ASP.NET Core ‒ This is the page the error message refers me to when I try to start the server without dev-certs created. The article seems to be only about the dev-certs, which works for "localhost" scenarios but not for remote machines, as it seems.
  • Hosting ASP.NET Core images with Docker Compose over HTTPS ‒ firstly, I don't want to use Docker, secondly it says you'd need a certificate for a domain, not an IP address.
  • Self-signed certificate for device with local IP ‒ Since the one above suggested IP might be impossible, I searched and found this SO question. One answer says "no you cannot create a certificate for an IP", and the other answer says "yes you can create a certificate for an IP". Sadly (as many articles, posts, and answers around certificate creation), the second answer uses UNIX commands, and the "config" and "key" stuff is already way over my head to translate into Windows.
  • Configure endpoints ‒ This article shows plentiful bits about certificate configurations, however they all seem to be like "this is just development stuff and not how you'd actually do it". But frankly, I'm not even worried about putting a password into the code at the moment, it's my local network and I just want to get it to run at all for the moment.
  • Generate Self-Signed Certificates ‒ I thought I could work through this and see if that worked, but it's super quick to jump on Dockerfiles as well and lost me right there because I don't use Docker at all in my setup, and I'm having a hard time telling apart the things they do for Docker from the things they do for the certificate setup.

I am lost. At this point I'm not even sure establishing a machine-to-machine gRPC connection over https is even possible without a proper host names per machine and a DNS, even within my local network.

I might actually be able to assign a name to IP if needed, but honestly I'd prefer to stick to using IPs in the code if possible, because it's way more flexible for moving the server program to other machines and networks without setting up DNS for all machines all the time.

LWChris
  • 3,320
  • 1
  • 22
  • 39
  • I just found and added [a temporary workaround](https://stackoverflow.com/a/58191947/1843468) to make gRPC accept all certificates, just so I can continue working at all. But I still wonder how you can setup certificates correctly so that it works without that hack. – LWChris Jul 29 '23 at 16:10

0 Answers0