web-dev-qa-db-ja.com

NGINXプロキシがWebSocketに渡され、PHP SSLで機能しない

次の方法でNginxでリクエストをrouteしようとしています:

  1. /に対して行われたリクエストは、PHPスクリプト(proxy.php、それ自体がプロキシ)に送信する必要があります)
  2. /websocketへのリクエストはhttp://localhost:4000/websocketにプロキシする必要があります
  3. 他のすべてのリクエストはhttp://localhost:4000/にプロキシする必要があります

私は2。を次の設定を使用して動作させることができます:

server {
    listen 443 ssl;

    server_name proxy.domain.com;

    ssl_certificate /etc/nginx/ssl/proxy.domain.com/468446/server.crt;
    ssl_certificate_key /etc/nginx/ssl/proxy.domain.com/468446/server.key;

    location = /websocket/ {
        proxy_pass http://127.0.0.1:4000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_Host;
        proxy_pass         http://127.0.0.1:4000;
    }

}

それから私は1。を追加する方法を見つけようとし、次のことを思いつきました:

server {
    listen 443 ssl;

    server_name proxy.domain.com;

    root /var/www/dowmain;

    ssl_certificate /etc/nginx/ssl/proxy.domain.com/468446/server.crt;
    ssl_certificate_key /etc/nginx/ssl/proxy.domain.com/468446/server.key;

    location = /websocket/ {
        proxy_pass http://127.0.0.1:4000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_Host;
        proxy_pass         http://127.0.0.1:4000;
    }

    location = / {
        include fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME  $document_root/proxy.php;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }

}

ただし、この構成では、2。は機能しなくなります。 /websocketに対して行われたリクエストは、PHPスクリプトによって処理されます。/websocketlocationブロックが機能しなくなったようです。

興味深いことに、構成をhttp://に切り替えると、すべてが正常に機能します。

私が間違っていることについて何か考えはありますか?

更新

location /websocket { ... }ブロック内のPHP config stuffをlocation = / { ... }ブロックのルールで置き換えると、正常に機能しますが、location / { ... }を問題の原因として除外できると思います私が必要としているものではありません)。だから私はPHPを疑っています。

更新II

mkcertからの証明書を使用して、まったく同じ構成でローカルマシンでも機能します。

したがって、唯一の違いは、Let's Encrypt証明書とローカル証明書の違いです。 NginxとPHPバージョンは基本的に同じです(PHP 7.2.7、ローカルマシン上のNginx 1.15.1とPHP 7.2.13、 Nginx 1.15.6)

2
Rico Leuthold

Proxy_passディレクティブを含む場所の末尾のスラッシュに問題があるようです。 WebSocketの場所に追加してみてください。

location /websocket/ {
    proxy_pass http://127.0.0.1:4000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

また、 this のため、URIの「/ webconfig」の部分を「/ webconfig /」に置き換えているため、proxy_passディレクティブから/ websocket /を削除しました混乱しています

Proxy_passディレクティブがURIで指定されている場合、要求がサーバーに渡されると、場所に一致する正規化された要求URIの部分が、ディレクティブで指定されたURIに置き換えられます。

主な質問へ- Nginxドキュメントに基づいて

場所がスラッシュ文字で終わるプレフィックス文字列で定義されており、リクエストがproxy_pass、fastcgi_pass、uwsgi_pass、scgi_pass、memcached_pa​​ss、またはgrpc_passのいずれかによって処理される場合、特別な処理が実行されます。この文字列と等しいURIを持つが、末尾にスラッシュがない要求に応答して、コード301の永続的なリダイレクトが、スラッシュが追加された要求されたURIに返されます。

あなたの場合、websocketの場所には末尾のスラッシュがなく、このルールによって/場所に301リダイレクトされていると思います。

3
Shanjohn

あなたの設定は私にはうまく見えます、私は私のnginxセットアップでそれを再確認しました、そしてそれはそれがする必要があることをします。さまざまな場所にヘッダーを追加して確認しました。

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name proxy.domain.com;
    root /var/www/dowmain;

    ssl_certificate /etc/nginx/ssl/proxy.domain.com/468446/server.crt;
    ssl_certificate_key /etc/nginx/ssl/proxy.domain.com/468446/server.key;

    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/nginx/dhparams.pem;

    location /websocket {
        proxy_pass http://127.0.0.1:4000/websocket/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        add_header X-location websocket always;
    }

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_Host;
        proxy_pass         http://127.0.0.1:4000;
        add_header X-location wildcard always;
    }

    location = / {
        include fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME  $document_root/proxy.php;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        add_header X-location root always;
    }
}

次に、ヘッダーを次のように検査します。

$ curl -I https://proxy.domain.com
$ curl -I https://proxy.domain.com/anythingelse
$ curl -I https://proxy.domain.com/websocket

出力には以下が含まれている必要があります:

X-location: websocket
X-location: wildcard
X-location: root

X-locationの値は、そのブロックのnginx構成で設定したものと一致する必要があります。

私のnginxバージョンは次のとおりです。

# nginx -v
nginx version: nginx/1.10.1
1
Chone