node.js socket io https - node.js

I'm trying to establish a WebSocket (with node.js/socket.io) on an
HTTPS protocol. But the client still keeps on polling and could not find the server although the server seems fine and listens.
This is what I have done so far. Could you see anything wrong with it?
My assumption is there is something not right with the certificates which I am using. I encrypted the server with plesk "lets encrypt" and took the certificates from this procedure is that right?
---- server side ----
var fs = require('fs');
var express = require('/opt/plesk/node/7/bin/node_modules/express');
var https = require('https');
var app = express();
var server = https.createServer({
key: fs.readFileSync('file.pem'),
cert: fs.readFileSync('file.crt')
},app);
var io = require('/opt/plesk/node/7/bin/node_modules/socket.io').listen(server);
server.listen(8080);
---- client side -----
var socket = io('/', {rejectUnauthorized: false, secure:true});
This is what the client gives me continuously:
https://foo.de:8080/socket.io/?EIO=3&transport=polling&t=MF9zjE6

Since you don't tell what error message you get it's a little hard to identify your problem. Perhaps you should try getting your socket to work and then afterwards try to implement https.
Maybe you should try and simplify it a bit like this.
Server:
var express = require('express')
var app = express()
var server = require('http').Server(app)
var io = require('socket.io')(server)
server.listen(8080);
Client:
var socket = io();
This piece of code should create your socket and your express app. Then you could try and change http to https and it should work aswell.

Related

Node, Express, Socket.io Unable to Connect To Server

I have made a node server with with express and sockets io. It is a simple chat application that would be an addon, to my existing project on my website.
I am having this issue where I am unable to connect to the server from the client to be able to use the chat application.
Error: polling-xhr.js:202 GET https://128.127.106.17:6379/socket.io/?EIO=4&transport=polling&t=Nixndgr net::ERR_CONNECTION_TIMED_OUT
SERVER
const fs = require("fs");
const path = require('path');
const express = require('express');
const app = express();
const http = require('http');
const options = {
key: fs.readFileSync(PATH_TO_KEY),
cert: fs.readFileSync(PATH_TO_CERT),
}
const server = http.createServer(app);
const cookie = require('cookie');
const { Server } = require("socket.io");
const io = new Server(server);
CLIENT
var socket = io(HOSTNAME, {'transports': ['websocket', 'polling']});
With these settings it works perfectly fine on my local environment, but with the actually website I have trouble getting it connected.
The few things I have attempted
I tried adding the ssl options , "const server = http.createServer(options, app);"
I played around with CORS as well and different settings.
Found this https://docs.cpanel.net/knowledge-base/web-services/how-to-install-a-node.js-application/
And I found that the server was running and I would get the hello world but still not able to connect to it and starting to get stumped and running out of resources/possible solutions.

Socket.io server with https

Here is my socket.io server.js file.
var fs = require('fs');
var https = require('https');
var httpsServer = https.createServer({
key:fs.readFileSync("/etc/nginx/ssl/example.com/server.key").toString(),
cert:fs.readFileSync("/etc/nginx/ssl/example.com/server.crt").toString(),
});
httpsServer.listen(9091);
io = require('socket.io').listen(httpsServer);
I run node server.js on server and I tried to go to here:
https://example.com:9091/socket.io/socket.io.js
But it didn't work. (This site can't be reached)
When I did it like as following with http, it worked well.
(http://example.com:9091/socket.io/socket.io.js)
var http = require('http');
var httpServer = http.createServer();
httpServer.listen(9091);
io = require('socket.io').listen(httpServer);
I know we can configure it with nginx reverse proxy too but
what I want to is to setup it without nginx reverse proxy.
Can anyone help me? Thanks in advance.

How to get certificate file from server?

When i dont get any proper answer so i asked this question that i created a chat app for my site using socket.io and node.js my site is on https server it's not working it's giving me error
GET https://example.com:3000/socket.io/?EIO=3&transport=polling&t=1507034613131-2 net::ERR_INSECURE_RESPONSE
CODE IS HERE
var app = require('express')();
var fs = require('fs');
var path = require('path');
var forceSsl = require('express-force-ssl');
app.use(forceSsl);
var options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
var server = require('https').createServer(options, app).listen(3000,function(){
console.log("Https server started on port 3000");
});
var io = require('socket.io').listen(server);
i find above code for https authentication so how can i get these files i have already installed ssl.
i think you can check in your cpanel there is ssl manager which is cpanel service so you can get from there after that you can use in your https nodejs service

Use both http and https for socket.io

I am trying to make socket.io work both on http and https connections, but it seems that with my current configuration it can work only on one of them.
With the below config options it can access my application through https, but when trying to access it through http it cannot connect and I receive errors:
var app = express()
, http= require('http').createServer(app)
, https = require('https').createServer(options, app)
, io = require('socket.io').listen(https, { log: false })
And later I have this:
http.listen(80, serverAddress);
https.listen(443, serverAddress);
On client side I have this:
<script src='/socket.io/socket.io.js'></script>
var socket = io.connect('https://<%= serverAddress %>', {secure: true, 'sync disconnect on unload' : true});
Of course if I switch the http with the https options on the .listen and .connect functions of the server and the client respectively I am having the reverse results, e.g. it can access through http and not through https.
How is it possible to achieve this? I need it mostly because it is regarding a Facebook app, so it must provide both http and https connection options according to Facebook's rules.
Edit: In case it helps about the problem, the error I am receiving is this:
Failed to load resource: the server responded with a status of 404 (Not Found) http://DOMAIN/socket.io/socket.io.js
And because of this I get others such as:
Uncaught ReferenceError: io is not defined
I believe the problem is in your way of setting up socket.io on the server side and on the client.
Here's how I made it work (just for you).
Server:
var debug = require('debug')('httpssetuid');
var app = require('../app');
var http = require('http');
var https = require('https');
var fs = require('fs');
var exec = require('child_process').exec;
var EventEmitter = require('events').EventEmitter;
var ioServer = require('socket.io');
var startupItems = [];
startupItems.httpServerReady = false;
startupItems.httpsServerReady = false;
var ee = new EventEmitter();
ee.on('ready', function(arg) {
startupItems[arg] = true;
if (startupItems.httpServerReady && startupItems.httpsServerReady) {
var id = exec('id -u ' + process.env.SUDO_UID, function(error, stdout, stderr) {
if(error || stderr) throw new Error(error || stderr);
var uid = parseInt(stdout);
process.setuid(uid);
console.log('de-escalated privileges. now running as %d', uid);
setInterval(function cb(){
var rnd = Math.random();
console.log('emitting update: %d', rnd);
io.emit('update', rnd);
}, 5000);
});
};
});
app.set('http_port', process.env.PORT || 80);
app.set('https_port', process.env.HTTPS_PORT || 443);
var httpServer = http.createServer(app);
var opts = {
pfx: fs.readFileSync('httpssetuid.pfx')
};
var httpsServer = https.createServer(opts, app);
var io = new ioServer();
httpServer.listen(app.get('http_port'), function(){
console.log('httpServer listening on port %d', app.get('http_port'));
ee.emit('ready', 'httpServerReady');
});
httpsServer.listen(app.get('https_port'), function(){
console.log('httpsServer listening on port %d', app.get('https_port'));
ee.emit('ready', 'httpsServerReady');
});
io.attach(httpServer);
io.attach(httpsServer);
io.on('connection', function(socket){
console.log('socket connected: %s', socket.id);
});
Client:
script(src='/socket.io/socket.io.js')
script.
var socket = io();
socket.on('update', function(update){
document.getElementById('update').innerHTML = update;
});
Here are the key points for the server:
require socket.io but don't call it's listen method yet (assuming http and https are already required). Instead, just keep the reference. (var ioServer = require('socket.io'))
create your http & https server
create a new instance of ioServer
bind your http and https servers (.listen)
attach http&https server instances to the io instance. (.listen is an alias for .attach)
setup io events.
And the client (jade syntax but you get the idea):
include socket.io script tag
call io and capture reference
setup your event handlers
On the client you don't need to call io.connect(). Furthermore, I'm not sure about your options there. It looks like you have a typo (, ,) and I can't find any reference to secure: true in the 1.0 documentation.
Arguably, the node.js server object for HTTP and HTTPS ought to be given the capability to listen on an arbitrary number of ports and interfaces, with and without SSL, but this does not seem to currently be implemented. (I was able to get one server to listen on two ports by passing a second server that had no request listener as the "handle" argument to server.listen(handle, [callback]) interface, in addition to server.listen(port, [hostname], [backlog], [callback]), but it did not work with SSL/non-SSL servers mixed.)
The stunnel workaround already mentioned is of course a viable option, but if it is not desirable to install a separate piece of software (to avoid non-node.js dependencies), the same tunneling can be achieved natively in node.js instead (assuming HTTP on port 80 and HTTPS on port 443):
var fs = require('fs');
var net = require('net');
var tls = require('tls');
var sslOptions = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
tls.createServer(sslOptions, function (cleartextStream) {
var cleartextRequest = net.connect({
port: 80,
host: '127.0.0.1'
}, function () {
cleartextStream.pipe(cleartextRequest);
cleartextRequest.pipe(cleartextStream);
});
}).listen(443);
This will have the same effect as using stunnel. In other words, it will avoid the need for two separate socket.io server instances, while also making the node.js "https" module redundant.
I have done something similar and it required two socket.io instances. Something like this:
var express = require('express');
var oneServer = express.createServer();
var anotherServer = express.createServer();
var io = require('socket.io');
var oneIo = io.listen(oneServer);
var anotherIo = io.listen(anotherServer);
Of course that you will need to inject messages twice: for both socket.io instances.
A good option is delegate SSL handling to stunnel and forget about SSL in your code.
I solved the problems using a different approach, I configured the server to support only unencrypted transport, and used stunnel for the https support.
For information on how to install stunnel you can check this post.
Then, used the following con configuration:
#/etc/stunnel/stunnel.conf
cert = /var/www/node/ssl/encryption.pem
[node]
accept = 443
connect = 80
Finally, I used the following to connect the clients:
var socket = that.socket = io.connect('//'+server);
This will auto detect the browser scheme and connect using http/https accordingly.
I am guessing Cross origin requests could be the reason why you are getting errors. Change in protocol is considered change in domain. So for page served via http server accessing https server (websocket server attached to it) may throw security errors. See an example here on how to enable CORS in express.
Also you should change * in the header to http://serverAddress , https://serverAddress. Allowing all sites is not a good idea, use it for testing.
The same is true if you are trying to AJAX between your http and https servers. Please post the errors, just to be sure about it.

Connect2 and Socket.io

I'm trying to get connect and socket.io to work together nicely and simply. I have the following code on server side:
var connect = require('connect'),
io = require('socket.io');
var app = connect().use(connect.logger('dev'));
var sio = io.listen(app);
app.listen(8000);
when i open http://localhost:8000/socket.io/socket.io.js i'm get error:
Cannot GET /socket.io/socket.io.js
And Socket.IO not work, i'm trying copy file and load from another location, but socket.io requests do not reach the server
SOLUTION
if anyone comes to this issue, you need to wrap the connect/express app in a node http.Server. The app.listen() method is a convenience method for this and returns the server:
var io = require('socket.io');
var app = connect();
var server = app.listen(3000);
io.listen(server);
or the following is equivalent:
var io = require('socket.io');
var http = require('http');
var app = connect();
var server = http.createServer(app);
server.listen(3000);
io.listen(server);

Resources