ユーニックス総合研究所

  • home
  • archives
  • django-allowed-hosts

DjangoのALLOWED_HOSTSの役割と使い方

  • 作成日: 2021-01-11
  • 更新日: 2023-12-24
  • カテゴリ: Django

DjangoのALLOWED_HOSTSの役割と使い方

PythonのWebフレームワークであるDjango(ジャンゴ)には数々のセキュリティ対策が実装されています。
settings.py内に設定するALLOWED_HOSTSというリストもそのセキュリティ対策の一部です。

この記事ではALLOWED_HOSTSの役割と使い方を解説します。

具体的には↓を見ていきます。

  • ALLOWED_HOSTSの役割
  • ALLOWED_HOSTSの仕組み
  • ALLOWED_HOSTSの使い方
  • ソースコードの解析

ALLOWED_HOSTSの役割

Djangoのプロジェクトのsettings.pyに書かれれるALLOWED_HOSTSは、HTTPのホスト・ヘッダー攻撃を防ぐためのリストです。
このリストにコンテンツを配信するサーバー自身のホスト名を書くことで、そのホスト名がホワイトリストの役割をして外部からの攻撃を防ぎます。

ホスト・ヘッダー攻撃とはたとえば↓のような攻撃です。

  • クロスサイトリクエストフォージェリ
  • キャッシュポイズニング攻撃
  • メール内のポイゾニングリンク

ALLOWED_HOSTSの仕組み

ALLOWED_HOSTSのデフォルト値は空のリスト([])です。

ALLOWED_HOSTSの値はdjango.http.HttpRequest.get_host()メソッド内で参照されます。
django.http.HttpRequest.get_host()メソッドは内部でALLOWED_HOSTSをホワイトリストとして参照し、現在のリクエストのホストとのバリデーションを行います。
バリデーションに失敗した場合はSuspiciousOperationを発生させます。

ALLOWED_HOSTSのリスト内の値は文字列です。
この文字列はFQDN(完全修飾名: 例 www.example.com)で記述することが出来ます。
この場合はバリデーション時にリクエストのホストヘッダーと正確にマッチを行います。
大文字小文字を区別せず、ポートは含めません。

ピリオドで始まる値をサブドメインのワイルドカードとして使えます。
たとえば.example.comなどです。この値はexample.comwww.example.com、またexample.comのサブドメインにそれぞれマッチします。
この場合、ホストヘッダの検証はミドルウェアなどを使って自分で行う必要があります。

DEBUGTrueでかつALLOWED_HOSTSが空のリストの場合はdjango.http.HttpRequest.get_host().localhost, 127.0.0.1, [::1]]を使ったバリデーションを行います。

また値にはワイルドカード(*)を使うことも出来ます。

ALLOWED_HOSTSの使い方

開発環境の場合のドメインはlocalhostが多いと思います。
ですので開発環境下に限定したい場合はALLOWED_HOSTSの記述は↓のようになります。

ALLOWED_HOSTS = [  
    'localhost',  
    'www.localhost',  
]  

配信中のサービスがexample.comで開発環境も考慮する場合は↓のようになります。

ALLOWED_HOSTS = [  
    'example.com',  
    'www.example.com',  
    'localhost',  
    'www.localhost',  
]  

また、ワイルドカードを使ってすべてのホストを許可することも出来ます。

ALLOWED_HOSTS = ['*']  

ソースコードの解析

django.http.HttpRequest.get_host()のコードを見てみます。

コードを見るとsettings.pyALLOWED_HOSTSが参照されているのがわかります。
また、DEBUGTrueでかつALLOWED_HOSTSが空の場合はallowed_hosts = ['.localhost', '127.0.0.1', '[::1]']でホストのリストを初期化しています。
その後にリクエストのホストをポートとドメインに分割し、ドメイン部分のみにallowed_hostsを使ってバリデートしています。
バリデートに成功した場合はリクエストのホスト名を返し、失敗した場合はDisallowedHostオブジェクトを返しています。
エラー内容は↓のいずれかになります。

  • Invalid HTTP_HOST header: ホスト名. You may need to add ドメイン名 to ALLOWED_HOSTS.
  • Invalid HTTP_HOST header: ホスト名. The domain name provided is not valid according to RFC 1034/1035.

おわりに

今回はDjangoのALLOWED_HOSTSを見て見ました。
入門初期から認識が必要になるリストですが、その実体についてはけっこうあいまいに覚えてる人も多いのではないでしょうか。

🦝 < ピッピ! 君はだめ。君はOK

🐭 < ホストの番人ALLOWED_HOSTS