GRPC Golang Server and NodeJS client. TLS connect failed - node.js

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

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);

Related

Connecting to AWS documentDB using mongoose giving error: 'MongoParseError: option ssl_ca_certs is not supported'

Hello I am just trying to connect to my documentDb using mongoose; hosted on AWS. From my local pc, I am try to do it like:
const URI = 'mongodb://username:npassword#docdb-2022-05-31-18-46-43.cluster-cnyrbefiq91q.eu-west-2.docdb.amazonaws.com:27017/?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'
mongoose.connect(URI, { useNewUrlParser: true , ssl: true});
I am getting the error:
MongoParseError: option ssl_ca_certs is not supported
Can any1 explain to me what I am doing wrong?
DocumentDB supports TLS protocol. It worked for me when I
1/ downloaded the TLS public key using
wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
2/ changed the parameter ssl=true to tls=true in the connection string,
3/ and updated the params to connect() method.
const uri = 'mongodb://<user>:<password>#<clusterAddress>:27017/?tls=true&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'
const client = new MongoClient(uri,{tlsCAFile: `rds-combined-ca-bundle.pem`});
try{
await client.connect();
}
I referred to this DocumentDB documentation.
Try sslCA insted of ssl_ca_certs.

how to get hostname information on TCP via TLS

Below is the code from server file. Trying to get the remoteAdress as host name. but it is giving Remote Address received: :ffff :10.197.0.145 instead of hostname.
async function serverImpl(stream) {
const ctx = {
id: crypto.createHash("sha256").update(stream.getSession())
.digest("hex"), // deriving a unique client id from the tls session identifier
remoteAddress: stream.remoteAddress,
remotePort: stream.remotePort,
servername: stream.servername
}
}
We are using TLS handshake for the Security. Expecting hostname from TCP or using TLS mandatorily. Help us on this

Node.js https server throws 'bad decrypt' error if cert passphrase has $ in it

Any other special char in the passphrase works but not when passphrase has $ in it for some reason, for example passphrase like te$t, the error thrown while starting the server is -
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at Error (native)
at Object.createSecureContext (_tls_common.js:106:19)
at Server (_tls_wrap.js:598:25)
at new Server (https.js:36:14)
at Object.exports.createServer (https.js:56:10)
Here is how the code looks like -
const sslConfig = {
secureOptions: ...,
cert: fileSystem.readFileSync(<cert path>),
key: fileSystem.readFileSync(<key path>),
ciphers: [ ... ].join(':'),
};
if (<has passphrase setup>) {
sslConfig.passphrase = fileSystem.readFileSync(<passphrase path>, { encoding: 'utf8' }),
// console logging the passphrase here shows the correct passphrase
// file path for passphrase file is valid
}
const expressApp = express(); // followed by settings specific to express.js
https.createServer(sslConfig, expressApp).listen(...);
FYI - this is using Node.js v0.12.7, its a legacy app. Upgrading node version is not an option at the moment.
Any pointers?

Mosquitto security error: OpenSSL Error: routines:SSL3_GET_RECORD:wrong version number

I'm trying to store MQTT payloads in a MongoDB database using NodeJS.
When I run my code I get the following error popped up at the Mosquitto server:
1427756032: Socket error on client <unknown>, disconnecting.
1427756033: New connection from 146.175.138.141 on port 8883.
1427756033: OpenSSL Error: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
I'm not the only one facing this error but the proposed solutions on google won't work for me.
I'm working in a Ubuntu14.04 TLS (trusty) server environment. The version of OpenSSL which I used to make my own keys and certificates is:
OpenSSL 1.0.1f 6 Jan 2014
For making these keys I followed the manual of Mosquitto.
The version of nodejs is:
v0.10.25
The configuration file of mosquitto:
port 8883
cafile /etc/keys/ca.crt
certfile /etc/keys/server.crt
keyfile /etc/keys/server.key
tls_version tlsv1
require_certificate true
The nodejs file:
var mqtt=require('mqtt')
var mongodbClient=require('mongodb').MongoClient;
var deviceRoot="demo/device/"
var mqtthost = '146.175.138.141';
var KEY = '/etc/keys/client.key';
var CERT = '/etc/keys/client.crt';
var CAfile = '/etc/keys/ca.crt';
var options = {
host: mqtthost,
port: 8883,
protocolId: 'MQIsdp',
ca: CAfile,
keyPath: KEY,
certPath: CERT,
secureProtocol: 'TLSv1_method',
protocolId: 'MQIsdp',
protocolVersion: 3
};
var collection,client;
mongodbClient.connect("mongodb://localhost:27017/exampleDb", function(err,db){
if(err){return console.dir(err);}
collection=db.collection("test_mqtt");
client=mqtt.connect(options);
client.subscribe("#");
client.publish(deviceRoot, '21');
client.on('message', function(topic,payload){
str = payload.toString();
console.log(str);
var key=topic.replace(deviceRoot,'');
collection.update(
{ _id:key },
{ $push: { events: { event: { value:str, when:new Date() } } } },
{ upsert:true }
)})})
The keys should be working because publishing with the following command is not a problem:
mosquitto_pub -h 146.175.138.141 -p 8883 -t Server -m helloworld --cafile /etc/keys/ca.crt --cert /etc/keys/client.crt --key /etc/keys/client.key --tls-version tlsv1
Any idea what I'm doing wrong?
I can't say for sure, but I suspect that your nodejs connection isn't using TLS. You could verify this by connecting with mosquitto_pub without passing --cafile:
mosquitto_pub -h 146.175.138.141 -p 8883 -t Server -m helloworld
That should produce the same error on the broker that you see with your nodejs connection.
The next step is to remove the tls_version tlsv1 line from your mosquitto configuration and repeat the above command. In that case I would expect to get the following error message on the broker:
Client connection from ::1 failed: error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol.
If you now repeat the test with your nodejs client and get the same error message, it is a fair bet that what I'm saying is correct. I'm afraid I don't know how to fix it though!
An easier test would be to leave your nodejs code unchanged, but set mosquitto to listen without using TLS. If node connects fine then it confirms the situation.
On a related note, if you are using mosquitto 1.4, the best option is to not force a particular version of TLS because the default behaviour is to allow TLS v1.0, v1.1 and v1.2. Earlier versions only provided a single version of TLS per listener.
Using "fs" guarantees access to the files
var fs = require('fs');
var mongodbClient=require('mongodb').MongoClient;
var deviceRoot="demo/device/"
var mqtthost = '146.175.138.141';
var KEY = fs.readFileSync('/etc/keys/client.key');
var CERT = fs.readFileSync('/etc/keys/client.crt');
var CAfile = [fs.readFileSync('/etc/keys/ca.crt')];
var options = {
host: mqtthost,
port: 8883,
protocol: 'mqtts', //also add this
protocolId: 'MQIsdp',
ca: CAfile,
key: KEY,
cert: CERT,
secureProtocol: 'TLSv1_method',
protocolId: 'MQIsdp',
protocolVersion: 3
};

Cannot get node-apn to connect

I'm trying to make a connection to APNs. It simply won't connect. I get variations of:
apn Socket error occurred +609ms { [Error: socket hang up] code: 'ECONNRESET' }
and
apn Connection error occurred before TLS Handshake +0ms
This is for a Passbook pass. Not an app. I'm using Passbook certificates.
My code is:
var apns = require('apn');
var root = process.cwd();
var fs = require('fs');
var options = {
cert: root + '/certs/new/cert.pem', /* Certificate file path */
certData: null, /* String or Buffer containing certificate data, if supplied uses this instead of cert file path */
key: root + '/certs/new/key.pem', /* Key file path */
keyData: null, /* String or Buffer containing key data, as certData */
passphrase: 'secret', /* A passphrase for the Key file */
ca: null, /* String or Buffer of CA data to use for the TLS connection */
gateway: 'gateway.sandbox.push.apple.com',/* gateway address */
port: 2195, /* gateway port */
enhanced: true, /* enable enhanced format */
errorCallback: undefined, /* Callback when error occurs function(err,notification) */
cacheLength: 100 /* Number of notifications to cache for error purposes */
};
var apnsConnection = new apns.Connection(options);
var myDevice = new apns.Device('token');
var note = new apns.Notification();
note.payload = {};
note.device = myDevice;
apnsConnection.sendNotification(note);
It appears that I mixed up my certificates. I'm sure I tried swapping them earlier but obviously didn't.
cert: Your app cert.
key: Apple's WWDR
are you behind a proxy? that could be the issue (at least it is often in my case)
Try the following structure : Read the .cert and .key files manually and set them as certData and keyData property, respectivelly. Here is the core :
var key = root + '/certs/new/key.pem'
var cert = root + '/certs/new/cert.pem';
var certData = fs.readFileSync(cert, encoding='ascii');
var keyData = fs.readFileSync(key, encoding='ascii');
var apnsConnection = new apns.Connection({
certData: certData,
keyData: keyData,
gateway: 'gateway.sandbox.push.apple.com',
port: 2195,
... /* other configs of course */
});

Resources