From 5da76351640909cf3a992150e88a4a314212f077 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Tue, 20 Aug 2019 16:50:55 +0200 Subject: [PATCH] account: add IP rate limiting for account creation Add a configurable cooldown in seconds for which no further accounts can be created from the same IP. --- config.example.py | 4 ++++ nyaa/views/account.py | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/config.example.py b/config.example.py index 8107de2..304e229 100644 --- a/config.example.py +++ b/config.example.py @@ -139,6 +139,10 @@ MINIMUM_ANONYMOUS_TORRENT_SIZE = 1 * 1024 * 1024 # Relies on USE_RECAPTCHA. Set to 0 to disable. ACCOUNT_RECAPTCHA_AGE = 7 * 24 * 3600 # A week +# Seconds after which an IP is allowed to register another account +# (0 disables the limitation) +PER_IP_ACCOUNT_COOLDOWN = 24 * 3600 + # Backup original .torrent uploads BACKUP_TORRENT_FOLDER = 'torrents' diff --git a/nyaa/views/account.py b/nyaa/views/account.py index b6a4a9e..3be63df 100644 --- a/nyaa/views/account.py +++ b/nyaa/views/account.py @@ -1,6 +1,6 @@ import binascii import time -from datetime import datetime +from datetime import datetime, timedelta from ipaddress import ip_address import flask @@ -80,6 +80,15 @@ def logout(): return response +def _check_for_multi_account(ip, cooldown): + if not cooldown: + return False + cooldown_timestamp = datetime.utcnow() - timedelta(seconds=cooldown) + q = models.User.query.filter(ip == models.User.registration_ip, + models.User.created_time > cooldown_timestamp) + return db.session.query(q.exists()).scalar() + + @bp.route('/register', methods=['GET', 'POST']) def register(): if flask.g.user: @@ -87,10 +96,17 @@ def register(): form = forms.RegisterForm(flask.request.form) if flask.request.method == 'POST' and form.validate(): + ip = ip_address(flask.request.remote_addr).packed + + if _check_for_multi_account(ip, app.config.get('PER_IP_ACCOUNT_COOLDOWN', 0)): + flask.flash('You or somebody else has already registered an account from this IP ' + 'recently. You cannot register another one.', 'danger') + return flask.render_template('register.html', form=form) + user = models.User(username=form.username.data.strip(), email=form.email.data.strip(), password=form.password.data) - user.registration_ip = ip_address(flask.request.remote_addr).packed - user.last_login_ip = user.registration_ip + user.registration_ip = ip + user.last_login_ip = ip db.session.add(user) db.session.commit()