I'm comfronted with a big problem with socket.io ans NodeJS.
I try to communicate with the NodeJS server through Socket.IO under HTTPS, but when it's time for the server to send a response to the client, it doesn't do anything.
I've checked, but it's not a certificate error ! Key and certificate are valid.
However, without HTTPS, it works perfectly.
Here is my code:
var express = require('express'),
fs = require('fs');
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json', 'utf8')),
options = config.options || {};
var PORT = options.port,
SSL_PORT = options.ssl_port;
var app = express(),
server = require('http').createServer(app);
io = require('socket.io').listen(server);
server.listen(PORT, function()
{
startServer(io);
});
if (options.ssl_key.length && options.ssl_cert.length)
{
var sslOpt = {
key: fs.readFileSync(options.ssl_key, 'utf8'),
cert: fs.readFileSync(options.ssl_cert, 'utf8')
};
var sslServ = require('https').createServer(sslOpt, app),
ioSsl = require('socket.io').listen(sslServ);
sslServ.listen(SSL_PORT, function()
{
startServer(ioSsl);
});
}
function startServer(io)
{
io.on('connection', function(socket)
{
socket.on('msg', function(data)
{
io.emit('clientMsg', 'New message !');
});
}.bind(this));
}
And the client part:
var PORT = 2999,
secured = false,
serverName = 'my-website-url',
completeUrl = 'https://my-website-url.com';
if (completeUrl.substr(0, 5) == 'https')
{
PORT = 3000;
secured = true;
}
var socket = io(serverName + ':' + PORT, {
transports: ['websocket'],
secure: secured
});
socket.emit('msg', 'I send a msg');
I use port 2999 for HTTP and 3000 for HTTPS, when I send a message through the HTTPS server (port 3000), I don't receive the server response, but I receive it on HTTP server (port 2999).
So, under SSL, the server doesn't send a response to clients who are using my HTTPS website.
Related
I have 2 node.js servers running;
1 on port 8000
another on port 8080
The one on port 8080 will be an API, so need to send POST requests to it.(Endpoint: websocket/test).
When I try to do this, a 404 gets returned.
It is sat in a subdirectory(ROOT/webhook), so not sure if that is the reason, or if its the fact that it is on port 8080?
Socket.io is working fine and connects with no issues, I just cant send a POST request to this server.
Here is the server.js file:
//SOCKET.IO Server
const express = require('express');
const app = express();
const port = 8080;
const fs = require('fs');
const http = require('http');
const https = require('https');
const sslKey = 'HIDDEN';
const sslCert = 'HIDDEN';
const options = {
key: fs.readFileSync(sslKey),
cert: fs.readFileSync(sslCert)
};
const httpServer = http.createServer();
const httpsServer = https.createServer(options);
const io = require('socket.io')(httpsServer);
// FOR HTTP
// httpServer.listen(port, () => {
// console.log("Socket.io http server is listening on port: " + port)
// console.log(__dirname + '/key.pem');
// })
// FOR HTTPS
httpsServer.listen(port, () => {
console.log("Socket.io https server is listening on port: " + port);
})
io.on('connection', function(socket){
console.log('made socket connection', socket.id);
socket.emit('welcome', 'Hiya! Welcome');
app.post('/websocket/test', function() {
console.log('webhook received');
io.emit('webhook', 'You have received a webhook!');
});
});
You almost got everything right. Except you aren't telling your express application to start listening for requests. By just changing this code:
const httpsServer = https.createServer(options);
to this:
const httpsServer = https.createServer(options, app);
Your server should work.
My code is hosted on the GitHub Pages. I'm trying to connect client to my computer's Node.JS server by IP, but connection says an error ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
That's my server code:
var app = require('express')();
var server = require('https').createServer(app);
var io = require('socket.io')(server);
app.set('port', process.env.PORT || 8080);
app.set('host', process.env.HOST || '0.0.0.0');
server.listen(app.get('port'), app.get('host'), () => {
console.log("Express server listening IP: " + app.get('host'));
});
io.on('connection', socket => {
socket.on('sayHi', data => {
console.log(data.message);
});
});
And this is client side:
const socket = io.connect('https://myPublicIP:8080');
socket.emit('sayHi', { message: 'Hello world' });
That error happen because you using HTTPS for running SocketIO Server.
So we have two way for resolve this issue:
Change require('https') to require('http')
Import your Certificate SSL files when createServer following this example source code
const privateKey = fs.readFileSync(process.env.PRIVATE_KEY, 'utf8')
const certificate = fs.readFileSync(process.env.CERTIFICATE, 'utf8')
const credentials = {
key: privateKey,
cert: certificate,
passphrase: process.env.PASSPHRASE
}
var server = require('https').createServer(credentials, app);
Hope this can help you!
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
}
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.
Server:
// Load libraries
var https = require('https');
var fs = require('fs');
var socketio = require('socket.io');
// The server options
var srvAddress = '123.123.123.123';
var srvPort = 8888;
var srvOptions = {
key: fs.readFileSync('ssl/cert.key'),
cert: fs.readFileSync('ssl/cert.crt'),
ca: fs.readFileSync('ssl/cert-ca.crt')
};
// Create a Basic server and response
var app = https.createServer(srvOptions, function(req, res) {
res.writeHead(200);
res.end('Online...');
});
// Create the Socket.io Server over the HTTPS Server
var io = socketio.listen(app, srvAddress);
// Now listen in the specified Port
app.listen(srvPort, srvAddress);
Client:
var socket = require("socket.io-client").connect('https://123.123.123.123:8888', {secure: true});
But client don't connect to server. I tried http instead of https, but the same result.
Server works fine. Without ssl certificate connection works. When try to open via web, then all works too.