繁体   English   中英

使用apache隧道安全websocket连接

[英]tunneling secure websocket connections with apache

我有一个只能通过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连接的隧道连接?

我有它的工作。

脚本

-------------       ----------------       ----------
| Browser   |<----->| Apache httpd |<----->| Tomcat |
|           |  SSL  |    2.4.9     |  SSL  | 7.0.52 |
-------------       ----------------       ----------

浏览器WebSocket通过Apache httpd,反向代理Tomcat中的Web应用程序。 所有SSL从前到后。

这是每件作品的配置:

Browser Client

请注意url中的尾部“/”: 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

我正在使用Apache httpd 2.4.9,开箱即用提供了mod_proxy_wstunnel 但是,在使用wss:// scheme时,提供的mod_proxy_wstunnel.so不支持SSL。 它最终尝试以明文方式连接到后端(Tomcat),这使SSL握手失败。 这里的 bug。 因此,您必须通过遵循错误报告中的建议更正来自行修补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

构建Apache httpd

这是我用来构建我想要的模块的(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"使用下划线而不是短划线。

Apache httpd配置

httpd.conf文件
 ... 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/ 

如果你没有在上面的配置中看到我的注释,那么它又是: 严格注意斜杠“/”或缺少!

另外,如果您在apache日志中看到调试日志语句表示已关闭wss连接,则可能会像我一样启用mod_reqtimeout,因此请确保未加载:

 #LoadModule reqtimeout_module modules/mod_reqtimeout.so 

Tomcat的

假设您的HTTP连接器设置正确,那么在tomcat中配置的并不多。 虽然为了帮助调试,我发现创建一个看起来像这样的$CATALINA_HOME/bin/setenv.sh很有用:

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的backport可以应用于2.2.x版本 希望我上面的笔记可以应用于那些旧版本。

如果您不希望Apache终止SSL连接(并转发未加密的WebSocket流量),但是在最终目标WebSocket服务器上终止了SSL 并且异常希望在进入Apache的WebSocket流量上使用WSS,则mod_proxy_connect可能能够只是通过原始流量连接。 不确定。 如果有效,我也会感兴趣。

如果上面不成立,这里有更多信息:

在任何情况下,使用Apache都会严重限制有关并发服务的WebSocket连接数的可伸缩性,因为每个WS连接将在Apache上使用1个进程/线程。

我正在尝试安装此https://github.com/kawasima/mod_proxy_websocket 希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM