Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSocket server does not work with SSL

I have a working chat application using websockets. I want to go one step further and enable encryption on my connections, however when I switch up the http server with a https one my connections start failing.

I have generated a self-signed certificate that I use on all of my websites (under the same TLD, which implies it is a wildcard certificate). I can confirm it is a valid certificate, so the problem should not be there.

This is what works (unencrypted)

var webSocketServer = require('websocket').server;
var http = require('http');

var server = http.createServer(function() {});
server.listen(webSocketsServerPort, function () {
    log("system", "Server is listening on port " + webSocketsServerPort);
});

var wsServer = new webSocketServer({
    httpServer: server
});

Using this I can now connect to ws://my.domain:port.

This is what does not work

var webSocketServer = require('websocket').server;
var http = require('https');
var fs = require('fs');

var server = http.createServer({
    key: fs.readFileSync("path/to/host.key"),
    cert: fs.readFileSync("path/to/host.pem")
});
server.listen(webSocketsServerPort, function () {
    log("system", "Server is listening on port " + webSocketsServerPort);
});

var wsServer = new webSocketServer({
    httpServer: server
});

With this code the server starts as well, I see the log message "Server is listening.." but when I try to connect at wss://my.domain:port the connection can not be established.

I have added an exception in my browser for the certificate because my client page and websocket server address are under the same tld and sub-domain.

What could be the problem?

like image 950
php_nub_qq Avatar asked Sep 22 '16 17:09

php_nub_qq


People also ask

Does WebSocket use SSL?

The probe supports Secure Sockets Layer (SSL) connections between the probe and WebSocket. SSL connections provide additional security when the probe retrieves alarms from the target systems. To enable SSL connections, obtain any required SSL certificates and Trusted Authority certificates for WebSocket.

Does WebSocket use HTTP or HTTPS?

The WebSocket connection establishment begins with HTTP request upgrading that features a couple of headers such as Connection: Upgrade, Upgrade: WebSocket, Sec-WebSocket- Key, and so on.

Does WebSocket require TLS?

If an encrypted WebSocket connection is used, then the use of Transport Layer Security (TLS) in the WebSocket Secure connection ensures that an HTTP CONNECT command is issued when the browser is configured to use an explicit proxy server.

Is WebSocket more secure than HTTPS?

wss is secure only because it means "WebSocket protocol over https". WebSocket protocol itself is not secure. There is no Secure WebSocket protocol, but there are just "WebSocket protocol over http" and "WebSocket protocol over https". See also this answer.


2 Answers

It is not enough to add the site from which you'd like to connect to the websocket as exception. Go to the site https://my.domain:port (the websocket address) and add the location as exception. (It certainly is a necessary step in Firefox)

Alternatively you could import your certificate in the certificate manager into Authorities.

Edit: I can tell you what works for me.

> openssl genrsa -out key.pem
> openssl req -new -key key.pem -out csr.pem
> openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem

setting the common name as localhost

in main.js

var https = require('https');
var ws = require('websocket').server;
var fs = require('fs');

var options = {
    key:fs.readFileSync('key.pem'),
    cert:fs.readFileSync('cert.pem')
};

var server = https.createServer(options,
    function(req,res){res.writeHeader(200);res.end();});
server.listen(8000);
var wss = new ws({httpServer:server});

wss.on('request',function(req){
    req.on('requestAccepted',function(conn){
        conn.on('message',function(msg){
            conn.send(msg.utf8Data + " received");
        });
    })
    req.accept(null,req.origin);
});

then in the browser(Firefox) at https://localhost:8000 (added cert as exception)

var ws = new WebSocket('wss://localhost:8000/')
ws.onmessage = function(msg){console.log(msg.data)}
ws.send("test")

and received test received.

like image 185
Adam Avatar answered Sep 19 '22 16:09

Adam


Bad practices combined with bad logging habits were the cause of the problem.

On opening a new connection there was a check performed to validate the origin of the request which had hardcoded http:// in there and since I was requesting it from a secure page (https://) the check no longer passed and connections were impossible.

like image 31
php_nub_qq Avatar answered Sep 20 '22 16:09

php_nub_qq