HTTPS経由でのみアクセス可能なApacheを実行しています。同じマシンで実行されている追加のサーバーアプリケーションからWebSocketを提供したいのですが、クライアントが443以外のポートでサーバーに接続できないため、これらのWebSocket接続はApache経由でプロキシする必要があります。
これでmod_proxyがインストールされ、次のように構成されました。
SSLProxyEngine on
ProxyPass /ws https://127.0.0.1:9001
ただし、これは機能しません。ブラウザでhttps:// server/wsに接続できるようになりましたが、ApacheはWebSocketヘッダーの一部を飲み込んでいるようなので、実際のWebSocket接続は機能しません。
Apacheサーバーを介してWebSocket接続をトンネリングするにはどうすればよいですか?
私はそれを働いています。
------------- ---------------- ----------
| Browser |<----->| Apache httpd |<----->| Tomcat |
| | SSL | 2.4.9 | SSL | 7.0.52 |
------------- ---------------- ----------
Apache httpdを介したブラウザWebSocket、TomcatのWebアプリへのリバースプロキシ。すべてのSSLフロントツーバック。
それぞれの構成は次のとおりです。
URLの末尾の「/」に注意してください:wss://Host/app/ws/
。正しいwss ProxyPassディレクティブ(Apache構成セクションでさらに下に表示)と一致させ、https://Host/app/ws
への301リダイレクトを防ぐ必要がありました。つまり、バックエンドのwssスキームではなく、httpsスキームを使用してリダイレクトしていました。
<!doctype html>
<body>
<script type="text/javascript">
var connection = new WebSocket("wss://Host/app/ws/");
connection.onopen = function () {
console.log("connected");
};
connection.onclose = function () {
console.log("onclose");
};
connection.onerror = function (error) {
console.log(error);
};
</script>
</body>
</html>
私は、Apache httpd 2.4.9を使用しています。これは、標準でmod_proxy_wstunnelを提供しています。ただし、提供されているmod_proxy_wstunnel.soは、wss://スキームを使用する場合、SSLをサポートしません。最終的に、プレーンテキストでバックエンド(Tomcat)に接続しようとするため、SSLハンドシェイクに失敗します。バグ ここ を参照してください。そのため、バグレポートで提案されている修正に従って、自分でパッチmod_proxy_wstunnel.cを適用する必要があります。これは簡単な3行の変更です。
Suggested correction,
314a315
> int is_ssl = 0;
320a322
> is_ssl = 1;
344c346
< backend->is_ssl = 0;
---
> backend->is_ssl = is_ssl;
次に、モジュールを再構築し、新しいmod_proxy_wstunnel.soを古いものに置き換えます。
これが、必要なモジュールをビルドするために使用した(2.4.9)コマンドです。あなたはそれらすべてを必要としないかもしれません。
./configure --prefix=/usr/local/Apache --with-included-apr --enable-alias=shared
--enable-authz_Host=shared --enable-authz_user=shared
--enable-deflate=shared --enable-negotiation=shared
--enable-proxy=shared --enable-ssl=shared --enable-reqtimeout=shared
--enable-status=shared --enable-auth_basic=shared
--enable-dir=shared --enable-authn_file=shared
--enable-autoindex=shared --enable-env=shared --enable-php5=shared
--enable-authz_default=shared --enable-cgi=shared
--enable-setenvif=shared --enable-authz_groupfile=shared
--enable-mime=shared --enable-proxy_http=shared
--enable-proxy_wstunnel=shared
最後のスイッチに注意してください:--enable-proxy_wstunnel=shared
最初は、--enable-proxy-wstunnel=shared
を誤って使用していました、正常にビルドされているように見えましたが、結果の.soファイルを使用した場合、最終的には機能しません。違いを見ます? "proxy_wstunnel"
ではダッシュではなくアンダースコアを使用してください。
...
LoadModule proxy_module modules/mod_proxy.so
...
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
...
LoadModule ssl_module modules/mod_ssl.so
...
Include conf/extra/httpd-ssl.conf
...
LogLevel debug
ProxyRequests off
# Note, this is the preferred ProxyPass configuration, and *should* be equivalent
# to the same inline version below, but it does NOT WORK!
#<Location /app/ws/>
# ProxyPass wss://localhost:8443/app/ws
# ProxyPassReverse wss://localhost:8443/app/ws
#</Location>
#<Location /app/>
# ProxyPass https://localhost:8443/app/
# ProxyPassReverse https://localhost:8443/app/
#</Location>
# NOTE: Pay strict attention to the slashes "/" or lack thereof!
# WebSocket url endpoint
ProxyPass /app/ws/ wss://localhost:8443/app/ws
ProxyPassReverse /app/ws/ wss://localhost:8443/app/ws
# Everything else
ProxyPass /app/ https://localhost:8443/app/
ProxyPassReverse /app/ https://localhost:8443/app/
上記の設定で私のメモが表示されなかった場合は、次のようになります:スラッシュ「/」またはその欠如に厳密に注意してください!
また、wss接続が確立されて閉じられたことを示すデバッグログステートメントがApacheログに表示される場合は、私と同じようにmod_reqtimeoutを有効にしている可能性があるため、読み込まないようにしてください。
#LoadModule reqtimeout_module modules/mod_reqtimeout.so
HTTPコネクターが正しくセットアップされていると仮定すると、Tomcatで構成することはあまりありません。デバッグを支援するために、次のような$CATALINA_HOME/bin/setenv.sh
を作成すると便利です。
CATALINA_OPTS=$CATALINA_OPTS" -Djavax.net.debug=all -Djavax.net.debug=ssl:handshake:verbose"
これにより、変更したmod_proxy_wstunnel.soがwss://で機能していたかどうかを確認できました。機能していない場合、私のcatalina.outログファイルには次のように表示されます。
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
http-nio-8443-exec-1, SEND TLSv1 ALERT: fatal, description = internal_error
http-nio-8443-exec-1, WRITE: TLSv1 Alert, length = 2
http-nio-8443-exec-1, called closeOutbound()
http-nio-8443-exec-1, closeOutboundInternal()
私はApache httpd 2.4.9を使用していますが、 mod_proxy_wstunnelのバックポートをバージョン2.2.xに適用できる場所を確認しました 。うまくいけば、上記の私のノートがそれらの古いバージョンに適用できることを願っています。
ApacheにSSL接続を終了させたくない(そして暗号化されていないWebSocketトラフィックを転送したくない)が、最終的なターゲットWebSocketサーバーでSSLを終了させたい場合and Apacheに着信するWebSocketトラフィックでWSSを排他的に使用したい場合、mod_proxy_connectはそのままのトラフィックを介して接続できる場合があります。わからない。それがうまくいけば、私も興味があります。
上記が当てはまらない場合は、以下に詳細を示します。
いずれの場合でも、すべてのWS接続はApacheで1つのプロセス/スレッドを消費するため、Apacheを使用すると、同時に提供されるWebSocket接続の数に関するスケーラビリティが大幅に制限されます。
これをインストールしようとしています https://github.com/kawasima/mod_proxy_websocket 。それが役に立てば幸い。