menu

Questions & Answers

Nest.js GRPC client gets RST_STREAM with code 2 when connecting to server behind NGINX with SSL enabled

We have 2 microservices that need to communicate over GRPC, and they are both written in Nestjs. These two services can easily communicate over IP & Port.

Now, the problem occures when the GRPC server is behind the Nginx proxy with SSL enabled (Nginx without SSL works fine). I tried testing it with grpcurl and the request reaches the GRPC server, however the GRPC client written in Nestjs fails to communicate when SSL is enabled with the following error:

code: 13,
details: 'Received RST_STREAM with code 2 triggered by internal client error: Protocol error'

It is noteworthy to mention that the 2 microservices do not communicate with internal SSL and Nginx sends unencrypted traffic to the GRPC server.

Here is the Nginx configuration:

server {
    server_name grpc.example.com;
    error_log /var/log/nginx/grpc.log info;


    location / {
        grpc_pass grpc://127.0.0.1:5001;
    }

    listen 443 ssl http2;

    ssl_certificate /path/to/cert
    ssl_certificate_key /path/to/cert/key
}

The GRPC client microservice uses this doc and gets the URL like this:

imports: [
  ClientsModule.register([
    {
      name: 'HERO_PACKAGE',
      transport: Transport.GRPC,
      options: {
        url: 'grpc.example.com'
        package: 'hero',
        protoPath: join(__dirname, 'hero/hero.proto'),
      },
    },
  ]),
];

Also tried grpc.example.com:443 as URL and the same happens.

I'd appreciate any clue to help the problem and I'll be happy to provide more details, if required.

Answers(2) :
import { ChannelCredentials } from '@grpc/grpc-js'

imports: [
  ClientsModule.register([
    {
      name: 'HERO_PACKAGE',
      transport: Transport.GRPC,
      options: {
        url: 'grpc.example.com:443'
        package: 'hero',
        protoPath: join(__dirname, 'hero/hero.proto'),
        credentials: ChannelCredentials.createSsl(),
      },
    },
  ]),
];

My guess would be to configure the credentials when you register the ClientsModule in Nest. This is the function I think you should be using.ChannelCredentials.createSsl And you can provide it the rootCerts.

     * Return a new ChannelCredentials instance with a given set of credentials.
     * The resulting instance can be used to construct a Channel that communicates
     * over TLS.
     * @param rootCerts The root certificate data.
     * @param privateKey The client certificate private key, if available.
     * @param certChain The client certificate key chain, if available.
     */
    static createSsl(rootCerts?: Buffer | null, privateKey?: Buffer | null, certChain?: Buffer | null, verifyOptions?: VerifyOptions): ChannelCredentials;
}
Comments:
2023-01-25 00:05:03
Could you elaborate on the parameters? Should I generate a rootCert? Shouldn't it be possible to access the SSL site without generating something? like with HTTPS, or whatever way grpcurl is doing it?