Securing Node Redis - node.js

I'm trying to secure the Node Redis IPC server to use a private/public key. I've followed this tutorial which uses stunnel which wraps the tunnel used by Redis under a SSL layer.
The example is not for Node, but it does secure the connection, and I only can connect to the server if I include the certification in my config file, otherwise the connection is reseted.
However, I cannot replicate this with NodeJS. On my server computer, I have:
var redis = require('redis');
var client = redis.createClient();
client.auth('myPassword');
client.publish('instances', 'start');
And my on my client computer I have:
var redis = require('redis');
var client = redis.createClient();
client.auth('myPassword');
client.subscribe('instances');
client.on('message', function (channel, message) {
console.log("Got message " + message + " from channel " + channel);
})
But, the two devices communicate whether or not I include the certification in my stunnel config file. How can I secure this connection up?
Cheers

You can do this by passing in the tls configuration when creating the client like so
var redis = require("redis");
var client = redis.createClient(6380,'location.of.server', {auth_pass: 'password', tls: {servername: 'location.of.server'}});

I have also searched for this . But redis doesn't need any ssl since in runs only on verified private networks. The only way to provide security using stunnel. Since we can enable password by using AUTH command. In redis they have provided a password generator which is named as GPG key. Which generated a 2048 length key which will provide security. I think my answer is relevant.

Related

Node.js Connecting to redis cluster

There are tons of examples and resources for connecting to a redis "server" but not to a redis "cluster".
What I currently have is:
const redis = require("redis");
const client = redis.createClient({
port : 6379, // replace with your port
host : '10.0.0.100', // replace with your hostanme or IP address
password : 'Notforyou', // replace with your password
// optional, if using SSL
// use `fs.readFile[Sync]` or another method to bring these values in
tls : {
key : stringValueOfKeyFile,
cert : stringValueOfCertFile,
ca : [ stringValueOfCaCertFile ]
}
});
But this is for a single redis server not a cluster. How would I go about connecting to my cluster?
The Readme tab in redis npm package has this link(Clustering Guide) explaining how to connect to redis cluster with node under heading 'Clustering'. It's very simple, create a cluster instead of creating client and configure the nodes url as given in this example
Check out this library ioredis
I think that this will help you with your issue.

Node.js and Socket.io - Certificate is invalid

I'm having trouble connecting my chat application to Node.js server running on Ubuntu 16.04. The problem seems to be the ssl certificate which have been generated using 'letsencrypt'.
I have successfully connected to my Node.js server using a openssl certificate - this however only works in my Chrome browser.
Here is my code for the Node.js part.:
let fs = require('fs');
let https = require('https');
var options = {
key: fs.readFileSync('./file.pem'),
cert: fs.readFileSync('./file.crt')
};
let server = https.createServer(options);
let io = require('socket.io')(server);
let Redis = require('ioredis');
let redis = new Redis();
redis.subscribe('all-chat');
redis.on('message', function (channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
server.listen(3201);
The error code I'm getting from my browser is.:
net::ERR_INSECURE_RESPONSE
My guess is that for some odd reason the certificates I have obtained is not following a standard of some sorts, so the browser discards the response.
For what I can gather around the web about this problem - the solution should be using a certificate from 'letsencrypt' and/or multiple variations of.:
var options = { ... };
And I do believe I have tried every possible combination.
If I open my website in two windows, one in Edge and one in Chrome, I can succesfully send a message from Edge to Chrome - the message will however not be shown in Edge as it should.
Thanks in advance for any detail that may put me back on track!
The answer was rather simple. To be sure you can use your certificate you can use the diagnostic tool found on https://www.digicert.com/help/.
For the connection from client to my Node.js end I stated the IP on the client side - and that will not do when using a certificate which have been created with the public domain. So I changed the IP on the client side from the IP to the public domain and it worked!

assign HTTPS to node.js socket.io

i want to create HTTPS server to my node.js socket.io server,
did it with self sign certification, using this code
var fs = require( 'fs' );
var app = require('express')();
var https = require('https');
var server = https.createServer({
key: fs.readFileSync('C:/ssl/ia.key'),
cert: fs.readFileSync('C:/ssl/ia.crt'),
requestCert: false,
rejectUnauthorized: false
},app);
server.listen(8888);
but when purchasing real one i only get .crt file, how to secure my node app using it on windows server?
Short answer: no private key - no way.
You need a private key that was used to purchase the certificate.
Or you can use letsencrypt-express:
Free SSL and managed or automatic HTTPS for node.js with Express, Koa,
Connect, Hapi, and all other middleware systems.
https://www.npmjs.com/package/letsencrypt-express
Found the answer, i had to do a CSR from my server using OPENSSL batch, in that case it will create CSR and the private KEY, buying SSL using the CSR will give me the CRT
and i will use the generated key from the OPENSSL.

node.js mqtt client using TLS

I am trying to implement a node.js mqtt client with TLS using the package below;
https://www.npmjs.com/package/mqtt#client
The code for running mqtt client without TLS is as follows;
var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://test.mosquitto.org')
client.on('connect', function () {
client.subscribe('presence')
client.publish('presence', 'Hello mqtt')
})
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
client.end()
})
How should the above code be modified to use TLS on the mqtt client?
The mosca MQTT broker was run as a stand-alone using the command below;
mosca --key ./tls-key.pem --cert ./tls-cert.pem --http-port 3000 --http-bundle --http-static ./ | pino
Should be enough to change the protocol part of the URL to mqtts://
mqtts://test.mosquitto.org.
Self-signed certificates
You can pass the following option to the connect function when using self-signed certificates (for testing purposes only):
mqtt.connect('mqtts://test.mosquitto.org', {
rejectUnauthorized: false
});
You need to provide the mqtt.connect() function with an options object which includes the CA certificate to use to verify the connection.
The options object needs to include a ca key that points to the certificate used to sign the brokers certificate. As it looks like your using a self signed certificate this will be the same one used by the broker.
The ca key is described here
Or you can allow any certificate with the rejectUnauthorized key as mentioned in #notion's answer. But that makes it impossible to detect if somebody is impersonating your broker

How to verify that a connection is actually TLS secured?

I have created a TLS server and an appropriate TLS client in Node.js. Obviously they both work with each other, but I would like to verify it.
Basically, I think of something such as inspecting the connection, or manually connecting to the server and inspecting what it sends, or something like that ...
The relevant code of the server is:
var tlsOptions = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('server.pem')
};
tls.createServer(tlsOptions, function (tlsConnection) {
var d = dnode({
// [...]
});
tlsConnection.pipe(d).pipe(tlsConnection);
}).listen(3000);
The appropriate client code is:
var d = dnode();
d.on('remote', function (remote) {
// [...]
});
var tlsConnection = tls.connect({
host: '192.168.178.31',
port: 3000
});
tlsConnection.pipe(d).pipe(tlsConnection);
How could I do that?
Wireshark will tell you if the data is TLS encrypted, but it will not tell you if the connection is actually secure against Man-in-the-Middle attacks. For this, you need to test if your client refuses to connect to a server that provides a certificate not signed by a trusted CA, a certificate only valid for a different host name, a certificate not valid anymore, a revoked certificate, ...
If your server.pem is not a certificate from a real/trusted CA, and your client doesn't refuse to connect to the server (and you didn't explicitly provide server.pem to the client), then your client is very probably insecure. Given that you are connecting to an IP, not a host name, no trusted CA should have issued a certificate for it, so I assume you use a selfsigned one and are vulnerable. You probably need to specify rejectUnauthorized when connect()ing. (Rant: As this is a pretty common mistake, I think it is extremely irresponsible to make no verification the default.)
Basically, I think of something such as inspecting the connection, or manually connecting to the server and inspecting what it sends, or something like that ...
You can use tools such as Wireshark to see the data they are transmitting.

Resources