ChannelOptions doesn't work well in client tls connection
See original GitHub issueProblem description
In TLS connection scenaio, the client implemented by nodejs(which depends on grpc-js) cannot connect to server.
I got the error messages from c++ server ssl_transport_security.cc:1847] No match found for server name: localhost.
, and no error message from nodejs server.
The certs is signed with a special dns name, and the client uses localhost
to connect. So, I use ChannelOptions
in node/ChannelArguments
in c++ to define the grpc.default_authority
. In this way, the c++ client(actually, including java/kotlin/csharp/python/rust/go) works well.
I’m not sure if it’s an issue or my mistake. Please help to check:
let address = connectTo + ":" + port
let secure = process.env.GRPC_HELLO_SECURE
if (typeof secure !== 'undefined' && secure !== null) {
logger.info("Connect With TLS(%s)", port)
let rootCertContent = fs.readFileSync(certChain);
let privateKeyContent = fs.readFileSync(certKey);
let certChainContent = fs.readFileSync(certChain);
const credentials = grpc.credentials.createSsl(rootCertContent, privateKeyContent, certChainContent);
//https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
const channelOptions = {
'grpc.default_authority': serverName
}
return new services.LandingServiceClient(address, credentials, channelOptions)
} else {
logger.info("Connect With InSecure(%s)", port)
return new services.LandingServiceClient(address, grpc.credentials.createInsecure())
}
const string &port = Utils::getBackendPort();
const basic_string<char, char_traits<char>, allocator<char>> &target = Utils::getBackend() + ":" + port;
const string &secure = Utils::getSecure();
if (!secure.empty() && secure == "Y") {
grpc::SslCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = Connection::getFileContent(certChain);
ssl_opts.pem_private_key = Connection::getFileContent(certKey);
ssl_opts.pem_cert_chain = Connection::getFileContent(certChain);
grpc::ChannelArguments channel_args;
channel_args.SetString("grpc.default_authority", serverName);
LOG(INFO) << "Connect with TLS(" << port << ")";
return grpc::CreateCustomChannel(target, grpc::SslCredentials(ssl_opts), channel_args);
} else {
LOG(INFO) << "Connect with InSecure(" << port << ")";
return grpc::CreateChannel(target, grpc::InsecureChannelCredentials());
}
Reproduction steps
Clone and go to this folder: https://github.com/feuyeux/hello-grpc/tree/main/grpc/hello-grpc-nodejs
Run the below scripts on two terminals:
export GRPC_HELLO_SECURE="Y"
sh server_start.sh
export GRPC_HELLO_SECURE="Y"
sh client_start.sh
Environment
- OS name, version and architecture: macOS 11.6
- Node version: v16.13.0 and v17.0.1(need to remove sleep lib)
- Node installation method: brew
- Package name and version: package.json
Additional context
Issue Analytics
- State:
- Created 2 years ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
I also want to mention that I will be off for the rest of the year. I will continue to look into this in January, but I do not expect to respond again until then.
I managed to run your Node example. When I have the Node client communicate with the Node server, the server does not report any error like the one you mentioned, but the client actually gets an error that says “unsupported certificate purpose”. I can’t tell why that is happening in this example, but from my research that seems to be some kind of problem with the “X509v3 Extended Key Usage” field in the certificate.
I am still trying to get your C++ example to build, so I have not tested the Node client with the C++ server yet, but one suggestion I have is to not use client authentication (don’t provide the certificate or key to
credentials.createSsl
) just to simplify the TLS interaction that we are trying to debug. Does that still result in the same error? In addition, can you run the client with the environment variablesGRPC_TRACE=subchannel
andGRPC_VERBOSITY=DEBUG
and look for a line that starts like this:We know what error the server sees, but that line should provide more information about what error the client is seeing when the connection fails.