web-dev-qa-db-ja.com

Nginx WebSocketリバースプロキシが101ではなく200を返す

私は現在、個人サーバーで hack.chat を機能させようとしています。

要するに、2つのサーバーで構成されています。 1つ目は、JavaScriptとCSSを提供する単純なhttpdサーバーです。 2つ目のチャットシステムは、javascriptがwebsocketを使用して接続するnode.jsサーバーです。そして、ここに問題があります。

Nginxの別のサーバーブロックを使用して、すべてが単一のIPで異なるドメイン名を持つポート80を使用するようにします。

私は The Nginx websocket doc に従いましたが、これは機能しません。 WebSocketが接続しようとすると、常に200の戻りコードが返されますが、よく理解している場合は101(スイッチングプロトコル)が返されます。

Nginxのバージョンは1.8.0で、サーバーはLinux 4.0.5を使用するgentooで実行されています

以下は、関連するnginx confファイルのダンプです。

nginx.conf:

user nginx nginx;
worker_processes 1;

error_log /var/log/nginx/error_log info;

events {
    worker_connections 1024;
    use epoll;
}

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

    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $bytes_sent '
        '"$http_referer" "$http_user_agent" '
        '"$gzip_ratio"';

    client_header_timeout 10m;
    client_body_timeout 10m;
    send_timeout 10m;

    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 2k;
    request_pool_size 4k;

    gzip on;
    gzip_min_length 1100;
    gzip_buffers 4 8k;
    gzip_types text/plain;

    output_buffers 1 32k;
    postpone_output 1460;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 75 20;

    ignore_invalid_headers on;

    include /etc/nginx/sites-enabled/*;
}

サイト対応/チャット:

map $http_upgrade $connection_upgrade{
    default upgrade;
    ''  close;
}

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

    location / {
        proxy_pass http://127.0.0.1:6060;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

Access_logを見ると、200応答が効果的に示され、error_logにエラーはありません。残念ながら、node.jsサーバーはログを提供しません(またはログを表示する方法がわかりません)。

よろしくお願いします。

[〜#〜]編集[〜#〜]

Thxからmc0eまで、私はhack.chatサーバーに101を応答させることができました。nginxとnode.jsの間で実際に何が発生するかを直接接続で発生するものと比較することにより、直接ヘッダーアップグレードでwebsocketが設定されているのにnginxはそうであることがわかりましたない。だから私は私のサイトが有効になっている/チャットを修正しました:

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

    location / {
        proxy_pass http://127.0.0.1:6060;
        proxy_http_version 1.1;
        proxy_set_header Upgrade "websocket";
        proxy_set_header Connection "Upgrade";
    }

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

アップグレードの代わりに接続ヘッダーを閉じるように設定するために使用していたため、マップブロックも削除しました。

それでも動作しません。 hack.chatは、接続:アップグレードとアップグレード:websocketで101を返しますが、nginxは、接続:キープアライブ(Firefoxで表示されるもの)で101を返します:/

[〜#〜]編集[〜#〜]

Nginx通信でngrepを行いましたが、hack.chatが彼に返送したパケットを送信し、Firefoxはクロスオリジンについて不平を言っています。クロスオリジンを避けようと思います。

最終編集

家に帰ってきたので、テストを行ってみました。私の最後の問題が私の作業プロキシのせいだったことにかなり驚きますが、それがキャッシュであるか、そうでなければすべてが役に立たなかったことを願いましょう。

これがクロスオリジンを回避する私の最後のconfです:

server{
        listen 0.0.0.0:80;
        server_name chat.axellink.fr;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_Host;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://127.0.0.1:8081;
        }

        location /chat/ {
                proxy_pass http://127.0.0.1:6060;
                proxy_http_version 1.1;
                proxy_set_header Upgrade "websocket";
                proxy_set_header Connection "Upgrade";
        }

        access_log /var/log/nginx/chat_access;
        error_log /var/log/nginx/chat_error debug;
}
7
axellink

Nginx websocketドックを読んだところ、nginxプロキシがUpgradeヘッダーを検出すると、それをhack.chatに渡します。その後、hack.chatは101応答で応答する必要があります。

まず、実際のHTTPトランザクションとhack.chatトランザクションをデバッグできるようにして、問題がクライアントアプリにあるのか、Webサーバーにあるのか、hack.chat通信にあるのかを確認します。これにより、正確なHTTP応答を取得することもできます。これは、現在取得方法がわからないというものです。ただし、問題がサーバー側にある場合は、何が問題かをより詳細に記録したいと考えている可能性があります。

Tcpdumpまたはngrepを使用して、httpトラフィックをキャプチャできます。 ngrepに行きます。このようにすると、端末に出力が表示されます。

ngrep 'Host: chat.axellink.fr' port 80

おそらくそれをWebサーバー上で実行する必要がありますが、ngrepを実行できるデスクトップ環境がある場合は、そこで実行することを選択できます。サーバー上で実行すると、nginxとチャットサーバー間のやり取りもキャプチャできます。

ngrep '.' port 6060

端末の出力で必要なものを確認できる場合がよくありますが、tcpdumpが '-w'で行うように、 '-O'フラグを使用してngrepでデータをpcapダンプファイルに書き込むこともできます。次に、そのファイルをデスクトップに戻して、wiresharkなどのグラフィカルクライアントで確認できます。

これから問題を見つけることができるかもしれませんが、そうでない場合は、さまざまなやり取りをキャプチャして質問に追加してください。

Javascriptが提供されるドメインとは異なるドメインでhack.chat通信を要求するjavascriptに問題がありますか?これは関連している可能性があります: https://stackoverflow.com/questions/20093070/unable-to-create-cross-domain-websocket-connection-to-node-js-socket-io-server

2
mc0e