Allow IP ranges in BLOCKED_IPS setting (#3306)

Allow IP ranges — defined with the CIDR notation (e.g. 192.168.1.0/24) — in BLOCKED_IPS setting.
This commit is contained in:
Francesco Lodolo 2024-09-04 19:24:14 +02:00 коммит произвёл GitHub
Родитель 1dd5c81069
Коммит 08eae32fa2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 46 добавлений и 4 удалений

Просмотреть файл

@ -73,8 +73,11 @@ you create:
Set to 'google' if you want to use 'Google' (corresponding GOOGLE_* settings must be set).
``BLOCKED_IPS``
A comma-separated list of IP addresses to be blocked from accessing the app,
for example because they are DDoS'ing the server.
A comma-separated list of IP addresses or IP ranges (expressed using the
`CIDR notation`_, e.g. `192.168.1.0/24`) to be blocked from accessing the app, for
example because they are DDoS'ing the server.
.. _CIDR notation: https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation
``CELERY_ALWAYS_EAGER``
Controls whether asynchronous tasks (mainly used during sync) are sent to

Просмотреть файл

@ -1,3 +1,7 @@
import logging
from ipaddress import ip_address
from raygun4py.middleware.django import Provider
from django.conf import settings
@ -38,6 +42,19 @@ class BlockedIpMiddleware(MiddlewareMixin):
if ip in settings.BLOCKED_IPS:
return HttpResponseForbidden("<h1>Forbidden</h1>")
# Convert request IP string to an IP object, check if it belongs to an
# IP range
try:
ip_obj = ip_address(ip)
except ValueError:
log = logging.getLogger(__name__)
log.error(f"Invalid IP detected in BlockedIpMiddleware: {ip}")
return None
for ip_range in settings.BLOCKED_IP_RANGES:
if ip_obj in ip_range:
return HttpResponseForbidden("<h1>Forbidden</h1>")
return None

Просмотреть файл

@ -1,9 +1,12 @@
"""Django settings for Pontoon."""
import logging
import os
import re
import socket
from ipaddress import ip_address, ip_network
import dj_database_url
from django.utils.functional import lazy
@ -277,8 +280,27 @@ INSTALLED_APPS = (
"django_ace",
)
# A list of IP addresses to be blocked from accessing the app, because they are DDoS'ing the server
BLOCKED_IPS = os.environ.get("BLOCKED_IPS", "").split(",")
# A list of IP addresses or IP ranges to be blocked from accessing the app,
# as a DDoS countermeasure.
blocked_ip_settings = os.environ.get("BLOCKED_IPS", "").split(",")
BLOCKED_IPS = []
BLOCKED_IP_RANGES = []
for ip in blocked_ip_settings:
ip = ip.strip()
if ip == "":
continue
try:
# If the IP is valid, store it directly as string
ip_obj = ip_address(ip)
BLOCKED_IPS.append(ip)
except ValueError:
try:
# Check if it's a valid IP range (CIDR notation)
ip_obj = ip_network(ip, strict=False)
BLOCKED_IP_RANGES.append(ip_obj)
except ValueError:
log = logging.getLogger(__name__)
log.error(f"Invalid IP or IP range defined in BLOCKED_IPS: {ip}")
MIDDLEWARE = (
"django.middleware.security.SecurityMiddleware",