Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't connect to local Node.js secure WebSocketServer

For testing a JavaScript / html5 application, I created a local WebSocketServer with node.js and ws package. I want to use secure websockets (wss) with SSL/TLS.

Key and certificate were create for testing purposes by OpenSSL locally (self signed certificate).

The client just tries to use the native WebSocket object to connect to the (local) https Server:

var ws = new Websocket('wss://localhost:8080');

The Problem is, no browser (Firefox, Chrome, Edge) can connect to the server and they all give me different error messages.

Firefox:

Firefox can not connect to the server at wss: // localhost: 8080 /.

Chrome:

ws_client.js:7 WebSocket connection to 'wss://localhost:8080/' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID

Edge:

SCRIPT12017: SCRIPT12017: WebSocket Error: SECURITY_ERR, Cross zone connection not allowed

I created the certificate and key in OpenSSL (light, newest version) like this:

openssl req -new -x509 -nodes -out server.crt -keyout server.key

(source)

I checked almost every question about this (and similar) topics, e.g. this question, but none of them could provide a solution.

Please do not mark this question as a duplicate, because all similar questions contain slightly different problems!

Server Code:

var fs = require('file-system');

var pkey = fs.readFileSync('server.key', 'utf8');
var crt = fs.readFileSync('server.crt', 'utf8');

var credentials = { key: pkey, cert: crt };
var https = require('https');

var httpsServer = https.createServer(credentials);
httpsServer.listen(8080);

var WebSocketServer = require('ws').Server;

var wss = new WebSocketServer({
    server: httpsServer
});

wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
        console.log('received: %s', message);
        ws.send('reply from server : ' + message)
    });

});

I tried another code as server, but same errors occur:

const WebSocketServer = require('ws').Server; 
var fs = require('file-system');

var ws_cfg = {
    ssl: true,
    port: 8080,
    ssl_key: 'server.key',
    ssl_cert: 'server.crt'
};

var processRequest = function(req, res) {
    console.log('Request received');
};

var httpServ = require('https');

var app = httpServ.createServer({
    key: fs.readFileSync(ws_cfg.ssl_key, 'utf8', (error) => {
        console.log('Error reading file');
    }),
    cert: fs.readFileSync(ws_cfg.ssl_cert, 'utf8',  (error) => {
        console.log('Error reading file');
    })
}, processRequest).listen(ws_cfg.port, function(){
    console.log('Server running');
});



var wss = new WebSocketServer( {server: app, port: 8080, host: 'localhost', domain: 'localhost'} );



wss.on('connection', function (ws) {

    console.log('Connected to a client');

    ws.on('message', function (message) {

        console.log('MSG received: ' + message);

    });

});

There's one more thing. Always, if I add a console.log(wss); to the server Code, the output looks something like this:

WebSocketServer {
  domain: null,
  ...some more stuff...
  ...cert key etc....
  host: null,
  path: null,
  port: null } }

host, domain and port is set to null. I tried everything to set it to localhost:8080, but nothing worked out. I think this could be the source of all Problems, but can't find a way. If anyone knows an answer to this question, I would highly appreciate it.

(Using the insecure 'ws' protocol ('ws://localhost:8080') in order to connect to local node.js http server works, but I want to test the app as realistic as possible and use a secure Connection.)

like image 576
Squareoot Avatar asked Jan 11 '19 17:01

Squareoot


Video Answer


2 Answers

-- This is not an answer, just my workaround --

For anyone having the same problems, here is what I did:

Server Code should be:

const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');

const server = new https.createServer({
  cert: fs.readFileSync('localcert.cert'),   //what ever you're files are called
  key: fs.readFileSync('localkey.key')
});

const wss = new WebSocket.Server({ server });  // !

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('MSG received: %s', message);
  });

  ws.send('Hi to client');
});


server.listen(8080);

Only working in Google Chrome for now, can still not connect in Firefox.

enter chrome://flags/#allow-insecure-localhost in Google Chrome and enable.

like image 192
Squareoot Avatar answered Sep 30 '22 19:09

Squareoot


Try to add the self-signed certificate or the generated CA to be trusted on the system that you are using.

like image 42
Alex Avatar answered Sep 30 '22 19:09

Alex