Ban system broken unless both timers are equal
The current score-based banning system appears to be broken in the following two configuration cases:
-
ban-reset-time>min-reauth-time -
ban-reset-time<min-reauth-time
Case 1: ban-reset-time > min-reauth-time
Configuration example
ban-reset-time = 1200
min-reauth-time = 300
max-ban-score = 44
Expected behavior
If a client accumulates 44 ban points within 20 minutes (1200 seconds), they are banned for 5 minutes (300 seconds). After the ban expires, they can reconnect, but if they again accumulate 44 points within the next 20-minute window, they should be banned again.
Actual behavior
A malicious client quickly gains 44 points (e.g., within 1 minute) and is banned for 5 minutes as expected. However, affter the ban expires, the client can continue brute-forcing without being banned again for the remainder of the 20-minute window, even if they accumulate millions of additional points. This effectively gives an attacker a free pass for the remaining duration of the ban-reset-time window.
Possible fix
The accumulated score should be reset when the ban expires, not based solely on the ban-reset-time. This would restart the scoring window after each ban.
Case 2: ban-reset-time < min-reauth-time
Configuration example
ban-reset-time = 60
min-reauth-time = 300
max-ban-score = 44
Expected behavior
If a client gains 44 ban points within 1 minute (60 seconds), they are banned for 5 minutes (300 seconds).
Actual behavior
The client is banned as expected, but after 60 seconds (ban-reset-time), the statistics are reset and the client is unbanned prematurely, even though min-reauth-time is set to 300 seconds. This means the ban only lasts for 60 seconds instead of the intended 300 seconds.
Possible fix
The ban-reset-time timer should not reset the score of a currently banned client. The ban duration should be independent of the scoring reset logic.
Conclusion
Currently, the only way to achieve predictable behavior is to set ban-reset-time equal to min-reauth-time. This suggests a fundamental flaw in how these two timers interact.
Are my expectations correct, or is there a design rationale behind the current behavior that I may have misunderstood?