From 3a9515c8852eaa2afae250237602ffe92b18ed0a Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Sun, 24 May 2020 19:22:17 +0200 Subject: [PATCH] Fixed ratelimits Didn't really do anything with cronjobs --- core/cron.py | 11 +++++++++-- core/helpers/auth.py | 4 ++++ core/tasks/cron.py | 5 +++-- core/views/auth.py | 21 ++++++++++++--------- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/core/cron.py b/core/cron.py index a438b42..02dbaa1 100644 --- a/core/cron.py +++ b/core/cron.py @@ -1,5 +1,5 @@ from core.classes.cron import Cronjob -from core.helpers.auth import clear_login_log +from core.helpers.auth import clear_login_log, clear_ratelimits CRONDEFINITIONS = [] CRONFUNCTIONS = {} @@ -19,4 +19,11 @@ debug_cron = Cronjob("core.debug_job", "* * * * *") loginlog_cron = Cronjob("core.clear_login_log", "* * * * *") CRONFUNCTIONS["core.clear_login_log"] = clear_login_log -CRONDEFINITIONS.append(loginlog_cron) \ No newline at end of file +CRONDEFINITIONS.append(loginlog_cron) + +### Remove old entries from the rate limit table + +ratelimit_cron = Cronjob("core.clear_ratelimits", "* * * * *") + +CRONFUNCTIONS["core.clear_ratelimits"] = clear_ratelimits +CRONDEFINITIONS.append(ratelimit_cron) \ No newline at end of file diff --git a/core/helpers/auth.py b/core/helpers/auth.py index 3d3064c..f44fb71 100644 --- a/core/helpers/auth.py +++ b/core/helpers/auth.py @@ -23,5 +23,9 @@ def login_success(request, user): LoginLog.objects.create(user=user, ip=get_client_ip(request), success=True) def clear_login_log(maxage=int(getValue("core.auth.ratelimit.period", 600))): + timestamp = timezone.now() - timezone.timedelta(seconds=maxage) + LoginLog.objects.filter(timestamp__lt=timestamp).delete() + +def clear_ratelimits(maxage=int(getValue("core.auth.ratelimit.block", 3600))): timestamp = timezone.now() - timezone.timedelta(seconds=maxage) LoginLog.objects.filter(timestamp__lt=timestamp).delete() \ No newline at end of file diff --git a/core/tasks/cron.py b/core/tasks/cron.py index b05f258..60fc146 100644 --- a/core/tasks/cron.py +++ b/core/tasks/cron.py @@ -6,7 +6,6 @@ logger = get_task_logger(__name__) @task(name="cron") def process_crons(): from core.modules.cron import crondefinitions - for definition in crondefinitions: if definition.is_due and not definition.is_running: definition.run() @@ -17,6 +16,7 @@ def run_cron(name, *args, **kwargs): from core.modules.cron import cronfunctions log = CronLog.objects.create(task=name) + try: output = cronfunctions[name]() if output: @@ -24,4 +24,5 @@ def run_cron(name, *args, **kwargs): except Exception as e: logger.error(f"[{name}] {str(e)}") log.locked = False - log.save() \ No newline at end of file + log.save() + diff --git a/core/views/auth.py b/core/views/auth.py index d9b2ec3..d79ef08 100644 --- a/core/views/auth.py +++ b/core/views/auth.py @@ -19,23 +19,26 @@ class RateLimitedView(TemplateView): template_name = f"{settings.EXPEPHALON_BACKEND}/auth/ratelimit.html" def dispatch(self, request, *args, **kwargs): - if not IPLimit.objects.filter(ip=get_client_ip(request)): - return redirect("login") - return super().dispatch(request, *args, **kwargs) + for iplimit in list(IPLimit.objects.filter(ip=get_client_ip(request))): + if iplimit.end >= timezone.now(): + messages.error(request, f"Sorry, there have been to many failed login attempts from your IP. Please try again after {str(iplimit.end)}, or contact support if you need help getting into your account.") + return super().dispatch(request, *args, **kwargs) + return redirect("login") class AuthView(FormView): def dispatch(self, request, *args, **kwargs): limits = list(IPLimit.objects.filter(ip=get_client_ip(request))) - if not limits: - period = timezone.now() - timezone.timedelta(seconds=int(getValue("core.auth.ratelimit.period", 600))) - failures = LoginLog.objects.filter(ip=get_client_ip(request), success=False, timestamp__gte=period) - if len(failures) >= int(getValue("core.auth.ratelimit.attempts", 5)): - limits.append(IPLimit.objects.create(ip=get_client_ip(request))) for limit in limits: if limit.end > timezone.now(): - messages.error(request, f"Sorry, there have been to many failed login attempts from your IP. Please try again after {str(limit.end)}, or contact support if you need help getting into your account.") return redirect("ratelimited") + + period = timezone.now() - timezone.timedelta(seconds=int(getValue("core.auth.ratelimit.period", 600))) + failures = LoginLog.objects.filter(ip=get_client_ip(request), success=False, timestamp__gte=period) + if len(failures) >= int(getValue("core.auth.ratelimit.attempts", 5)): + IPLimit.objects.create(ip=get_client_ip(request)) + return redirect("ratelimited") + return super().dispatch(request, *args, **kwargs) class LoginView(AuthView):