NGINXはWebSocketをリバースプロキシし、SSL(wss://)を有効にしますか?


136

私は自分でNGINXを構築するのが初めてで、迷っていますが、追加のレイヤーなしで安全なWebSocketを有効にできるようにしたいと思っています。

Websocketサーバー自体でSSLを有効にしたくないが、代わりにNGINXを使用してSSLレイヤーを全体に追加したい。

そこにあるすべてのWebページには、私はそれを行うことができないと書かれていますが、私はできることを知っています!(私自身)私に方法を教えてくれる人に感謝します!

回答:


185

nginxがリリース1.3.13でWebsocketをサポートするようになったことに注意してください。使用例:

location /websocket/ {

    proxy_pass ​http://backend_host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;

}

nginxの変更ログWebSocketプロキシのドキュメントも確認できます


上記と同じタイムアウトの問題があります;)
3rdEden 2013

5
@ 3rdEden:タイムアウトの問題についてはproxy_read_timeout、私は答えを編集しました。
Steve Kehlet、2013

2
この構成はどこに置くべきですか?backend_hostとは何ですか?
Aysennoussi 2014年

3
@世界:locationディレクティブは、serverまたは別のlocationディレクティブ内に配置されます(場所のドキュメントを参照)。backend_hostupstream上流のドキュメントを参照)-プロキシするサーバーの1つまたはグループです。
Radko Dinev 2014

1
このタイムアウトの問題はどうですか?それを回避するために、非常に大きな値に設定する必要がありますか?これ以上エレガントな解決策はありませんか?
Mohammed Noureldin

54

勇敢なOpsプログラマーグループが、ブランドをスパンキングする新しいnginx_tcp_proxy_moduleで状況を解決しているため、恐れはありません。

2012年8月に書かれているので、もしあなたが未来から来ているなら、あなたは宿題をするべきです。

前提条件

CentOSを使用していると仮定します。

  • NGINXの現在のインスタンスを削除します(このために開発サーバーを使用することをお勧めします)
  • 可能であれば、古いNGINX構成ファイルを保存して、init.d/nginxスクリプトを含めて再利用できるようにします。
  • yum install pcre pcre-devel openssl openssl-devel NGINXをビルドするために必要なその他のライブラリ
  • ここhttps://github.com/yaoweibin/nginx_tcp_proxy_moduleの GitHubからnginx_tcp_proxy_moduleを取得し、配置したフォルダを覚えておいてください(zipされていないことを確認してください)

新しいNGINXを構築する

ここでも、CentOSを想定しています。

  • cd /usr/local/
  • wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
  • tar -xzvf nginx-1.2.1.tar.gz
  • cd nginx-1.2.1/
  • patch -p1 < /path/to/nginx_tcp_proxy_module/tcp.patch
  • ./configure --add-module=/path/to/nginx_tcp_proxy_module --with-http_ssl_module (必要に応じてモジュールを追加できます)
  • make
  • make install

オプション:

  • sudo /sbin/chkconfig nginx on

Nginxをセットアップする

古い構成ファイルを再利用する場合は、最初にコピーしてください。

重要:tcp {} confの最上位にディレクティブを作成する必要があります。ディレクティブの中にないことを確認してくださいhttp {}

以下の設定例は、単一のアップストリームWebソケットサーバーと、SSLと非SSLの両方の2つのプロキシを示しています。

tcp {
    upstream websockets {
        ## webbit websocket server in background
        server 127.0.0.1:5501;
        
        ## server 127.0.0.1:5502; ## add another server if you like!

        check interval=3000 rise=2 fall=5 timeout=1000;
    }   

    server {
        server_name _;
        listen 7070;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }

    server {
        server_name _;
        listen 7080;

        ssl on;
        ssl_certificate      /path/to/cert.pem;
        ssl_certificate_key  /path/to/key.key;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }
}

5
これはかなり役に立ちましたが、それでも60秒でタイムアウトが発生しました。次のように設定して、なんとかこれを修正しました。タイムアウト43200000; websocket_connect_timeout 43200000; websocket_read_timeout 43200000; websocket_send_timeout 43200000; proxy_connect_timeout 43200000; proxy_read_timeout 43200000; proxy_send_timeout 43200000;
jbg

2
共有してくれてありがとう!後で同様の問題が発生していることに気づきました。偶然にも、yaoweibin氏自身がGitHubの問題に返信し、問題#28へのコメントへのリンクを示しました。小さな世界...
crockpotveggies

1
ブラウザーが認証された後でのみ、同じhttpポートからWebソケットを提供したいと思っていました。これは同じポートでWebSocketを処理できないようです。人々はこれをどのように扱いますか?
uroc

1
着信プロトコルを検出するには、ソフトウェアを変更する必要があります。WebSocketは実際にはHTTPハンドシェイク(TCPよりも高いソフトウェアレベル)として開始されるため、アプリを微調整してTCPトラフィックとHTTPトラフィックの両方を処理する必要があります。これを行う方法はまだお勧めできません。
crockpotveggies

2
2018年の他の人々がここに来た場合、これらの指令はもはや機能しません。最近の手順については、nginx.org / en / docs / http / websocket.htmlにアクセスするか、以下のHarlan T Woodの回答を参照してください。
GaryO

37

これは私のために働きました:

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

-借用:https : //github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
TeamCityのWebソケットをリバースプロキシの背後で動作させるのに問題がありました。あなたの# WebSocket support手先が私のためにそれをしました。以前はポート400を転送しようとしていましたが、wssは443を超えて機能します。FYIの将来の読者:)
Mario Tacke

あなたは解決策を理解しましたか?私はまた、同様の問題に直面しなければならなかったので stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

多くの人(自分のような)が/をWebソケットと通常のHTTP2の両方に使用しているので、私はこの答えが一番好きです。
mikemaccana

@誰もが呼び出しているJavaScriptは何でしょうか?
Andrew Simpson

17

.net core 2.0 Nginx for SSL

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}

これは私のために働いた


C#コードとは 私は現在これをwindows / iisに持っています_server = new WebSocketServer( "wss://0.0.0.0:8200 / MessageRelayer"){Certificate = new X509Certificate2(PfxFileName、SslPassword)、RestartAfterListenError = true};
Andrew Simpson

SignalRを使用しています
Altair CA

これが私にとって有効な唯一の解決策でした。ありがとう!
m-ketan

8

私にとっては、proxy_pass場所の設定に行き着きました。HTTPSプロトコルを使用するように切り替え、ノードサーバー側で有効なSSL証明書を設定する必要がありました。そうすれば、外部ノードサーバーを導入するときに、IPを変更するだけで、他はすべて同じ構成のままです。

これが途中で誰かを助けることを願っています...私はずっと問題を見つめていました...ため息...

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
upstream nodeserver {
        server 127.0.0.1:8080;
}
server {
        listen 443 default_server ssl http2;
        listen [::]:443 default_server ssl http2 ipv6only=on;
        server_name mysite.com;
        ssl_certificate ssl/site.crt;
        ssl_certificate_key ssl/site.key;
        location /websocket { #replace /websocket with the path required by your application
                proxy_pass https://nodeserver;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_intercept_errors on;
                proxy_redirect off;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-NginX-Proxy true;
                proxy_ssl_session_reuse off;
            }
}

を試しましたがlocaltion /horizon、うまくいきません。localtion /またはのみlocation /websockify動作します。理由がわからない...
njuguoyi 2018年

6

Pankaj Malhotraによる優れた簡潔な記事は、NGINXを使用してこれを行う方法について説明しており、こちらから入手できます

基本的なNGINX構成を以下に再現します。

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

upstream appserver {
    server 192.168.100.10:9222; # appserver_ip:ws_port
}

server {
    listen 8888; // client_wss_port

    ssl on;
    ssl_certificate /path/to/crt;
    ssl_certificate_key /path/to/key;


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

1
NGINXの最新バージョンもタイムアウトの問題に対処していますか?
crockpotveggies

2

nginx / 1.14.0の使用

ポート8097でwebsocketサーバーを実行していて、ユーザーがポート8098でwssに接続している場合、nginxはコンテンツを復号化してwebsocketサーバーに転送するだけです。

だから私はこの設定ファイルを持っています(私の場合/etc/nginx/conf.d/default.conf

server {
    listen   8098;
        ssl on;
        ssl_certificate      /etc/ssl/certs/combined.pem;
        ssl_certificate_key  /root/domain.key;
    location / {

        proxy_pass http://hostname:8097;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.