# Django Blacklist
Blacklist users and hosts in Django. Automatically blacklist rate-limited clients.
## Overview
`Django Blacklist` allows you to block specific users and IP addresses/networks from accessing your application.
Clients can be blocked manually from the admin interface, or automatically after exceeding a request rate limit.
Each blacklist rule is applied for a specific duration.
The blacklist is very scalable and is applied without noticeable overhead for large numbers of rules.
## Installation
To install the package, run:
```
$ pip install django-blacklist
```
Add the `blacklist` application to `INSTALLED_APPS`:
```
INSTALLED_APPS = [
...
'blacklist'
]
```
Add the `BlacklistMiddleware` middleware after `AuthenticationMiddleware`:
```
MIDDLEWARE = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'blacklist.middleware.BlacklistMiddleware',
...
]
```
Apply the blacklist database migrations:
```
$ python manage.py migrate blacklist
```
## Usage
You can manage the blacklist rules from the admin.
Changes take effect after a configurable time, or when the server is restarted.
A rule can target a user or an IP address.
You can also target IP networks (ranges) by specifying the optional `prefixlen` field (number of network prefix bits).
Each rule has a specific duration. After that time interval passes, the rule expires.
When a request is blocked due to a matching rule:
* Status 400 (bad request) is returned.
* An error template is rendered.
You can specify a custom one (see `Settings` below), or use the one for status 400.
* A message is logged
(warning from logger `blacklist.middleware` for custom templates, or error from logger `django.security` otherwise).
### Removing Expired Rules
Expired rules are not automatically removed from the database.
They can be cleaned up with the included management command `trim_blacklist`:
```
$ python manage.py trim_blacklist [-c <created_days>] [-e <expired_days>]
```
The options `-c` and `-e` specify the minimum ages of creation and expiry, respectively.
## Automatic Blacklisting
Clients can be blacklisted automatically, after exceeding a specified request rate limit.
This feature requires [django-ratelimit](https://github.com/jsocol/django-ratelimit).
First, rate-limit a view by applying the `@ratelimit` decorator. Make sure to set `block=False`.
Then, blacklist rate-limited clients by adding the `@blacklist_ratelimited` decorator. Specify the blacklist duration.
For example:
```
from datetime import timedelta
from django_ratelimit.decorators import ratelimit
from blacklist.ratelimit import blacklist_ratelimited
@ratelimit(key='user_or_ip', rate='50/m', block=False)
@blacklist_ratelimited(timedelta(minutes=30))
def index(request):
...
```
Automatic rules take effect immediately.
If the request comes from an authenticated user, the rule will target that user.
Otherwise, it will target their IP address.
`@blacklist_ratelimited` accepts two arguments: `(duration, block=True)`.
* `duration` can be a `timedelta` object, or a tuple of two separate durations
(for user-based and IP-based rules).
* `block` specifies if the request should be blocked immediately, or passed to the view.
Automatic rules will have a comment that contains the ID of the request, which triggered the creation of the rule,
and the "request line".
The request ID is added only if available. Django does not generate request IDs.
For that purpose, you can install [django-log-request-id](https://github.com/dabapps/django-log-request-id).
## Proxies and Client Addresses
By default, the client IP address is taken from the `REMOTE_ADDR` value of `request.META`.
If your application server is behind one or more reverse proxies,
this will usually be the address of the nearest proxy, and not the actual client address.
To properly blacklist clients by IP address,
you can configure `Django Blacklist` to use addresses from another source (see `Settings` below).
To actually obtain the proxied client addresses,
you can use [django-ipware](https://github.com/un33k/django-ipware).
In this case, you can configure `Django Blacklist` to obtain client addresses from your function,
which in turn calls `django-ipware` for the actual logic.
Alternatively, you can set `REMOTE_ADDR` from the `X-Forwarded-For` header in middleware,
installed before `Django Blacklist`.
However, keep in mind that this header can be forged to bypass the rate limits.
To counter that, you can use the last address in that header (which should be set by your trusted reverse proxy).
If you are behind two proxies, use the second to last address, and so on.
## Settings
* `BLACKLIST_ENABLE` - whether blacklisted clients should be blocked,
and rate-limited clients should be blacklisted; default: `True`
* `BLACKLIST_RELOAD_PERIOD` - how often to reload the blacklist, in seconds; default: `60`
* `BLACKLIST_RATELIMITED_ENABLE` - whether rate-limited clients should be automatically blacklisted;
requires `BLACKLIST_ENABLE`; default: `True`
* `BLACKLIST_TEMPLATE` - name of a custom error template to render to blocked clients;
its context will contain `request` and `exception`;
set to `None` to use the template for status 400; default: `None`
* `BLACKLIST_LOGGING_ENABLE` - whether blocked requests should be logged
(honored only if a custom error template is configured); default: `True`
* `BLACKLIST_ADDRESS_SOURCE` - the source of client addresses; can be a key in `request.META`,
a callable that receives the request object, or the dotted string path to such a callable;
default: `'REMOTE_ADDR'`
Raw data
{
"_id": null,
"home_page": "https://github.com/vsemionov/django-blacklist",
"name": "django-blacklist",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "django blacklist ratelimit firewall",
"author": "Victor Semionov",
"author_email": "vsemionov@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/69/8b/b290c76547a536897b3a63c80ddba41b1a8544655fe5d37c7468f684edc1/django-blacklist-0.7.0.tar.gz",
"platform": null,
"description": "# Django Blacklist\n\nBlacklist users and hosts in Django. Automatically blacklist rate-limited clients.\n\n\n## Overview\n\n`Django Blacklist` allows you to block specific users and IP addresses/networks from accessing your application.\nClients can be blocked manually from the admin interface, or automatically after exceeding a request rate limit.\nEach blacklist rule is applied for a specific duration.\nThe blacklist is very scalable and is applied without noticeable overhead for large numbers of rules.\n\n\n## Installation\n\nTo install the package, run:\n```\n$ pip install django-blacklist\n```\n\nAdd the `blacklist` application to `INSTALLED_APPS`:\n```\nINSTALLED_APPS = [\n ...\n 'blacklist'\n]\n```\n\nAdd the `BlacklistMiddleware` middleware after `AuthenticationMiddleware`:\n```\nMIDDLEWARE = [\n ...\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\n 'blacklist.middleware.BlacklistMiddleware',\n ...\n]\n```\n\nApply the blacklist database migrations:\n```\n$ python manage.py migrate blacklist\n```\n\n\n## Usage\n\nYou can manage the blacklist rules from the admin.\nChanges take effect after a configurable time, or when the server is restarted.\nA rule can target a user or an IP address.\nYou can also target IP networks (ranges) by specifying the optional `prefixlen` field (number of network prefix bits).\nEach rule has a specific duration. After that time interval passes, the rule expires.\nWhen a request is blocked due to a matching rule:\n* Status 400 (bad request) is returned.\n* An error template is rendered.\n You can specify a custom one (see `Settings` below), or use the one for status 400.\n* A message is logged\n (warning from logger `blacklist.middleware` for custom templates, or error from logger `django.security` otherwise).\n\n### Removing Expired Rules\n\nExpired rules are not automatically removed from the database.\nThey can be cleaned up with the included management command `trim_blacklist`:\n```\n$ python manage.py trim_blacklist [-c <created_days>] [-e <expired_days>]\n```\nThe options `-c` and `-e` specify the minimum ages of creation and expiry, respectively.\n\n\n## Automatic Blacklisting\n\nClients can be blacklisted automatically, after exceeding a specified request rate limit.\nThis feature requires [django-ratelimit](https://github.com/jsocol/django-ratelimit).\n\nFirst, rate-limit a view by applying the `@ratelimit` decorator. Make sure to set `block=False`.\nThen, blacklist rate-limited clients by adding the `@blacklist_ratelimited` decorator. Specify the blacklist duration.\nFor example:\n```\nfrom datetime import timedelta\nfrom django_ratelimit.decorators import ratelimit\nfrom blacklist.ratelimit import blacklist_ratelimited\n\n@ratelimit(key='user_or_ip', rate='50/m', block=False)\n@blacklist_ratelimited(timedelta(minutes=30))\ndef index(request):\n ...\n```\n\nAutomatic rules take effect immediately.\nIf the request comes from an authenticated user, the rule will target that user.\nOtherwise, it will target their IP address.\n\n`@blacklist_ratelimited` accepts two arguments: `(duration, block=True)`.\n* `duration` can be a `timedelta` object, or a tuple of two separate durations\n(for user-based and IP-based rules).\n* `block` specifies if the request should be blocked immediately, or passed to the view.\n\nAutomatic rules will have a comment that contains the ID of the request, which triggered the creation of the rule,\nand the \"request line\".\nThe request ID is added only if available. Django does not generate request IDs.\nFor that purpose, you can install [django-log-request-id](https://github.com/dabapps/django-log-request-id).\n\n\n## Proxies and Client Addresses\n\nBy default, the client IP address is taken from the `REMOTE_ADDR` value of `request.META`.\nIf your application server is behind one or more reverse proxies,\nthis will usually be the address of the nearest proxy, and not the actual client address.\nTo properly blacklist clients by IP address,\nyou can configure `Django Blacklist` to use addresses from another source (see `Settings` below).\n\nTo actually obtain the proxied client addresses,\nyou can use [django-ipware](https://github.com/un33k/django-ipware).\nIn this case, you can configure `Django Blacklist` to obtain client addresses from your function,\nwhich in turn calls `django-ipware` for the actual logic.\n\nAlternatively, you can set `REMOTE_ADDR` from the `X-Forwarded-For` header in middleware,\ninstalled before `Django Blacklist`.\nHowever, keep in mind that this header can be forged to bypass the rate limits.\nTo counter that, you can use the last address in that header (which should be set by your trusted reverse proxy).\nIf you are behind two proxies, use the second to last address, and so on.\n\n\n## Settings\n\n* `BLACKLIST_ENABLE` - whether blacklisted clients should be blocked,\n and rate-limited clients should be blacklisted; default: `True`\n* `BLACKLIST_RELOAD_PERIOD` - how often to reload the blacklist, in seconds; default: `60`\n* `BLACKLIST_RATELIMITED_ENABLE` - whether rate-limited clients should be automatically blacklisted;\n requires `BLACKLIST_ENABLE`; default: `True`\n* `BLACKLIST_TEMPLATE` - name of a custom error template to render to blocked clients;\n its context will contain `request` and `exception`;\n set to `None` to use the template for status 400; default: `None`\n* `BLACKLIST_LOGGING_ENABLE` - whether blocked requests should be logged\n (honored only if a custom error template is configured); default: `True`\n* `BLACKLIST_ADDRESS_SOURCE` - the source of client addresses; can be a key in `request.META`,\n a callable that receives the request object, or the dotted string path to such a callable;\n default: `'REMOTE_ADDR'`\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Blacklist users and hosts in Django. Automatically blacklist rate-limited clients.",
"version": "0.7.0",
"split_keywords": [
"django",
"blacklist",
"ratelimit",
"firewall"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "107761b69ce51f228276081171cf73dc",
"sha256": "70cfc2252510d00e776d14b911c01961e4a45e312d4d7c89083a7d34dffe1ef1"
},
"downloads": -1,
"filename": "django_blacklist-0.7.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "107761b69ce51f228276081171cf73dc",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 9989,
"upload_time": "2022-12-07T23:15:11",
"upload_time_iso_8601": "2022-12-07T23:15:11.419494Z",
"url": "https://files.pythonhosted.org/packages/43/57/fa47ccf06bc4aaf099b17f3d8e77d6365e48a7c800bdbd59c85ea5b93789/django_blacklist-0.7.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "a7dffdb85fcc750547ba5767ced10d51",
"sha256": "e62f9e1274abde7c2c3fe22b5cce5e7c17bef436c5c2b74521f763b1dba5ac7a"
},
"downloads": -1,
"filename": "django-blacklist-0.7.0.tar.gz",
"has_sig": false,
"md5_digest": "a7dffdb85fcc750547ba5767ced10d51",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 10701,
"upload_time": "2022-12-07T23:15:14",
"upload_time_iso_8601": "2022-12-07T23:15:14.575931Z",
"url": "https://files.pythonhosted.org/packages/69/8b/b290c76547a536897b3a63c80ddba41b1a8544655fe5d37c7468f684edc1/django-blacklist-0.7.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-07 23:15:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "vsemionov",
"github_project": "django-blacklist",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "django-blacklist"
}