How to protect against distributed denial-of-service attacks in Node.js with Socket.io?
Asked Answered
G

4

63

I have been learning node.js and socket.io lately. My question is how can I protect server against client side attacks?

This is my server code

io.sockets.on('connection', function (socket) { 
//users.push(socket);       
socket.on('message', function (data) {      

    socket.on('disconnect', function () { });           

    socket.on('bcast', function (data) {        
        socket.emit('news', { 'data': data });
        socket.broadcast.emit('news', { 'data': data });     
    });

    socket.on('login', function(data){
      socket.emit('login', {'data': [ socket.id, data ] });
    });
   });
 });

For example if a client uses chrome developer tools to do the flowing code

 for(var i = 0; i<99999999999; i++)
 {
        socket.emit('bcast', {data: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'});
 }

its going to kill the server.

Grodno answered 6/12, 2013 at 23:41 Comment(5)
If that really kills your server, you should probably implent some sort of throttling based on clients etc.Wigging
Node 0.10.20 has known problems with DoS, if you are using it (or below, I think).Malignity
Why dont you expose the node sockets endpoint using a DoS safeguard/throttling service? I am sure cloudflare or a similar provider will have very good DoS protection rather than you trying to roll your own.Stairway
Very good question, no good answers!Genteelism
Maybe you are taking the problem to the extreme. Exposing/misusing bcast like that is bad. If you use broadcast too much your server will stop functioning even before your users will do DDOS. Why dont you test your scenario by treating broadcast differently than single emit. Try rooms for example. Use broadcast only when required.Astrahan
R
31

Look into JS event throttling and debouncing!

Those techniques will help you prevent and detect attacks to a certain point (which is, in my opinion, enough for a small multiplayer socket game)...

EDIT:

In this jsfiddle: http://jsfiddle.net/y4tq9/9/

var sIO = {};

sIO.on = (function(){
    var messages = {};
    var speedLimit = 5; //5ms
    return function(message, handler) {
        messages[message] = messages[message] || {};
        if(messages[message].timestamp && new Date().getTime() - messages[message].timestamp < speedLimit) return false;
        else messages[message].timestamp = new Date().getTime();

        handler();
        return true;
        //execute code, Ex:
    }
}());

you can see that every request sent faster than 5ms will return false, otherwise the handler get run.

You simple disconnect the sockets who send request faster than 5ms (or 2ms, or 3ms depending on your network and your application's weight...).

You might as well using js event throttling on client site to make sure all of your requests doesn't send faster than the speed limit!

This technique will not provide absolute protection from exploiting, but it will prevent your server from crashing when attackers try to Dos...

Retrogressive answered 29/1, 2014 at 13:23 Comment(3)
I quickly wrote a sample code and edited my answer... This technique is very situational to the size of your application... You should rewrite it after you understand how it works. At least it works... and it doesn't cost!! lol!Retrogressive
'When attackers try to DDos it', dont you mean DoS? :)Unwisdom
I removed the broken link, please look up "Event Throttling" if you need more information about the techniqueRetrogressive
E
16

The rate-limiter-flexible Node.js package can be used against DDoS attacks.

const { RateLimiterMemory } = require('rate-limiter-flexible');

const rateLimiter = new RateLimiterMemory({
  points: 5, // 5 points
  duration: 1 // per second
});

socket.on('bcast', data => {
  rateLimiter.consume(uniqueSocketId) // consume 1 point per event
    .then(() => {
      socket.emit('news', { 'data': data });
      socket.broadcast.emit('news', { 'data': data });
    })
    .catch(rejRes => {
      // no available points to consume
      // emit error or another workaround
    });
});

Any event will be blocked, if it happens more than 5 times per second.

There is also the option for distributed applications using Redis. And some flexible settings like insurance and block strategy makes rate-limiter-flexible highly available and fast.

Erasme answered 16/5, 2018 at 7:28 Comment(0)
H
3

It's not always a good idea to do this in your http server. Check this answer: How to prevent DOS attacks on my http server which written in node.js?

Hydrogen answered 22/10, 2015 at 16:31 Comment(0)
H
1

Given that node is not the "best" at handling such DDoS Conditions within the framework itself I would look into third part DDoS Mitigation tactics such as cloudflare or blacklotus. They are costly offerings if you have a huge scale of use but they will protect Node or really any framework from denial of service attacks.

https://www.cloudflare.com

http://www.blacklotus.net/

Another option is using software based firewall solutions like aiProtect which are a bit more cost effective when scaling past the free tier of cloudflare and blacklotus.

http://aiscaler.com/home/protect

There are many more out there but this one happens to have an AWS partnership so you can easily spin up aiProtect VMs.

Hass answered 16/12, 2013 at 23:12 Comment(2)
Also note if you're wanting to run websockets with cloudflare or these services it costs thousands per month.Unwisdom
This is good, but they don't block "simple DDoS" attacks like the example given from @Virushan.Hydrogen

© 2022 - 2024 — McMap. All rights reserved.