Secure websockets with self-signed certificate
Asked Answered
F

5

34

I want to use secure Websockets to improve the success rate. I don't need the encryption.

Am I suppose to see a warning when using secure Websockets (wss://example.com) with a self-signed certificate? I tried it with Chrome 10 and I don't see a warning and it doesn't ask me to accept the certificate. It just works.

Is this a bug in chrome or the expected behavior? Will I be able to use self-signed certificates in the future?

Thanks

Fancher answered 15/3, 2011 at 13:19 Comment(0)
G
22

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.

Gallivant answered 15/3, 2011 at 14:31 Comment(6)
Do you know if the next Websockets draft improves the success rate of non-secure Websockets?Fancher
Probably not. The main changes are to the framing of the data (length based instead of delimiter based) and data from the client to the server is not masked to address the misbehaving intermediary problem. Port 80 and 443 are still the standard WebSockets ports and the handshake is still HTTP-like. What is the problem you are seeing causing WebSockets not to connect for you?Gallivant
I'm referring to ietf.org/mail-archive/web/hybi/current/msg01605.html. It says that port 80 has only 63% success rate while port 443 has 95% success rate. I'm also forced to use port 443 or 8080 because I'm using nginx as a proxy and it doesn't support HTTP 1.1. Port 443 requires a certificate which complicates stuff and maybe a little overhead. I'm not sure how many users have port 8080 blocked.Fancher
Those success rates don't apply to local connections, they are for traversing the Internet to and from arbitrary locations and they aren't measuring temperamental problems (it either works or it doesn't). The port 80 issues are because there can be many intermediaries that interfere with what is perceived as normal HTTP traffic. You won't get higher success on your local network with using wss over port 443. Very few users will have outgoing 8080 blocked since it isn't that uncommon to run normal web services on 8xxx ports on the Internet.Gallivant
Also, most of the port 80 issues are going to be on the server side, not the client side. If you have a server where you are running a WebSockets connection on port 80 and you are able to connect yourself, then the success rate for everybody else will be higher too. Some corporate transparent proxies could pose problems on the client side, but very few home users will see any client side issue with port 80.Gallivant
So I'll use port 8080 and setup SSL on port 443 if I'll have no choice. ThanksFancher
T
20

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
Tolley answered 12/4, 2014 at 21:22 Comment(1)
One trick you can use is to access an HTTPS URL at the same address/port as your websocket endpoint with the self signed certificate and when it throws up a box you can add a security exception. This exception will continue working for WebSocket connections as well. Many WebSocket implementations can also serve an HTTPS page. Otherwise standing up a quick HTTPS server via apache or openssl s_server just to add the security exception works too. This works in all major browsers, including FireFox.Batho
P
15

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/

Professional answered 14/1, 2015 at 10:10 Comment(4)
This works, I was missing this part "Now browse to 0.0.0.0:8443 server and accept the self-signed cert in Chrome."Lefthanded
In all honesty, I don't think users will go through the trouble to accept certificates when their content does not appear. Accepting certificates is too technical for most users.Scandal
The websocket protocol is an extension to http. It starts as a normal http request and the client then initiates a websocket handshake by passing an "upgrade" header over the existing http connection..Glum
This saves my day. Was trying to communicate a hardware that interfaced via secure websocket.Barham
U
5

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
Underproof answered 28/9, 2019 at 19:7 Comment(2)
What is wscat ?Comprise
wscat - Communicate over websocket wscat [options] (--listen <port> | --connect <url>)Underproof
A
1

I had a similar issue connecting to wss://... with my self-signed certificate. The solution is to accept the certificate in the browser:

  1. go to the corresponding https://... site in your Chrome browser
  2. click "Advanced" button
  3. click "proceed to xxx (unsafe)"
Acrodont answered 5/12, 2022 at 6:43 Comment(1)
nice! confirming this trick works great in firefoxOffertory

© 2022 - 2024 — McMap. All rights reserved.