From bd71e0f992f82cefe5394d6884cea684167a74ce Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Wed, 4 Jan 2017 17:45:23 +0100 Subject: [PATCH] [fix] #725 Added anti-DOS mechanism, limiting requests to 1 / second / IP. --- app/lib/system/network.js | 11 +++++++++++ package.json | 1 + test/fast/ddos-test.js | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 test/fast/ddos-test.js diff --git a/app/lib/system/network.js b/app/lib/system/network.js index d48d4cfb1..ff7df8962 100644 --- a/app/lib/system/network.js +++ b/app/lib/system/network.js @@ -5,6 +5,7 @@ const os = require('os'); const Q = require('q'); const _ = require('underscore'); const upnp = require('nnupnp'); +const ddos = require('ddos'); const http = require('http'); const express = require('express'); const morgan = require('morgan'); @@ -99,6 +100,14 @@ module.exports = { })); } + // DDOS protection + const whitelist = interfaces.map(i => i.ip); + if (whitelist.indexOf('127.0.0.1') === -1) { + whitelist.push('127.0.0.1'); + } + const ddosInstance = new ddos({ whitelist }); + app.use(ddosInstance.express); + // CORS for **any** HTTP request app.use(cors()); @@ -165,6 +174,8 @@ module.exports = { // Return API return { + getDDOS: () => ddosInstance, + closeConnections: () => co(function *() { for (let i = 0, len = httpServers.length; i < len; i++) { const httpServer = httpServers[i].http; diff --git a/package.json b/package.json index 7ebd46995..50de5902c 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "commander": "2.9.0", "cors": "2.8.1", "daemonize2": "0.4.2", + "ddos": "0.1.16", "errorhandler": "1.4.3", "event-stream": "3.3.4", "express": "4.14.0", diff --git a/test/fast/ddos-test.js b/test/fast/ddos-test.js new file mode 100644 index 000000000..a2c4f74f1 --- /dev/null +++ b/test/fast/ddos-test.js @@ -0,0 +1,39 @@ +"use strict"; +const should = require('should'); +const co = require('co'); +const limiter = require('../../app/lib/system/limiter'); +const toolbox = require('../integration/tools/toolbox'); +const user = require('../integration/tools/user'); +const bma = require('../../app/lib/streams/bma'); + +limiter.noLimit(); + +const s1 = toolbox.server({ + pair: { + pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', + sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' + } +}); + +describe('DDOS', () => { + + before(() => co(function*() { + limiter.noLimit(); + yield s1.initWithDAL().then(bma).then((bmapi) => { + s1.bma = bmapi; + bmapi.openConnections(); + }); + })); + + it('should not be able to send more than 10 reqs/s', () => co(function*() { + try { + s1.bma.getDDOS().params.limit = 3; + s1.bma.getDDOS().params.burst = 3; + s1.bma.getDDOS().params.whitelist = []; + yield Array.from({ length: 4 }).map(() => s1.get('/blockchain/current')); + throw 'Wrong error thrown'; + } catch (e) { + e.should.have.property('statusCode').equal(429); + } + })); +}); -- GitLab