I'm implementing some security measures and one of them is a site wide throttle on too many failed requests as protection against distributed brute force attacks.
The question I am stuck with is, after how many failed login requests should I start to throttle?
Now one reasonable way is, as mentioned here "using a running average of your site's bad-login frequency as the basis for an upper limit". If the site has an average of 100 failed logins, 300 (puffer added) might be a good threshold.
Now I don't have a running average and I don't want someone having to actively increase the upper limit as the user base grows. I want a dynamic formula that calculates this limit based on the active users amount.
The difficulty is that if there are only a few users, they should have a much higher user to threshold ratio than let's say 100k users. Meaning that for example for 50 users the limit could be set at 50% of the total user count which means allowing 25 failed login requests site-wide in a given timespan. But this ratio should decrease for 100k users, the threshold should be more like around 1%. 1000 failed login requests in the same let's say hour, is a lot (probably not accurate at all I am not a security expert, the numbers are only examples to illustrate).
I was wondering, is there any mathematical formula that could archive this in a neat way?
This is a chart of what I think the formula should be calculating approximately:
Here is what I have now (I know it's terrible, any suggestion will be better I'm sure):
$threshold = 1;
if ($activeUsers <= 50) {
// Global limit is the same as the total of each users individual limit
$threshold *= $activeUsers; // If user limit is 4, global threshold will be 4 * user amount
} elseif ($activeUsers <= 200) {
// Global requests allows each user to make half of the individual limit simultaneously
// over the last defined timespan
$threshold = $threshold * $activeUsers / 2;
} elseif ($activeUsers <= 600) {
$threshold = $threshold * $activeUsers / 2.5;
} elseif ($activeUsers <= 1000) {
$threshold = $threshold * $activeUsers / 3.5;
} else { // More than 1000
$threshold = $threshold * $activeUsers / 5;
}
return $threshold;