
A simple super fast django reusable app that blocks people from brute forcing login attempts
.. image:: https://jazzband.co/static/img/badge.svg :target: https://jazzband.co/ :alt: Jazzband
.. image:: https://img.shields.io/pypi/pyversions/django-defender.svg :alt: Supported Python versions :target: https://pypi.org/project/django-defender/
.. image:: https://img.shields.io/pypi/djversions/django-defender.svg :target: https://pypi.org/project/django-defender/ :alt: Supported Django versions
.. image:: https://github.com/jazzband/django-defender/workflows/Test/badge.svg :target: https://github.com/jazzband/django-defender/actions :alt: GitHub Actions
.. image:: https://codecov.io/gh/jazzband/django-defender/branch/master/graph/badge.svg :target: https://codecov.io/gh/jazzband/django-defender :alt: Coverage
.. image:: https://readthedocs.org/projects/django-defender/badge/?version=latest :alt: Documentation Status :target: https://django-defender.readthedocs.io/en/latest/?badge=latest
A simple Django reusable app that blocks people from brute forcing login attempts. The goal is to make this as fast as possible, so that we do not slow down the login attempts.
We will use a cache so that it doesn't have to hit the database in order to check the database on each login attempt. The first version will be based on Redis, but the goal is to make this configurable so that people can use whatever backend best fits their needs.
If you are using defender on your site, submit a PR to add to the list.
Documentation is available on Read the Docs:
https://django-defender.readthedocs.io
Log all login attempts to the database
Support for reverse proxies with different headers for IP addresses
Rate limit based on
Use Redis for the blacklist
Configuration
Redis server
Block length
Number of incorrect attempts before block
95% code coverage
Full documentation
Ability to store login attempts to the database
Management command to clean up login attempts database table
Admin pages
Can be easily adapted to custom authentication method.
Signals are sent when blocking username or IP
Admin pages
.. image:: https://cloud.githubusercontent.com/assets/261601/5950540/8895b570-a729-11e4-9dc3-6b00e46c8043.png :target: https://cloud.githubusercontent.com/assets/261601/5950540/8895b570-a729-11e4-9dc3-6b00e46c8043.png :alt: alt tag
.. image:: https://cloud.githubusercontent.com/assets/261601/5950541/88a35194-a729-11e4-981b-3a55b44ef9d5.png :target: https://cloud.githubusercontent.com/assets/261601/5950541/88a35194-a729-11e4-981b-3a55b44ef9d5.png :alt: alt tag
Download code, and run setup in one of the following ways depending on the method.
To install the production ready version from PyPI:
.. code-block:: bash
pip install django-defender
To install the development version from source code after download:
.. code-block:: bash
python setup.py install
To install the master branch development version from the GitHub repository:
.. code-block:: bash
pip install -e git+http://github.com/kencochran django-defender.git#egg=django_defender-dev
First of all, you must add this project to your list of INSTALLED_APPS in
settings.py
.. code-block:: python
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', # ... 'defender', # ... ]
Next, install the FailedLoginMiddleware middleware
.. code-block:: python
MIDDLEWARE_CLASSES = [ 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'defender.middleware.FailedLoginMiddleware', ]
If you want to manage the blocked users via the Django admin, then add the
following to your urls.py
.. code-block:: python
urlpatterns = [ path('admin/defender/', include('defender.urls')), # defender admin path('admin/', admin.site.urls), # normal admin # your own patterns follow... ]
Migrations
You will need to create tables in your database that are necessary for operation.
.. code-block:: bash
python manage.py migrate defender
Management commands
cleanup_django_defender
If you have a website with a lot of traffic, the AccessAttempts table will get full pretty quickly. If you don't need to keep the data for auditing purposes there is a management command to help you keep it clean.
It will look at your DEFENDER_ACCESS_ATTEMPT_EXPIRATION setting to determine
which records will be deleted. Default if not specified, is 24 hours.
.. code-block:: bash
$ python manage.py cleanup_django_defender
You can set this up as a daily or weekly cron job to keep the table size down.
.. code-block:: bash
24 0 * * * /usr/bin/python manage.py cleanup_django_defender >> /var/log/django_defender_cleanup.log
Performance
The goal of defender is to make it as fast as possible so that it doesn't slow down the login process. In order to make sure our goals are met we need a way to test the application to make sure we are on the right track. The best way to do this is to compare how fast a normal Django login takes with defender and django-axes.
The normal django login, would be our baseline, and we expect it to be the fastest of the 3 methods, because there are no additional checks happening.
The defender login would most likely be slower then the django login, and hopefully faster then the django-axes login. The goal is to make it as little of a difference between the regular raw login, and defender.
The django-axes login speed, will probably be the slowest of the three since it does more checks and does a lot of database queries.
The best way to determine the speed of a login is to do a load test against an application with each setup, and compare the login times for each type.
Load testing
In order to make sure we cover all the different types of logins, in our load test we need to have more then one test.
#. All success: We will do a load test with nothing but successful logins.
#. Mixed: some success some failure: We will load test with some successful logins and some failures to see how the failure effect the performance.
#. All Failures: We will load test with all failure logins and see the difference in performance.
We will need a sample application that we can use for the load test, with the only difference is the configuration where we either load defender, axes, or none of them.
We can use a hosted load testing service, or something like jmeter. Either way we need to be consistent for all of the tests. If we use jmeter, we should have our jmeter configuration for others to run the tests on their own.