mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-26 10:26:15 -04:00
Rate limit Socket IO communication - WIP (#4036)
Includes settings Includes i18n Includes a nice notification Disconnects on rate limit Includes feeding into metrics/stats Include console warn to server console.
This commit is contained in:
parent
4f5cf2dc63
commit
40014d8230
11 changed files with 75 additions and 8 deletions
|
@ -87,6 +87,9 @@
|
|||
"pad.modals.deleted": "Deleted.",
|
||||
"pad.modals.deleted.explanation": "This pad has been removed.",
|
||||
|
||||
"pad.modals.rateLimited": "Rate Limited.",
|
||||
"pad.modals.rateLimited.explanation": "You sent too many messages to this pad so it disconnected you.",
|
||||
|
||||
"pad.modals.disconnected": "You have been disconnected.",
|
||||
"pad.modals.disconnected.explanation": "The connection to the server was lost",
|
||||
"pad.modals.disconnected.cause": "The server may be unavailable. Please notify the service administrator if this continues to happen.",
|
||||
|
|
|
@ -37,6 +37,12 @@ var channels = require("channels");
|
|||
var stats = require('../stats');
|
||||
var remoteAddress = require("../utils/RemoteAddress").remoteAddress;
|
||||
const nodeify = require("nodeify");
|
||||
const { RateLimiterMemory } = require('rate-limiter-flexible');
|
||||
|
||||
const rateLimiter = new RateLimiterMemory({
|
||||
points: settings.commitRateLimiting.points,
|
||||
duration: settings.commitRateLimiting.duration
|
||||
});
|
||||
|
||||
/**
|
||||
* A associative array that saves informations about a session
|
||||
|
@ -164,6 +170,19 @@ exports.handleDisconnect = async function(client)
|
|||
*/
|
||||
exports.handleMessage = async function(client, message)
|
||||
{
|
||||
var env = process.env.NODE_ENV || 'development';
|
||||
|
||||
if (env === 'production') {
|
||||
try {
|
||||
await rateLimiter.consume(client.handshake.address); // consume 1 point per event from IP
|
||||
}catch(e){
|
||||
console.warn("Rate limited: ", client.handshake.address, " to reduce the amount of rate limiting that happens edit the rateLimit values in settings.json");
|
||||
stats.meter('rateLimited').mark();
|
||||
client.json.send({disconnect:"rateLimited"});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -343,6 +343,22 @@ exports.importExportRateLimiting = {
|
|||
"max": 10
|
||||
};
|
||||
|
||||
/*
|
||||
* From Etherpad 1.9.0 onwards, commits from individual users are rate limited
|
||||
*
|
||||
* The default is to allow at most 10 changes per IP in a 1 second window.
|
||||
* After that the change is rejected.
|
||||
*
|
||||
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
|
||||
*/
|
||||
exports.commitRateLimiting = {
|
||||
// duration of the rate limit window (seconds)
|
||||
"duration": 1,
|
||||
|
||||
// maximum number of chanes per IP to allow during the rate limit window
|
||||
"points": 10
|
||||
};
|
||||
|
||||
/*
|
||||
* From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported
|
||||
* file is always bounded.
|
||||
|
|
5
src/package-lock.json
generated
5
src/package-lock.json
generated
|
@ -7472,6 +7472,11 @@
|
|||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"rate-limiter-flexible": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-2.1.4.tgz",
|
||||
"integrity": "sha512-wtbWcqZbCqyAO1k63moagJlCZuPCEqbJJ6il1y2JVoiUyxlE36+cM7ETta9K6tTom9O5pNK+CxwHMgyyyJ31Gg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
"nodeify": "1.0.1",
|
||||
"npm": "6.14.5",
|
||||
"openapi-backend": "2.4.1",
|
||||
"rate-limiter-flexible": "^2.1.4",
|
||||
"rehype": "^10.0.0",
|
||||
"rehype-format": "^3.0.1",
|
||||
"request": "2.88.2",
|
||||
|
|
|
@ -63,9 +63,8 @@ var padconnectionstatus = (function()
|
|||
what: 'disconnected',
|
||||
why: msg
|
||||
};
|
||||
|
||||
var k = String(msg); // known reason why
|
||||
if (!(k == 'userdup' || k == 'deleted' || k == 'looping' || k == 'slowcommit' || k == 'initsocketfail' || k == 'unauth' || k == 'badChangeset' || k == 'corruptPad'))
|
||||
if (!(k == 'userdup' || k == 'deleted' || k == 'looping' || k == 'slowcommit' || k == 'initsocketfail' || k == 'unauth' || k == 'rateLimited' || k == 'badChangeset' || k == 'corruptPad'))
|
||||
{
|
||||
k = 'disconnected';
|
||||
}
|
||||
|
|
|
@ -279,6 +279,10 @@
|
|||
<h1 data-l10n-id="pad.modals.deleted"></h1>
|
||||
<p data-l10n-id="pad.modals.deleted.explanation"></p>
|
||||
</div>
|
||||
<div class="rateLimited">
|
||||
<h1 data-l10n-id="pad.modals.rateLimited"></h1>
|
||||
<p data-l10n-id="pad.modals.rateLimited.explanation"></p>
|
||||
</div>
|
||||
<div class="disconnected with_reconnect_timer">
|
||||
<% e.begin_block("disconnected"); %>
|
||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue