16

私は、djangoアプリの前にnginxを置いたかなり標準的なセットアップをしています。django アプリを SSL のみにしたいので、nginx conf に 2 つのリッスン ブロックがあり、ポート 80 (HTTP) で着信するトラフィックはポート 443 (SSL) にリダイレクトされます。これは期待どおりに機能しています。

ポート フォワーディングがオンになっている VM 内でこのセットアップを実行しているため、ホスト マシンからポート 8080 (HTTP) または 8081 (SSL) にアクセスしてサイトを参照できます。繰り返しますが、これは正常に機能します。

問題は、登録ワークフロー中に Django アプリから内部的にリダイレクトされたときに発生します。Django は SSL ステータスを認識しないため (SSL は nginx で終了し、アプリへのトラフィックは HTTP 経由でポート 5000 に転送されます)、ポートは認識されるため、リダイレクトは混乱します**。

これらすべての最終的な結果は、トラフィックが SSL ポートで nginx に向けられていることです。これは SSL ではありませんhttp://127.0.0.1:443/。これを処理するためにnginxを構成する方法はありますか?

** NB Nginx で X-Forwarded-Proto ヘッダーを設定しています。Django は正しい .is_secure() 値を取得しています。これは、外部ライブラリが is_secure をチェックせず、着信 URL スキームをリダイレクトするだけの特定の問題です。

[更新 1]

関連する構成設定が添付されています。これは Vagrantfile 自体からのもので、ポート転送を示しています。

config.vm.forward_port 80, 8080     # website, via nginx (redirects to SSL:8081)
config.vm.forward_port 443, 8081    # website, via nginx (accepts SSL)
config.vm.forward_port 5000, 8180   # website, via gunicorn (direct)

上記のポート転送構成を使用して、ホスト マシンのサイトを HTTP ポート (8080) で参照すると、要求が受け入れられ、nginx (以下を参照) がこの要求を HTTPS (ポート 8081 で実行) にリダイレクトします。HTTPS を使用すると、サイト自体は正常に動作します。

(host) http://127.0.0.1:8080  -> forwarded to -> (guest vm) http://127.0.0.1:80  
(host) https://127.0.0.1:8081 -> forwarded to -> (guest vm) https://127.0.0.1:443

この問題は、スキームとプロトコルを混合した Django から内部的にリダイレクトを取得し、http:\\127.0.0.1:8081\...nginx が 8081 のトラフィックが SSL であると想定しているため、失敗する へのリクエストで終わるときに発生します。

私が本当に欲しいのは、「SSL と非 SSL の両方で 443 をリッスンし、非 SSL をリダイレクトする」というルールです。

これは、関連する nginx 構成です。

# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
    server 127.0.0.1:5000 fail_timeout=0;
}

server {
    listen 80;
    # 8081 is the port I am forwarding to on the host machine
    rewrite ^ https://127.0.0.1:8081$request_uri? permanent;
}

server {
    listen 443;

    ssl on;
    ssl_protocols       SSLv3 TLSv1;
    ssl_ciphers         HIGH:!ADH:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_certificate     /etc/nginx/ssl/self-signed.crt;
    ssl_certificate_key /etc/nginx/ssl/self-signed.key;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /static/ {
        alias /app/static/;
    }
    location /media/ {
        alias /app/media/;
    }
    location / {
        # everything else is to be served by the django app (upstream 'gunicorn')
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # this is set to ensure that django is_secure returns True
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_pass http://gunicorn;
    }
}
4

1 に答える 1

28

このドキュメントの「エラー処理」セクションを確認する必要があります。

http://nginx.org/en/docs/http/ngx_http_ssl_module.html

非標準のエラーコード497を使用して、HTTPSポートに送信されたプレーンなHTTPリクエストを処理できます。

このようなものは機能するはずです(テストされていません):

error_page 497 https://$host$request_uri;

名前付きの場所はerror_pageでも使用できます。詳細については、http://nginx.org/r/error_pageを参照てください。

于 2013-01-09T15:54:54.700 に答える