web-dev-qa-db-ja.com

単一サーバー(およびそれ以降)のnginxリバースプロキシ構成の何が問題になっていますか

Nginxリバースプロキシの設定を機能させようとしています。 2つのWebサーバーがセットアップされています。1つはnginxで、もう1つはApache2です。私は現在、nginxサーバーだけでは機能しないので、今やろうとしていることはこれだけですが、セットアップに影響する場合に備えて、結局2つを試してみることを追加しました。

このセットアップでは4台のマシンを使用しています。


1。クライアントマシン

192.168.0.5

Ubuntu 14.04デスクトップ


2。リバースプロキシサーバー

192.168.0.10

nginx 1.4.6

Ubuntu 14.04サーバー


3。サーバー1

192.168.0.15

server1.mydomain.com

nginx 1.4.6

Ubuntu 14.04サーバー


4。サーバー2

192.168.0.20

server2.mydomain.com

Apache2

Ubuntu 14.04サーバー


以下のように、クライアントマシンで、各Webサーバーのリバースプロキシサーバーを指すようにhostsファイルを設定しました

/ etc/hostsクライアント上192.168.0.5 127.0.0.1 localhost 192.168.0.10 server1.mydomain.com 192.168.0.10 server2.mydomain.com

Server1とserver2のssl証明書があり、リバースプロキシサーバー(192.168.0.10)に配置しました。それらをserver1.crt、server1.key、およびserver2.crt、server2.keyと呼びます。

私はこのように動作する証明書でこの設定をしなければならないと私は信じています:

client(192.168.0.5) ---https---> reverseProxy(192.168.0.10 holds ssl certs) ---http---> server1 or server2 

現在、両方のサーバーがhttpで動作しており、nginxリバースプロキシ設定を192.168.0.10に修正するだけです。

これが私が試したものですが、正しくリダイレ​​クトされていません。もう一度、リバースプロキシサーバーへのhttps接続と、リバースプロキシとサーバー間のhttp接続が必要です。

/ etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

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

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_Ruby /usr/bin/Ruby;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

/ etc/nginx/sites-available/default

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
    }

server {
    listen 443;
    server_name server1.mydomain.com;

    ssl on;
    ssl_certificate /usr/local/nginx/conf/server1.crt;
    ssl_certificate_key /usr/local/nginx/conf/server1.key;
    ssl_session_cache shared:SSL:10m;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;

    location / {
            proxy_pass http://192.168.0.15:80;
            proxy_set_header Host server1;

            proxy_redirect http:// https://;
    }
}

私の/etc/nginx/sites-available/defaultファイルに問題があると思いますが、いくつかのチュートリアルを読んでいますが、これはかなり近いようです。この設定は明らかにserver1でのみ試行し、server2を無視しますが、1つの作業を取得できれば、必要なだけ他の作業を追加できると想定しました。 this oneなどの同様の質問を見つけましたが、この構成を単一のサーバーで動作させることはできません。

現在何が起こっているのか

現在、server1.mydomain.comにアクセスすると、リバースプロキシサーバー(192.168.0.10から標準 "Welcome to nginx!"ページが表示されます。 )。転送は行われていません。

近づいてる?前もって感謝します


EDIT1

Capileが投稿した解決策を試した後、別の問題に遭遇しました(これは、私よりもWebの知識が豊富な誰かによって予期されていた可能性があります)。

/etc/nginx/sites-available/defaultファイルを次のように変更した場合:

/ etc/nginx/sites-available/default(リバースプロキシ上)

server {

        listen 80 default_server;
        listen 443 ssl default_server;
        server_name server1.mydomain.com;

        ssl on;
        ssl_certificate /usr/local/nginx/conf/server1.com.crt;
        ssl_certificate_key /usr/local/nginx/conf/server1.com.key;
        ssl_session_cache shared:SSL:10m;

        ssl_session_timeout 5m;

        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
        ssl_prefer_server_ciphers on;

        location / {
                proxy_pass http://192.168.0.15:80;
                proxy_set_header Host server1;

                proxy_redirect http:// https://;
        }
}

この構成では、

400不正なリクエスト

プレーンHTTPリクエストがHTTPSポートに送信されました

たぶんhttps://server1.mydomain.comを試してみるべきだと思いましたが、それはただ回転します。

また、両方のサーバーに同じssl証明書を使用してもかまいません。それは問題にならないと思います。


EDIT2

まず初めに、すべての助けに感謝します。

Capileの推奨に従ってssl on;行を削除し、Richard Smithの推奨に従ってproxy_redirect http:// https://;行をproxy_redirect http:// $scheme://;に変更しました。

これにより、httpトラフィックの不正なリクエストが修正されました。したがって、http://server1.mydomain.comにアクセスすると、サイト(yaay !)

https://server1.mydomain.comにアクセスしようとすると、リダイレクトされますが、 接続できませんエラーが発生します。これは、リバースプロキシがhttpトラフィックをhttpに転送し、httpsトラフィックをhttpsに転送する場合に意味があります。これは、バックエンドサーバーのhttps構成がないためです。

私の目標は、 http://server1.domain.com にアクセスすると、httpsを使用してリバースプロキシに接続し、httpを使用してバックエンドサーバーに転送することです。それは起こっているようには見えません...それはhttpsを使用せずにそれを転送しているようです。

一方、 https://server1.domain.com にアクセスすると、httpsを使用してリバースプロキシに接続し、httpを使用してバックエンドサーバーに転送します。

したがって、クライアントからリバースプロキシサーバーへのhttp接続は必要ありません。

カールは期待どおりに機能しています。 httpまたはhttpsサイトをカールすると、次のようになります。

curl -i https://server1.mydomain.comまたはcurl -i http://server1.mydomain.com

HTTP/1.1 302 Found
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 21 Jan 2016 16:34:29 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 92
Connection: keep-alive
Cache-Control: no-cache
Location: http://test1/users/sign_in
Set-Cookie: session=336e109ad711; path=/; expires=Thu, 28 Jan 2016 16:34:36 -0000; HttpOnly
Status: 302 Found
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: ad65f-f6ds204-9fs8d-bdsdfa43-df5583266sdf87
X-Runtime: 0.005358
X-Xss-Protection: 1; mode=block

<html><body>You are being <a href="http://test1/users/sign_in">redirected</a>.</body></html>

したがって、リダイレクトはどちらのタイプの接続でも確実に発生していますが、クライアントとリバースプロキシサーバー間のhttps接続のSSL証明書が使用されているとは思いません。

3
trueCamelType

あなたは近くにいますが、httpにはリバースプロキシが設定されておらず、https(上記の設定)にのみ設定されているため、ドキュメントルートのデフォルトのコンテンツが表示されます。最初のサーバーにも末尾の}がありません。

同じブロックでhttpとhttpsの両方を設定できます。listenディレクティブでsslキーワードを使用するだけです(sslポートの下にあるため、ssl onディレクティブを設定する必要はありません)。

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    ...
    ssl_certificate /usr/local/nginx/conf/server1.crt;
    ssl_certificate_key /usr/local/nginx/conf/server1.key;
    ssl_session_cache shared:SSL:10m;
...

同じIP内で2つの異なるSSL証明書を使用することは多少制限があり複雑であることを警告する必要があります。これは、HTTPの再ネゴシエーションが必要になるためです(適切なホストを要求する前に、要求を証明書で暗号化する必要があるため)。証明書をserverブロックで区切る必要があります。これには、IPによるより具体的なlistenを使用します。

server {
    listen 192.168.0.10:443 ssl; # for server1.mydomain.com
...

server {
    listen 192.168.0.11:443 ssl; # for server2.mydomain.com
...

また、SSLセキュリティのベストプラクティスとして Mozilla SSL Config Generator を使用することをお勧めします。

編集1

400エラーを回避するには、ディレクティブssl on;を削除してリロードします。これにより、httpトラフィックにSSLが必要になりました—既にラインでsslを使用するように指示されています:listen 443ssldefault_server;(これは、このポートでsslをオンにすることを意味します)。

残りの構成は問題ありませんが、サーバーの応答によっては、プロキシ設定を調整する必要がある場合があります。

まず、回転がクライアント側かサーバー側かを確認します。cURLでアクセスするか、ブラウザーでWeb開発者ツールをオンにしてネットワークを確認します:ブラウザがリダイレクトされている場合は、proxy_redirectを調整するか、サーバーの応答で文字列を置き換える必要があります。

この方法でcURLを確認します。

curl -i http://server1.mydomain.com

応答にLocation:ヘッダーが表示される場合は、プロキシ設定を微調整する必要があります(応答によって異なります)。たとえば、httpsとしてアクセスしている場合、プロキシはhttpとして転送し、バックエンドサーバーアプリケーションはhttpsにリダイレクトします(ただし、応答がプロキシを通過すると、ブラウザーにhttpに戻ります)。 proxy_set_headerを使用したり、バックエンドサーバーを調整したりするなど、いくつかの方法で修正できます。

たとえば、次のように使用できます。

proxy_set_header X-Forwarded-Proto $scheme;

しかし、バックエンドのhttpサーバーかアプリケーションのどちらかがこれを正しく理解する必要があります。


または、リダイレクトがなく、応答もない場合(またはリクエストタイムアウト後のゲートウェイ応答がない場合-30秒)、バックエンドサーバーがプロキシサーバーに適切に応答しているかどうかを確認します。

また、バックエンドにhttpサーバーが必要ないことに注意してください。たとえば、FastCGIサーバーを直接使用できます。これにより、ダウンフォールが少なくなる場合があります。


EDIT2

CURL応答に基づいて、構成が期待どおりに機能していることがわかります。バックエンドサーバーの応答がサインインを要求しています。SSL証明書が機能していない場合、curl -i https://server1.mydomain.comを実行できません。

フロントエンド(プロキシ)とバックエンドの間のトラフィックはhttpのみを介して行われ(proxy_passディレクティブを参照)、通常はそれも予想されます(別の暗号化は不要なオーバーヘッドを追加する可能性があります)。

Httpsのみを使用する場合は、2つのオプションがあります。バックエンドで構成するか、https://に転送するようにします。 test1/users/sign_in)またはnginxに別の設定を使用します。http:80サーバーを削除して、すべてをhttps:443にリダイレクトします。次のようなもの(次のサーバーブロックからlisten 80を必ず削除してください):

server {
    listen 80 default;
    server_name  _;
    return 301 https://$Host$request_uri;
}

server {
    listen 443 ssl;
... 
1
Capilé

新しい(EDIT1)構成では、http(httpsではなく)を使用したマシン#2へのアクセスはすべてプロキシされます。これにより、元の「nginxへようこそ!」が削除されます。 (おそらく)httpスキームへのリダイレクトによって引き起こされた副作用。

次に進むと、問題の根本はマシン#3(実サーバー1)がリダイレクトを生成し、クライアントに戻るまでに正しくマッピングされていないことにあると思います。

相互作用を完全に理解するために、マシン#2とマシン#3のアクセスログを確認することができます。各インタラクションで使用されるスキーム(httpとhttps)を理解するために、 log format を調整する必要がある場合があります。

proxy_redirectを一時的に無効にして、クライアントで開発者ツールを使用して、マシン#3がhttp 3xx応答で発行しているURLを正確に理解できるようにすることができます。

両方のスキームをプロキシしているため、proxy_redirectディレクティブはEDIT1構成では間違っているため、これがより適切な場合があります。

proxy_redirect http:// $scheme://

そうは言っても、より具体的なproxy_redirectが適切な場合があります。 ドキュメント の状態では、複数のproxy_redirect rules. I am not an expert onproxy_redirect`ルールを使用できますが、次のような結果になる可能性があります。

proxy_pass http://192.168.0.15;
proxy_set_header Host server1;
proxy_redirect http://192.168.0.15 $scheme://
proxy_redirect http://server1 $scheme://
1
Richard Smith