diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e3cd3fa4f2..f52ca84689e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#9604](https://github.com/inventree/InvenTree/pull/9604) - refactors user API endpoint to be less ambiguous - [#11893](https://github.com/inventree/InvenTree/pull/11893) bumps Node environment to version 24 LTS - this is only relevant if you build the frontend assets yourself +- [#11951](https://github.com/inventree/InvenTree/pull/11951) adds API throtteling by default to make DoS attacks more difficult. This can be disabled by setting the `INVENTREE_THROTTLE_ANON` and `INVENTREE_THROTTLE_USER` settings to `None` (either via environment variable or config file). The default throttling rates are 20 requests per minute for anonymous users, and 20 requests per second for authenticated users. ### Added diff --git a/docs/docs/start/config.md b/docs/docs/start/config.md index 25b7fd663925..8aa77d81ea03 100644 --- a/docs/docs/start/config.md +++ b/docs/docs/start/config.md @@ -136,7 +136,8 @@ Depending on how your InvenTree installation is configured, you will need to pay | `INVENTREE_X_FORWARDED_PROTO_NAME` | `x_forwarded_proto_name` | `HTTP_X_FORWARDED_PROTO` | Name of the header to use for forwarded protocol information | {{ configsetting("INVENTREE_SESSION_COOKIE_SECURE") }} Enforce secure session cookies | {{ configsetting("INVENTREE_COOKIE_SAMESITE") }} Session cookie mode. Must be one of `Strict | Lax | None | False`. Refer to the [mozilla developer docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) and the [django documentation]({% include "django.html" %}/ref/settings/#std-setting-SESSION_COOKIE_SAMESITE) for more information. | - +{{ configsetting("INVENTREE_THROTTLE_ANON") }} Throttle rate for anonymous users (e.g. '20/minute') | +{{ configsetting("INVENTREE_THROTTLE_USER") }} Throttle rate for authenticated users (e.g. '5/second') | ### Debug Mode diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index 3aa32669be94..4d2ae1547f59 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -525,6 +525,8 @@ 'DEFAULT_METADATA_CLASS': 'InvenTree.metadata.InvenTreeMetadata', 'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer'], 'TOKEN_MODEL': 'users.models.ApiToken', + 'DEFAULT_THROTTLE_CLASSES': [], + 'DEFAULT_THROTTLE_RATES': {}, } if DEBUG: @@ -540,6 +542,21 @@ JWT_AUTH_REFRESH_COOKIE = 'inventree-token' INSTALLED_APPS.append('rest_framework_simplejwt') +# Throtteling setup +THROTTLE_ANON = get_setting('INVENTREE_THROTTLE_ANON', 'throttle.anon', '20/minute') +THROTTLE_USER = get_setting('INVENTREE_THROTTLE_USER', 'throttle.user', '60/second') + +if not DEBUG and THROTTLE_ANON and str(THROTTLE_ANON).lower() != 'none': + REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['anon'] = THROTTLE_ANON + REST_FRAMEWORK['DEFAULT_THROTTLE_CLASSES'].append( + 'rest_framework.throttling.AnonRateThrottle' + ) +if not DEBUG and THROTTLE_USER and str(THROTTLE_USER).lower() != 'none': + REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['user'] = THROTTLE_USER + REST_FRAMEWORK['DEFAULT_THROTTLE_CLASSES'].append( + 'rest_framework.throttling.UserRateThrottle' + ) + # WSGI default setting WSGI_APPLICATION = 'InvenTree.wsgi.application' diff --git a/src/backend/InvenTree/config_template.yaml b/src/backend/InvenTree/config_template.yaml index 4b790e7c17de..3cc449234f0b 100644 --- a/src/backend/InvenTree/config_template.yaml +++ b/src/backend/InvenTree/config_template.yaml @@ -162,6 +162,11 @@ cors: # regex: +# Throttling is applied to the API by default to make DoS attacks more difficult; these can be disabled by setting them to None. +# throttle: +# anon: '20/minute' +# user: '60/second' + # MEDIA_ROOT is the local filesystem location for storing uploaded files #media_root: '/home/inventree/data/media'