web-dev-qa-db-ja.com

WebSocketとApacheプロキシ:mod_proxy_wstunnelを構成する方法?

私は持っています :

  1. www.domain1.comのサーバーのポート80上のApache(v2.4)、mod_proxyおよびmod_proxy_wstunnel有効

  2. 同じサーバーのポート3001上のnode.js + socket.io

www.domain2.com(ポート80)にアクセスすると、2にリダイレクトされます。 ここで説明する方法 のおかげです。 Apache設定でこれを設定しました。

<VirtualHost *:80>
    ServerName www.domain2.com
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/
    ProxyPass / ws://localhost:3001/
    ProxyPassReverse / ws://localhost:3001/
</VirtualHost>

これは、websocket部分を除いて、すべてに対して機能します。ws://...は、プロキシによる送信とは異なります。

www.domain2.comのページにアクセスすると、次のものがあります。

Impossible to connect ws://www.domain2.com/socket.io/?EIO=3&transport=websocket&sid=n30rqg9AEqZIk5c9AABN.

質問:ApacheプロキシをWebSocketにする方法は?

72
Basj

このトピック のおかげで、ようやくやることができました。

TODO:

1)Apache 2.4をインストールして(2.2では動作しません)、以下を実行します。

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

2)nodejsをポート3001で実行している

3)Apache設定でこれを行います

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
  RewriteCond %{QUERY_STRING} transport=websocket    [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]

  ProxyPass / http://localhost:3001/
  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

注:websocketを使用する同じサーバー上に複数のサービスがある場合は、 do this を使用してそれらを分離することができます。

126
Basj

URLでフィルタリングする代わりに、HTTPヘッダーでフィルタリングすることもできます。この構成は、socket.ioを使用していない場合も、websocketを使用するすべてのWebアプリケーションで機能します。

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:3001/$1 [P,L]

  ProxyPassReverse / http://localhost:3001/
</VirtualHost>
77
cdauth

役に立つかもしれません。すべてのクエリがws経由でノードに送信されます

<VirtualHost *:80>
  ServerName www.domain2.com

  <Location "/">
    ProxyPass "ws://localhost:3001/"
  </Location>
</VirtualHost>
15
Sergey

Socket.IO 1.0(2014年5月)以降、すべての接続はHTTPポーリングリクエストで始まります(詳細は here )。つまり、WebSocketトラフィックの転送に加えて、transport=polling HTTP要求を転送する必要があります。

以下のソリューションは、他のトラフィックをリダイレクトせずに、すべてのソケットトラフィックを正しくリダイレ​​クトする必要があります。

  1. 次のApache2 modを有効にします。

    Sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
    
  2. * .confファイルでこれらの設定を使用します(例:/etc/Apache2/sites-available/mysite.com.conf)。各部分を説明するコメントを含めました。

    <VirtualHost *:80>
        ServerName www.mydomain.com
    
        # Enable the rewrite engine
        # Requires: Sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
        # In the rules/conds, [NC] means case-insensitve, [P] means proxy
        RewriteEngine On
    
        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:3001/$1 [P]
    
        # When socket.io wants to initiate a WebSocket connection, it sends an
        # "upgrade: websocket" request that should be transferred to ws://
        RewriteCond %{HTTP:Upgrade} websocket               [NC]
        RewriteRule /(.*)           ws://localhost:3001/$1  [P]
    
        # OPTIONAL: Route all HTTP traffic at /node to port 3001
        ProxyRequests Off
        ProxyPass           /node   http://localhost:3001
        ProxyPassReverse    /node   http://localhost:3001
    </VirtualHost>
    
  3. /nodeトラフィックをルーティングするための便利なセクションを追加しました。詳細については here を参照してください。

12
Erik Koopmans

これらの回答の助けを借りて、Ubuntu MateとApache2が動作するRaspberry Piで動作するNode-REDのリバースプロキシを最終的に入手しました。このApache2サイト構成を使用します:

<VirtualHost *:80>
    ServerName nodered.domain.com
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:1880/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:1880/$1 [P,L]
</VirtualHost>

また、次のようなモジュールを有効にする必要がありました。

Sudo a2enmod proxy
Sudo a2enmod proxy_http
Sudo a2enmod proxy_wstunnel
7
Otto Paulsen

私にとっては、以下のようにhttpd.confに1行のみを追加した後に機能します(太線)。


<VirtualHost *:80>
    ServerName: xxxxx

    #ProxyPassReverse is not needed
    ProxyPass /log4j ws://localhost:4711/logs
<VirtualHost *:80>

ApacheバージョンはCentOSで2.4.6です。

6
Leon

私のセットアップ:

Apache 2.4.10(Debianで実行)NodeJS(バージョン4.1.1)パス/ api/wsでWebSocketを受け入れるポート3000で実行中のアプリ

@Basjで前述したように、a2enmodプロキシとws_tunnelが有効になっていることを確認してください。

これは、私の問題を解決したApache confファイルのスクリーングラブです。

enter image description here

お役に立てば幸いです。

5
Anwaarullah

静的コンテンツ、RESTコンテンツ、およびWebSocketコンテンツを実行するSpringアプリケーションに対して次のことを行いました。

Apacheは、次のURIのプロキシおよびSSLエンドポイントとして使用されます。

  • / app→静的コンテンツ
  • / api→REST AP​​I
  • / api/ws→websocket

Apacheの構成

<VirtualHost *:80>
    ServerName xxx.xxx.xxx    

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    <Proxy *>
         Require all granted
    </Proxy>

    RewriteEngine On

    # websocket 
    RewriteCond %{HTTP:Upgrade}         =websocket                      [NC]
    RewriteRule ^/api/ws/(.*)           ws://localhost:8080/api/ws/$1   [P,L]

    # rest
    ProxyPass /api http://localhost:8080/api
    ProxyPassReverse /api http://localhost:8080/api

    # static content    
    ProxyPass /app http://localhost:8080/app
    ProxyPassReverse /app http://localhost:8080/app 
</VirtualHost>

SSL構成に同じvHost構成を使用します。プロキシに関連するものを変更する必要はありません。

スプリング構成

server.use-forward-headers: true
2

主な答えに加えて、WebSocketを使用する同じサーバー上に複数のサービスがある場合は、 カスタムパス (*):

ノードサーバー:

var io = require('socket.io')({ path: '/ws_website1'}).listen(server);

クライアントHTML:

<script src="/ws_website1/socket.io.js"></script>
...
<script>
var socket = io('', { path: '/ws_website1' });
...

Apacheの構成:

RewriteEngine On

RewriteRule ^/website1(.*)$ http://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule ^(.*)$ ws://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteRule ^(.*)$ http://localhost:3001$1 [P,L]

(*)注:デフォルトのRewriteCond %{REQUEST_URI} ^/socket.ioを使用することはWebサイトに固有ではなく、websocketリクエストは異なるWebサイト間で混同されます。

1
Basj

「ポーリング」トランスポート用。

Apache側:

<VirtualHost *:80>
    ServerName mysite.com
    DocumentRoot /my/path


    ProxyRequests Off

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass /my-connect-3001 http://127.0.0.1:3001/socket.io
    ProxyPassReverse /my-connect-3001 http://127.0.0.1:3001/socket.io   
</VirtualHost>

クライアント側:

var my_socket = new io.Manager(null, {
    Host: 'mysite.com',
    path: '/my-connect-3001'
    transports: ['polling'],
}).socket('/');
0
sNICkerssss

TODO:

  1. Apache 2.4がインストールされている(2.2では動作しない)、a2enmod proxyおよびa2enmod proxy_wstunnel.load

  2. Apacheの設定でこれを行います
    8080がTomcatの実行ポートであるファイルに2行追加するだけです

    <VirtualHost *:80>
    ProxyPass "/ws2/" "ws://localhost:8080/" 
    ProxyPass "/wss2/" "wss://localhost:8080/"
    
    </VirtualHost *:80>
    
0
Arvind Madhukar

WSのperfactソリューションのこのリンクを使用する https://httpd.Apache.org/docs/2.4/mod/mod_proxy_wstunnel.html

以下の手順を実行する必要があります。

/etc/Apache2/mods-availableに移動します

ステップ1

以下のコマンドを使用してmode proxy_wstunnel.loadを有効にします

$a2enmod proxy_wstunnel.load

ステップ2

/etc/Apache2/sites-availableに移動します

そして、仮想ホスト内の.confファイルに以下の行を追加します

ProxyPass "/ws2/"  "ws://localhost:8080/"

ProxyPass "/wss2/" "wss://localhost:8080/"

注:8080は、TomcatとTomcatに配置されたWarファイルがwsのApacheを提供するwsに接続するため、Tomcatがポートを実行していることを意味します。ありがとうございました

私の設定

ws://localhost/ws2/ALLCAD-Unifiedcommunication-1.0/chatserver?userid=4 =Connected
0
Arvind Madhukar