0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Djangoで「Invalid HTTP_HOST header: 'xxx'」が発生する

0
Posted at

事象

独自ドメインや新しいホスト名でDjangoアプリケーションにアクセスしたところ、画面上に「Bad Request (400)」が表示され、サーバー側のログに次のエラーが出力された。

Invalid HTTP_HOST header: 'example.com'. You may need to add 'example.com' to ALLOWED_HOSTS.
Traceback (most recent call last):
  ...
django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'example.com'. You may need to add 'example.com' to ALLOWED_HOSTS.

環境

  • Python 3.x
  • Django 3.x / 4.x / 5.x
  • Nginx(リバースプロキシ)
  • Gunicorn / uWSGI / Docker

原因

主な原因は次の2つである。

1. ALLOWED_HOSTS にアクセス元のホスト名が登録されていない

DjangoはHTTP Hostヘッダーインジェクション攻撃を防ぐため、settings.pyALLOWED_HOSTS に登録されていないホスト名からのリクエストをすべて拒否する仕様になっている。
本番環境で独自ドメインを割り当てた直後や、ロードバランサー・リバースプロキシを経由させた際に追加を忘れていると発生する。

2. ALLOWED_HOSTS の書き方が誤っている(URL全体を指定している)

ALLOWED_HOSTS にはホスト名(FQDN)またはIPアドレスのみを指定する必要がある。
よくある間違いとして、プロトコル(http://https://)や末尾のスラッシュ、ポート番号を含めてしまうケースがある。

# ❌ よくある間違い
ALLOWED_HOSTS = [
    "https://example.com/",  # スキームや末尾スラッシュは不可
    "http://example.com",    # スキームは不可
]

これらはドメイン名として正しくパースされず、マッチしないためエラーが解消しない。

対策

1. settings.pyALLOWED_HOSTS を正しく設定する

スキームやスラッシュを除いたホスト名のみを配列に設定する。

# settings.py

ALLOWED_HOSTS = [
    "example.com",
    "www.example.com",
    "127.0.0.1",       # 内部通信やヘルスチェック用
    "localhost",
]

任意のサブドメインを許可したい場合は、先頭にピリオドを付けるかワイルドカードを利用する。

# .example.com と書くと example.com および そのすべてのサブドメインにマッチする
ALLOWED_HOSTS = [
    ".example.com",
]

2. リバースプロキシ(Nginx)の Host ヘッダー転送を確認する

Nginxなどを経由している場合、Nginx側でクライアントがリクエストしたホスト名をDjangoにそのまま渡すよう設定されているか確認する。

# nginx.conf

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;  # クライアントのリクエストHostを転送
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

3. Djangoアプリケーションを再起動する

settings.py の変更は、Djangoプロセス(Gunicorn/uWSGI等)を再起動しないと反映されない。Nginxのリロードだけでは反映されない点に注意する。

# Gunicornを手動/systemdで動かしている場合
sudo systemctl restart gunicorn

# Docker Compose環境の場合
docker compose restart web

4. 動作確認

ブラウザまたは curl からアクセスし、正常なステータスコード(200など)が返ることを確認する。

curl -I https://example.com/

エラーログに DisallowedHost が出力されなくなっていれば対応完了である。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?