From 3cf533cc0ae748588a29338c1ce555fcbe435998 Mon Sep 17 00:00:00 2001 From: Mystikfluu Date: Sat, 18 Jun 2022 18:28:29 +0200 Subject: [PATCH] add individual url ratelimiting --- server.js | 37 ++++++++++++++++++ server_config.json | 95 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index fc6da82..268947c 100644 --- a/server.js +++ b/server.js @@ -181,6 +181,7 @@ var API_CALLS_ACCOUNT = {} var USER_CALLS = {} var SESSIONS = {} var REVERSE_SESSIONS = {} +var INDIVIDUAL_CALLS = {} function clear_api_calls() { API_CALLS = {} } @@ -194,6 +195,32 @@ setInterval(clear_api_calls, config.rate_limits.api.reset_time) setInterval(clear_account_api_calls, config.rate_limits.api.reset_time) setInterval(clear_user_calls, config.rate_limits.user.reset_time) +function increaseIndividualCall(url,req) { //true = continue, false = ratelimit + let conf = config["rate_limits"]["individual"][url] + if(!conf) { + console.log(5,"uri not in individual ratelimiter",url); + return true; + } + if(!conf["enabled"])return true; + let ip = req.socket.remoteAddress + if(INDIVIDUAL_CALLS[ip]==undefined)INDIVIDUAL_CALLS[ip] = {} + if(INDIVIDUAL_CALLS[ip][url]==undefined)INDIVIDUAL_CALLS[ip][url] = 0 + if(INDIVIDUAL_CALLS[ip][url] == 0) { + setTimeout(function(){ + INDIVIDUAL_CALLS[ip][url] = 0 + },conf["reset_time"]) + } + + INDIVIDUAL_CALLS[ip][url]++; + + if(INDIVIDUAL_CALLS[ip][url] >= conf["max"]){ + console.log(5,"ratelimiting someone on", url, INDIVIDUAL_CALLS[ip][url],conf["max"]); + return false; + } + + return true; +} + function increaseAccountAPICall(req,res) { let cookie = req.cookies.AUTH_COOKIE if(!cookie){ @@ -307,6 +334,16 @@ app.use("/*",function(req,res,next){ return } } + let fullurl = req.baseUrl + req.path + if(fullurl != "/") { + fullurl = fullurl.substring(0,fullurl.length-1) + } + if(!increaseIndividualCall(fullurl,req)){ + res.status(429) + res.json({"error":"you are sending too many requests!"}) + return + } + next() }) diff --git a/server_config.json b/server_config.json index 8c7f90e..51ea466 100644 --- a/server_config.json +++ b/server_config.json @@ -11,14 +11,101 @@ }, "rate_limits": { "api": { - "reset_time": 10000, - "max_without_session": 20, - "max_with_session": 60, - "max_per_account": 30 + "reset_time": 40000, + "max_without_session": 30, + "max_with_session": 120, + "max_per_account": 200 }, "user": { "reset_time": 30000, "max": 60 + }, + "individual": { + "/" : { + "enabled": true, + "max": 4, + "reset_time": 10000 + }, + "/js/warn_message.js" : { + "enabled": true, + "max": 10, + "reset_time": 5000 + }, + "/js/addnavbar.js" : { + "enabled": true, + "max": 10, + "reset_time": 5000 + }, + "/css/logon.css" : { + "enabled": true, + "max": 10, + "reset_time": 5000 + }, + "/css/global.css" : { + "enabled": true, + "max": 10, + "reset_time": 5000 + }, + "/api/getuser" : { + "enabled": true, + "max": 10, + "reset_time": 10000 + }, + "/api/getotheruser" : { + "enabled": true, + "max": 60, + "reset_time": 10000 + }, + "/login" : { + "enabled": true, + "max": 6, + "reset_time": 10000 + }, + "/images/default_avatar.png" : { + "enabled": true, + "max": 20, + "reset_time": 10000 + }, + "/images/bot.png" : { + "enabled": true, + "max": 10, + "reset_time": 10000 + }, + "/js/markdown.js" : { + "enabled": true, + "max": 5, + "reset_time": 10000 + }, + "/posts" : { + "enabled": true, + "max": 5, + "reset_time": 10000 + }, + "/js/httppost.js" : { + "enabled": true, + "max": 10, + "reset_time": 10000 + }, + "/js/htmlescape.js" : { + "enabled": true, + "max": 10, + "reset_time": 10000 + }, + "/api/getPosts" : { + "enabled": true, + "max": 10, + "reset_time": 20000 + }, + "/api/setBio": { + "enabled": true, + "max": 3, + "reset_time": 20000 + }, + "/api/setavatar": { + "enabled": true, + "max": 6, + "reset_time": 120000 + } } }, "logs": {