Skip to content

Commit

Permalink
import/export: always rate limit import and exports
Browse files Browse the repository at this point in the history
This is a departure from previous versions, which did not limit import/export
requests. Now such requests are ALWAYS rate limited. The default is 10 requests
per IP each 90 seconds, and also applies to old instances upgraded to 1.8.3.

Administrators can tune the parameters via settings.importExportRateLimiting.
  • Loading branch information
JohnMcLear committed Apr 4, 2020
1 parent 0d70b67 commit 56ece63
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 0 deletions.
17 changes: 17 additions & 0 deletions settings.json.docker
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,23 @@
"indentationOnNewLine": false,
*/

/*
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
* limited.
*
* The default is to allow at most 10 requests per IP in a 90 seconds window.
* After that the import/export request is rejected.
*
* See https://github.com/nfriedly/express-rate-limit for more options
*/
"importExportRateLimiting": {
// duration of the rate limit window (milliseconds)
"windowMs": 90000,

// maximum number of requests per IP to allow during the rate limit window
"max": 10
},

/*
* If true, importing to a pad is allowed only if an author has a session
* estabilished and has already contributed to that specific pad.
Expand Down
17 changes: 17 additions & 0 deletions settings.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,23 @@
"indentationOnNewLine": false,
*/

/*
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
* limited.
*
* The default is to allow at most 10 requests per IP in a 90 seconds window.
* After that the import/export request is rejected.
*
* See https://github.com/nfriedly/express-rate-limit for more options
*/
"importExportRateLimiting": {
// duration of the rate limit window (milliseconds)
"windowMs": 90000,

// maximum number of requests per IP to allow during the rate limit window
"max": 10
},

/*
* If true, importing to a pad is allowed only if an author has a session
* estabilished and has already contributed to that specific pad.
Expand Down
12 changes: 12 additions & 0 deletions src/node/hooks/express/importexport.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@ var exportHandler = require('../../handler/ExportHandler');
var importHandler = require('../../handler/ImportHandler');
var padManager = require("../../db/PadManager");
var authorManager = require("../../db/AuthorManager");
const rateLimit = require("express-rate-limit");

settings.importExportRateLimiting.onLimitReached = function(req, res, options) {
// when the rate limiter triggers, write a warning in the logs
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;

console.warn(`Rate limiter triggered for IP address ${ip}`);
}

var limiter = rateLimit(settings.importExportRateLimiting);

exports.expressCreateServer = function (hook_name, args, cb) {

// handle export requests
args.app.use('/p/:pad/:rev?/export/:type', limiter);
args.app.get('/p/:pad/:rev?/export/:type', async function(req, res, next) {
var types = ["pdf", "doc", "txt", "html", "odt", "etherpad"];
//send a 404 if we don't support this filetype
Expand Down Expand Up @@ -40,6 +51,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
});

// handle import requests
args.app.use('/p/:pad/import', limiter);
args.app.post('/p/:pad/import', async function(req, res, next) {
if (await hasPadAccess(req, res)) {
let exists = await padManager.doesPadExists(req.params.pad);
Expand Down
17 changes: 17 additions & 0 deletions src/node/utils/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,23 @@ exports.scrollWhenFocusLineIsOutOfViewport = {
*/
exports.exposeVersion = false;

/*
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
* limited.
*
* The default is to allow at most 10 requests per IP in a 90 seconds window.
* After that the import/export request is rejected.
*
* See https://github.com/nfriedly/express-rate-limit for more options
*/
exports.importExportRateLimiting = {
// duration of the rate limit window (milliseconds)
"windowMs": 90000,

// maximum number of requests per IP to allow during the rate limit window
"max": 10
};

/*
* If true, importing to a pad is allowed only if an author has a session
* estabilished and has already contributed to that specific pad.
Expand Down
5 changes: 5 additions & 0 deletions src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"etherpad-require-kernel": "1.0.9",
"etherpad-yajsml": "0.0.2",
"express": "4.17.1",
"express-rate-limit": "5.1.1",
"express-session": "1.17.0",
"find-root": "1.1.0",
"formidable": "1.2.1",
Expand Down

0 comments on commit 56ece63

Please sign in to comment.