3

Everything works fine when I don't use TLS. But when I do, it does not connect. More details:

I have configured the Golang GRPC server exactly like how this blog says https://bbengfort.github.io/programmer/2017/03/03/secure-grpc.html in Mutual TLS with Certificate Authority section. The server is up and running just fine.

Now I have a client written in NodeJS, trying to send some data through grpc. I have configured the NodeJS like below:

var PROTO_PATH = __dirname + '/protos/log.proto';
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {keepCase: true,
     longs: String,
     enums: String,
     defaults: true,
     oneofs: true
    });
    
var ssl_creds = grpc.credentials.createSsl(fs.readFileSync('ssl/ca.crt'), fs.readFileSync('ssl/client.key'), fs.readFileSync('ssl/client.crt'));

var log_proto = grpc.loadPackageDefinition(packageDefinition).log;
var client = new log_proto.LogData('<IP>:<PORT>',ssl_creds); 

I created the certificates like how it is mentioned here: https://github.com/grpc/grpc/issues/6757. Ofcourse, i did see this comment: https://github.com/grpc/grpc/issues/6757#issuecomment-264617793.

I am still seeing the error when I run NodeJS client:

{ Error: 14 UNAVAILABLE: Connect Failed
at Object.exports.createStatusError (/app/node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (/app/node_modules/grpc/src/client_interceptors.js:1204:28)
at InterceptingListener._callNext (/app/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/app/node_modules/grpc/src/client_interceptors.js:618:8)
at callback (/app/node_modules/grpc/src/client_interceptors.js:845:24)
code: 14,
metadata: Metadata { _internal_repr: {} },
details: 'Connect Failed' }

Certificate details: SSLv3 TLSv1.2

EDIT:

I added env variable GRPC_VERBOSITY as DEBUG and found the following: Peer name <IP> is not in peer certificate

Tjs
  • 843
  • 10
  • 17

1 Answers1

4

So the issue was that the certificate couldn't hold IP address as the hostname. It should have a name and not an IP - fixed it by providing a name and overriding the target name.

const options = {
  'grpc.ssl_target_name_override' : 'simple-host',
  'grpc.default_authority': 'simple-host'
};
var client = new log_proto.LogData('<IP>:<PORT>',ssl_creds,options); 
Tjs
  • 843
  • 10
  • 17
  • does this work with localhost? if we use localhost, do we need to add port number to the simple-host ? – James Tan May 31 '20 at 09:46
  • @JamesTan I would think so, because it needs a hostname. If you can resolve localhost to the desired ip address, you should be good. Also, the certs should use "localhost" and not the ip address – Tjs Jun 02 '20 at 17:16
  • the : need to be the actual destination, which could be localhost, but for the options , we need to specify the tls generated cert domain (simple-host) which could be secure.example.com – James Tan Jun 05 '20 at 05:16
  • have you been able to run against ''domainname:port'' I'm having same issue and I don't know what is happening. I did a go client and it was connect right to the server. I have my server deployed on a VPS accessed through domain name. Is working fine. But with nodejs client is not... – Gudari Feb 07 '23 at 17:23
  • @Gudari ssl_target_name_override is the equivalent of servername in openssl s_client. Some reading on SNI: https://en.wikipedia.org/wiki/Server_Name_Indication – Tjs Mar 31 '23 at 21:00