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.
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;
}
grpcurl
is doing it?