Setup Server-Server SSL communication using socket.io in node.js - node.js

I'm trying to setup a server to server link using socket.io over ssl connection. This is my example:
/**
* Server
*/
var app = require('express')();
var config = require('./config');
var https = require('https');
var http = require('http');
var fs = require('fs');
var server = https.createServer({key: fs.readFileSync(config.ssl.key), cert: fs.readFileSync(config.ssl.cert), passphrase: config.ssl.passphrase}, app);
//var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(config.port);
app.get('/', function (req, res) {
res.send('Server');
//res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
/**
* Client
*/
var io = require('socket.io-client');
//var socket = io.connect('http://localhost', {port: 8088});
var socket = io.connect('https://localhost', {secure: true, port: 8088});
socket.on('connect', function(){
socket.on('event', function(data){});
socket.on('disconnect', function(){});
});
The code works fine when ran without SSL. I suspect it could be my self-signed certificate not being accepted, but I do not know how to make the client accept it.
Can I accept a self-signed SSL certificate, or is there another approach I can take?

I've had to do things a little differently on the client to get this to work, by manually telling socket.io to use that Agent as well (and the secure: true is implied by https:). Here it is:
// Client
var io = require('socket.io-client');
var https = require('https');
https.globalAgent.options.rejectUnauthorized = false;
var socket = io.connect('https://localhost:3210/', { agent: https.globalAgent });
socket.on('connect', function(){ console.log('connected'); });
This is using socket.io v1.0.2.
Alternatively, I've had success with the following as well, as pointed to here: Socket.io + SSL + self-signed CA certificate gives error when connecting
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
var io = require('socket.io-client');
var socket = io.connect('https://localhost:3210/');
socket.on('connect', function(){ console.log('connected'); });

After some more searching, adding this in the client makes it work:
require('https').globalAgent.options.rejectUnauthorized = false;
/**
* Client
*/
var io = require('socket.io-client');
//var socket = io.connect('http://localhost', {port: 8088});
require('https').globalAgent.options.rejectUnauthorized = false;
var socket = io.connect('https://localhost', {secure: true, port: 8088});
socket.on('connect', function(){
socket.on('event', function(data){});
socket.on('disconnect', function(){});
});

The previous answers didn't do it for me. require('https').globalAgent is always undefined.
Did some seaching and found the rejectUnauthorized parameter in the docs (https://nodejs.org/api/tls.html). Not sure if it's related to SocketIO, but it somehow seems to work with self-signed certificates:
var socket = io.connect('//yourhost:8000', {secure: true, rejectUnauthorized: false})
secure: true might be optional, but I like to enforce it anyhow.

While all the above solutions focus on rejectUnauthorized=false, I'd like to suggest an alternative.
const https = require('https');
const rootCas = require('ssl-root-cas').create();
rootCas.addFile('cert/ca.crt');
https.globalAgent.options.ca = rootCas; // optional
const io = require("socket.io-client");
var socket = io.connect("https://...", { agent: https.globalAgent });

Related

Socketio Websocket on https does not work

I am using socket io to sent some notifications Messages to the web ui, but currently I get this error message:
https://12.123.12.12:3000/socket.io/?EIO=3&transport=polling&t=MMfbmct
0 ()
My socket.js file:
var fs = require('fs');
var app = require('https').createServer({
key: fs.readFileSync('/opt/bitnami/apache2/conf/serverKey.pem'),
cert: fs.readFileSync('/opt/bitnami/apache2/conf/serverCrt.pem')
}, handler);
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
var Redis = require('ioredis');
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {});
// ...
// run server on port 3000
app.listen(3000, function () {
console.log('Server running!');
});
The eventjs file tries to get the data from the socket and do stuff on the ui, this worked a while ago and I do not remember how I declared the socket variable
// I tried following declarations but none work
var socket = io('http://localhost:3000');
var socket = io('http://123.123.123.123:3000'); // sever ip
var socket = io('https://localhost:3000');
var socket = io('https://123.123.123.123:3000'); // sever ip
socket.on('signed-in-channel:App\\Events\\UserSignedIn', (data) => {
// some stuff
});
How do I declare the socket properly?

Node.js, socket.io https connection

Server side code:
var io = require('socket.io').listen(8150);
io.sockets.on('connection', function (socket){
});
Client side code:
var socketIO = io('*.*.*.*:8150');
socketIO.once('connect', function(){
});
On http it's worked on https in same page it not connected.
Searched many examples, but all example for express. I dont create any http server in node.js need only to socket.io work.
When running the client over HTTPS, socket.io is attempting to connect to your server over HTTPS as well. Currently your server is only accepting HTTP connections, the listen(port) function does not support HTTPS.
You'll need to create an HTTPS server and then attach socket.io to it, something like this.
var fs = require('fs');
var options = {
key: fs.readFileSync('certs/privkey.pem'),
cert: fs.readFileSync('certs/fullchain.pem')
};
var app = require('https').createServer(options);
var io = require('socket.io').listen(app);
app.listen(8150);
io.sockets.on('connection', function (socket) {
});
And if you need both HTTP and HTTPS, you can start two servers and attach socket.io to both.
var fs = require('fs');
var options = {
key: fs.readFileSync('certs/privkey.pem'),
cert: fs.readFileSync('certs/fullchain.pem')
};
var httpServer = require('http').createServer();
var httpsServer = require('https').createServer(options);
var ioServer = require('socket.io');
var io = new ioServer();
io.attach(httpServer);
io.attach(httpsServer);
httpServer.listen(8150);
httpsServer.listen(8151);
io.sockets.on('connection', function (socket) {
});
Then on the client side you can determine which port to connect to based on whether the page was accessed over HTTP or HTTPS.
var port = location.protocol === 'https:' ? 8151 : 8150;
var socketIO = io('*.*.*.*:' + port);
socketIO.once('connect', function() {
});
Use letsencrypt with Plesk for a valid SSL certificat.
options = {
key: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/privkey.pem'),
cert: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/cert.pem'),
ca: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/chain.pem'),
rejectUnauthorized: false,
requestCert: true,
agent: false
}

Node.js and Socket.io: on ssl protocol switching is pending forever

When I want to connect to a node server through client, protocol switching is pending forever. Can someone tell me why that's happening?
Here is the server-side code:
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('*******'),
cert: fs.readFileSync('*******'),
passphrase: '*******',
rejectUnauthorized: false
};
var app = https.createServer(options);
var io = require('socket.io').listen(app);
app.listen(3700);
io.sockets.on('connection', function (client) {
client.on('join', function() {
//
});
});
And here's the client-side one:
var baseURL = getBaseURL();
var socketIOPort = 3700;
var socketIOLocation = baseURL + socketIOPort;
var socket = io.connect(socketIOLocation, {secure: true, rejectUnauthorized: false});
function getBaseURL()
{
return (location.protocol + "//" + location.hostname + ":" + location.port);
}
I'm using self-signed certificates on localhost.
Mozilla says the connection is aborted and tries to reconnect, Chrome is saying the status is '101 Switching protocols' and time(latency) is 'Pending'.
getBaseURL() already includes a port (location.port) but then you append to that 3700. Remove the location.port from getBaseURL() and that should fix that particular problem.

Nodejs - Socketio not working with https server, what could be the reason?

I tried debugging using http server, and socket.io worked, however when I try to use https socket.io stopped working
// create server for http and https
//var httpserver = http.createServer(app).listen('3000', '127.0.0.1');
var https_server = https.createServer(options, app).listen('4000', '127.0.0.1');
// let the backend listens to this server
UserServer.listen(https_server);
//UserServer.listen(httpserver);
exports.listen = function(server){
io = socketio.listen(server);
io.sockets.on('connection', function(socket){
console.log("Socket is connected, sweet ");
});
}
When
var httpserver = http.createServer(app).listen('3000', '127.0.0.1');
UserServer.listen(httpserver);
Print out
Socket is connected, sweet "
When
var https_server = https.createServer(options, app).listen('4000', '127.0.0.1');
UserServer.listen(https_server);
There are no output
Here are my set up for https
var express = require('express'),
https = require('https'),
fs = require('fs');
var options = {
key: fs.readFileSync('./key.pem', 'utf8'),
cert: fs.readFileSync('./cert.pem', 'utf8')
};
I was able to display the https page, so I am guessing https setup was not the problem
Any advice would be appreciated, thanks
First of all, you need to run Node.js Server with SSL.
Server.js
var fs = require('fs');
var options = {
key: fs.readFileSync('ssl/private/domain.com.key'),
cert: fs.readFileSync('ssl/certs/domain.com.crt'),
ca: fs.readFileSync('ssl/certs/domain.com.cabundle')
};
// You can do this easily if you are on windows
// var options = { pfx: fs.readFileSync('/home/mydir/secure.pfx'); };
var app = require('https').createServer(options, handler),
io = require('socket.io').listen(app);
//Recommended Production settings
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1); // reduce logging
io.set('flash policy port', 3300); //==> override Flash Policy Port
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
function handler(req, res) {
res.writeHead(200);
res.end("welcome sir!");
};
io.sockets.on('connection', function (socket) {
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
});
app.listen(3300);
Client.js
//socketAddress is server uri ex. https://www.domain.com:3300
var socket = io.connect(socketAddress, {'flash policy port':3300} );
socket.on('connect', function (data) {
//....
});
socket.on('message', function (data) {
//....
});

Secure inter-server communication with node.js

is there any example about secure inter-server communication in node.js?
Is socket.io necessary to realize this or I may use express too?
I would like to realize mutual authentication between two servers.
Thanks to all!!!
This is an example of what i've done; unfortunately it doesn't work...
Server 1
...
var ioc = require('socket.io-client');
var socketc = ioc.connect("https://127.0.0.1:5000", {'force new connection':true, 'secure':true});
...
Server 2
var fs = require('fs');
var https = require('https');
var io = require('socket.io');
var crypto = require('crypto');
// path to private key and certificate
var pathSSH = 'C:\\cert\\';
//array containing private key and certificate
var options = {
key: fs.readFileSync(pathSSH + 'keySatellite.pem'),
cert: fs.readFileSync(pathSSH + 'keySatellite-cert.pem')
};
var port = 5000;
var server = https.createServer(options, function(req, res) {
console.log('Connection with satellite node');
});
var sio = io.listen(server);
// ...listening at port XXXXX
server.listen(port, function(){
console.log("HTTPS server listening on port " + port);
});
sio.sockets.on('connection', function(socket) {
console.log('connected');
socket.disconnect();
});
UPDATE 1
I've noticed that server to server communication works fine if I set a http connection instead of https.

Resources