简体   繁体   中英

Node.js & Socket.io: Self-signed certificates for a secure websocket connection

I've been running across the internet looking for a straight forward answer, but most solutions involve using Express and serving HTTP content for secure connections. I'm more interested in a secure web socket connection ( wss ) for Node.js and socket.io

I don't use Node.js for HTTP requests. I use the socket.io module that works with Node.js to deliver messages in real time to my applications. I only use node for the web socket connection.

I'll explain breifly what my setup is. I use Django as my HTTP backend. Users make a request to Django, Django forwards the contents of that request to Redis, Node.js listens in on one of Redis' channels, it processes the contents and sends the message to the appropriate recipient.

Pretty simple and straight forward. Everything works fine. But I'm afraid that the websocket connection to Node.js is unsecure. When Node.js sends a message to the recipient, I don't want anyone snooping in between and intercepting the message. I would like to make sure my users feel safe and trust the service I have built for them.

I looked into self-signed certificates and certificates from a CA. Both provide the same level of security. Since I am only using Node.js for socket.io and not serving HTTP content, a self-signed certificate will work absolutely fine (the service I have built is for mobile, not for browsers!)

Below is my implentation of socket.io:

var io = require('socket.io').listen(8000);
var redis = require('socket.io/node_modules/redis')
var redisChannelConnection = redis.createClient(6000, "12.345.678.9");
var redisServer = redis.createClient(6000, "23.456.789.1");

// Subscribe to Redis Channel
redisChannelConnection.subscribe('messages');

io.sockets.on('connection', function (socket) {
     socket.emit('message', 'Hello World');
     }

I have just written up a simple connection function so far. It works as a normal websocket connection. But I would like to make it a secure websocket connection . How many I go about doing this?

Thank you for your help.

First you need to create an HTTPS server in node (for which you need a certificate):

http://nodejs.org/api/https.html
How to create an HTTPS server in Node.js?

Then you should use that server to initiate Socket.io.

var io = require('socket.io').listen(myHTTPSserver);

That should basically be all there is to it.

There is two ways to secure your connection from man-in-the-middle attacks:

  • Using a signed certificate, and having the client check that signature. The internet is stuffed with explanations for why this actually a pretty poor solution.
  • Making sure that the client refuses to connect with anything but your certificate. Any decent SSL/TLS library will allow you to specify a certificate that must be used for an outgoing connection, if the key on the server end doesn't match that certificate the connection is aborted. This does everything that the signature system should do, but doesn't rely on every single CA cert in the world being honest, or any of the other shortcomings of the CA system.

Your Django/Node.js combination sounds quite odd, is it correctly understood that clients make requests on one channel and receive the response on another channel?

While it could technically be okay, it sounds like a recipe for making odd vulnerabilities. If you must use both, consider making Node a proxy for the Django content and have Node handle all authentication.

In any case, I seriously doubt that encrypting just one of two channels is enough, once a hacker has pwned one channel there will most likely be a plethora of escalation options.

I looked into self-signed certificates and certificates from a CA. Both provide the same level of security.

No, they don't. The security of SSL has nothing to do if you do HTTPS (eg HTTP inside SSL) or wss (eg kind of socket inside HTTP tunnel inside SSL). SSL provides end-to-end encryption, but this end-to-end can only be guaranteed if you can identify the other end. That's what certificates are for. A certificate signed by a trusted CA means, that some CA looked at the certificate data and kind of made sure that the data in the certificate matches the owner. But a self-signed certificate just says, that the owner itself thinks that everything is fine, but nobody trusted had a look at it. This is the reason self-signed certificates are not trusted by default and each user has to explicitly trust the certificate (hopefully after he has validated the owner somehow).

First, I completely agree with the other answer that self-signed certificates are not as secure but more on that in a moment... What you want to do is require "https" instead of "http" and pass in your certificate options into createServer to create your HTTPS app. The options are pretty much the same as the TLS options here . Then when you call listen for socket.io, you'll be listening via HTTPS instead of HTTP.

Now back to the real issue which is a misunderstanding of the purpose of the CA. I agree that even a self-signed certificate will encrypt the content, but a self-signed certificate is not validated by anyone else meaning that anybody else can generate their own self-signed certificate that is just as valid. A malicious user at a coffee shop could set up a WiFi network that seems legitimate. In control of that network he can put himself in the middle of all requests. All he would have to do is generate his own self-signed certificate for your domain name and he would be able to not only decrypt, but also modify in transit all of the requests. This applies not just to browsers, but also mobile apps for Android, iPhone or anything else. The certificate authority is in place for operating system to dictate which root certificates are trusted to issue certificates. Because the malicious user can't register a certificate for your domain name at a trusted certificate authority, any certificate validated in that way guarantees that the computer on the other end is in fact the intended computer. Self-signed certificates are fine in development, but using them in production puts any data sent via your application at risk of spoofing your server, information disclosure, and message tampering.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM