我有一个只能通过HTTPS访问的Apache运行。我想从另一台运行在同一台机器上的服务器应用程序提供websockets,但由于客户端无法连接到443以外的另一个端口到我们的服务器,因此需要通过Apache代理这些websocket连接。
现在,我已经安装了mod_proxy并按如下方式对其进行了配置:
SSLProxyEngine on
ProxyPass /ws https://127.0.0.1:9001
然而,这不起作用。我现在可以在浏览器中连接到 https:// server / ws ,但是apache似乎吞下了部分websockets标头,因此真正的websocket连接不起作用。
如何通过Apache服务器实现对websocket连接的隧道连接?
答案 0 :(得分:27)
我已经开始工作了。
------------- ---------------- ----------
| Browser |<----->| Apache httpd |<----->| Tomcat |
| | SSL | 2.4.9 | SSL | 7.0.52 |
------------- ---------------- ----------
通过Apache httpd浏览器WebSocket,反向代理Tomcat中的Web应用程序。所有SSL从前到后。
这是每件作品的配置:
请注意尾随&#34; /&#34;在网址中: wss://host/app/ws/
。有必要匹配正确的wss ProxyPass指令(在Apache配置部分中进一步显示)并阻止301重定向到https://host/app/ws
。也就是说,它使用https方案重定向,而不是后端的wss方案。
<!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 。但是,使用wss:// scheme时,提供的 mod_proxy_wstunnel.so 不支持SSL。它最终尝试以明文方式连接到后端(Tomcat),这使SSL握手失败。请参阅错误here。因此,您必须按照错误报告中的建议更正来自行修补 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
,这似乎很好,但最终还是没有#39;当我使用生成的.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/
如果您在上面的配置中没有看到我的注释,请再次显示:严格注意斜线&#34; /&#34;或缺乏!
另外,如果您在apache日志中看到调试日志语句表示已关闭wss连接,那么您可能已启用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,I've seen where backports of mod_proxy_wstunnel can be applied to versions 2.2.x。希望我上面的笔记可以应用于那些旧版本。
答案 1 :(得分:1)
如果您不希望Apache终止SSL连接(并转发未加密的WebSocket流量),但是在最终目标WebSocket服务器上终止了SSL 和,则需要在WebSocket上使用WSS进入Apache的流量,然后 mod_proxy_connect 可能只能通过原始流量连接。不确定。如果有效,我也会感兴趣。
如果上述情况不成立,请提供以下信息:
在任何情况下,使用Apache都会严重限制有关并发服务的WebSocket连接数的可伸缩性,因为每个WS连接都会占用Apache上的1个进程/线程。
答案 2 :(得分:0)
我正在尝试安装此https://github.com/kawasima/mod_proxy_websocket。希望它有所帮助。