Secure websockets with self-signed certificate

Self-signed certificates are rejected by Chrome since v19 (http://crbug.com/53836). If you try to connect to a wss URL which uses a self-signed certificate, then the request is silently aborted.
To allow self-signed certificates to be used, start Chrome with the --ignore-certificate-errors flag, e,g:

chromium --user-data-dir=/tmp/whatever --ignore-certificate-errors

To my knowledge, there is no way to get Firefox to accept your self-signed certificate for wss. So, just use ws:// for testing in Firefox. If you're testing your web app over https, then you have to toggle a preference to allow connections to (insecure) ws:// URLs:

  1. Visit about:config
  2. Set network.websocket.allowInsecureFromHTTPS to true

Yep, that's the current behavior of Chrome but I wouldn't expect it to continue to be the policy in the future. In firefox 4 (if you enable WebSockets in about:config) you will get a warning about the certificate. To approve the certificate you may also have to enter the WebSockets URL in the browser (substitute wss with https) and approve it there first (since the warning from the WebSockets connection about the self-signed cert may not give you the opportunity to approve it).

I would expect all browsers to converge on the correct behavior which is to throw up a warning dialog that allows the self-signed certificate to be approved.


I got it working by following this:

https://github.com/einaros/ws/blob/master/test/WebSocketServer.test.js#L514

First generate your self-signed certs:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 100 -nodes

Then create your httpsServer from an express app using node's built-in https server:

var privateKey  = fs.readFileSync('sslcert/key.pem', 'utf8');
var certificate = fs.readFileSync('sslcert/cert.pem', 'utf8');

var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();

//... bunch of other express stuff here ...

//pass in your express app and credentials to create an https server
var httpsServer = https.createServer(credentials, app);
httpsServer.listen(8443);

Then setup your websocket server (ironically this will use the same port as the http server, I didn't know this but I guess protocols can share ports? -- this had me going for awhile).

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('something');
});

Now browse to https://0.0.0.0:8443 server and accept the self-signed cert in Chrome. Then websockets should now work isnide the browser.

Open a chrome devtools console and type:

var ws = new WebSocket('wss://0.0.0.0:8443');
ws.send('foo');

....or whatever host:port you used for httpsServer, the key here is you're using wss:// protocol

In your node express web server you should see a message logged to the console. Start the server with node ./server.js

http://www.chovy.com/web-development/self-signed-certs-with-secure-websockets-in-node-js/


When you are using wscat, then you can use -n flag(-n, --no-check: Do not check for unauthorized certificates)

wscat -c "wss://30.90.212.255:8000" -n