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?
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.
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.
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.
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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With