.. 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: 対応Pythonバージョン :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: 対応Djangoバージョン
.. 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: カバレッジ
.. image:: https://readthedocs.org/projects/django-defender/badge/?version=latest :alt: ドキュメントステータス :target: https://django-defender.readthedocs.io/en/latest/?badge=latest
ログイン試行のブルートフォース攻撃をブロックする、シンプルなDjango再利用可能アプリです。
目標は可能な限り高速に動作させることで、ログイン処理を遅くしないことです。
データベースへの問い合わせを毎回行わずに済むよう、キャッシュを使用します。最初のバージョンはRedisベースですが、将来的には設定可能にして、ユーザーが自身の環境に最適なバックエンドを選択できるようにすることを目指しています。
あなたのサイトでdefenderを使用している場合は、PRを送信してリストに追加してください。
ドキュメントはRead the Docsで公開されています:
https://django-defender.readthedocs.io
すべてのログイン試行をデータベースに記録
IPアドレスに異なるヘッダーを使用するリバースプロキシに対応
以下の条件に基づくレート制限
ブラックリストにRedisを使用
設定項目
Redisサーバー
ブロック時間
ブロック前の不正試行回数
コードカバレッジ95%
完全なドキュメント
ログイン試行をデータベースに保存する機能
ログイン試行データベーステーブルをクリーンアップする管理コマンド
管理ページ
カスタム認証方法に容易に適応可能
ユーザー名またはIPをブロックする際にシグナルが送信される
管理ページ
.. 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: 管理画面のスクリーンショット
.. 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: 管理画面のスクリーンショット
コードをダウンロードし、方法に応じて以下のいずれかの方法でセットアップを実行します。
PyPIからプロダクション対応バージョンをインストールする場合:
.. code-block:: bash
pip install django-defender
ソースコードから開発バージョンをインストールする場合(ダウンロード後):
.. code-block:: bash
python setup.py install
GitHubリポジトリからmasterブランチの開発バージョンをインストールする場合:
.. code-block:: bash
pip install -e git+http://github.com/kencochran django-defender.git#egg=django_defender-dev
まず、このプロジェクトを settings.py の INSTALLED_APPS リストに追加する必要があります。
.. code-block:: python
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', # ... 'defender', # ... ]
次に、FailedLoginMiddleware ミドルウェアをインストールします。
.. code-block:: python
MIDDLEWARE_CLASSES = [ 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'defender.middleware.FailedLoginMiddleware', ]
Django管理画面でブロックされたユーザーを管理したい場合は、以下の内容を 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... ]
マイグレーション
運用に必要なテーブルをデータベースに作成する必要があります。
.. code-block:: bash
python manage.py migrate defender
管理コマンド
cleanup_django_defender
トラフィックの多いウェブサイトでは、AccessAttempts テーブルがすぐに一杯になります。
データを監査目的で保持する必要がない場合は、テーブルをクリーンに保つための管理コマンドがあります。
このコマンドは、DEFENDER_ACCESS_ATTEMPT_EXPIRATION 設定を見て、どのレコードを削除するかを判断します。
指定がない場合のデフォルトは24時間です。
.. code-block:: bash
$ python manage.py cleanup_django_defender
これを日次または週次のcronジョブとして設定し、テーブルサイズを抑えることができます。
.. code-block:: bash
24 0 * * * /usr/bin/python manage.py cleanup_django_defender >> /var/log/django_defender_cleanup.log
パフォーマンス
defender の目標は、ログインプロセスを遅くしないよう可能な限り高速にすることです。
目標を達成しているか確認するため、アプリケーションをテストする方法が必要です。
最良の方法は、通常のDjangoログインとdefender、django-axesの速度を比較することです。
通常のDjangoログインがベースラインであり、追加のチェックがないため、3つの方法の中で最も高速であると予想されます。
defenderを使用したログインはおそらくDjangoログインより遅くなりますが、django-axesよりは高速であることを期待します。
目標は、通常の生のログインとdefenderとの差をできるだけ小さくすることです。
django-axesのログイン速度は、チェックが多くデータベースクエリも多いため、3つの中で最も遅くなるでしょう。
ログイン速度を測定する最良の方法は、各セットアップでアプリケーションに対して負荷テストを行い、各タイプのログイン時間を比較することです。
負荷テスト
すべてのタイプのログインをカバーするため、負荷テストでは複数のテストを行う必要があります。
#. すべて成功:成功ログインのみの負荷テスト。
#. 混合(一部成功、一部失敗):成功と失敗を混在させ、失敗がパフォーマンスに与える影響を確認。
#. すべて失敗:すべて失敗ログインの負荷テストで、パフォーマンスの違いを確認。
負荷テスト用のサンプルアプリケーションが必要で、唯一の違いはdefender、axes、またはどちらも使用しない設定のみとします。
ホスト型の負荷テストサービスやjmeterのようなツールを使用できます。
いずれの場合でも、すべてのテストで一貫性を保つ必要があります。
jmeterを使用する場合は、他の人が自分でテストを実行できるように、jmeterの設定ファイルも提供すべきです。
負荷テストの結果
結果はここに掲載します。各テストの説明と、結果をグラフとともに示します。
django-axesは優れていますが、すべてをデータベースに格納するため、データ量が多いとボトルネックになります。
認証リクエストが200〜300msも遅くなることがあります。
サイトによってはそれほど問題にならないかもしれませんが、他のサイトでは長すぎます。
これはdjango-axesのフォークとして始まり、可能な限りコードを再利用し、不要な部分を削除し、ルックアップを高速化してログインを改善しています。
#. 誰かがログインしようとすると、まずそのユーザーが現在ブロックされているかどうかを確認します。
使用しようとしているユーザー名とIPアドレスをチェックします。ブロックされていれば手順5へ。ブロックされていなければ手順2へ。
#. ブロックされていないので、ログインが有効かどうかを確認します。有効なら手順6へ。無効なら手順3へ。
#. ログイン試行が無効でした。この試行のユーザー名とIPアドレスをキャッシュに追加します。
これが制限を超えた場合、ブロックリストに追加し、手順5へ。制限を超えていない場合は手順4へ。
#. ログインは無効でしたが、制限を超えていません。ログイン画面に戻して再試行させます。
#. ユーザーがブロックされました:ブロックページに遷移させ、ブロックされていることと、ブロック解除の推定時間を伝えます。
#. ログインが有効です。失敗したログイン試行をリセットし、目的のページに転送します。
Defenderはキャッシュを使用して失敗した試行を保存します。
キャッシュキー
カウンター:
ブール値(存在すればブロック中):
django-defender を少しカスタマイズするためのオプションがいくつか用意されています。
これらは settings.py で定義してください。