![Apache 将所有 ws 连接代理到不同的端口](https://linux22.com/image/669257/Apache%20%E5%B0%86%E6%89%80%E6%9C%89%20ws%20%E8%BF%9E%E6%8E%A5%E4%BB%A3%E7%90%86%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E7%AB%AF%E5%8F%A3.png)
在我的 Apache 2.4 vhost 中,我尝试让所有https://
流量继续传输到端口 443,但所有ws://
流量都转发到ws://*:6969
。
例如:
https://example.com/index
会像平常一样https://example.com/index:443
。
ws://example.com/anypathhere/
将被转发至ws://example.com/anypathhere:6969
到目前为止,我已经尝试了 vhost 中注释掉的值。
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca.key
DocumentRoot /var/www/html/
RewriteOptions Inherit
AccessFileName .htaccess
AllowEncodedSlashes NoDecode
DirectoryIndex disabled
<Directory /var/www/html>
Options +FollowSymlinks
RewriteEngine On
AllowOverride All
Require all granted
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* %{REQUEST_URI}index.php [L]
</Directory>
ServerName localhost.localdomain
#ProxyPreserveHost On
#ProxyRequests Off
#ProxyPassMatch / ws://192.16.4.177:6969/ retry=0
#ProxyPassReverse ws:// ws://192.16.4.177:6969/
#ProxyPass ws:// ws://192.16.4.177:6969/
#RewriteEngine On
#RewriteRule ws:// ws://%{HTTP_HOST}/$1:6969 [NC,R=301,L]
所有这些都导致
Firefox can't establish a connection to the server at ws://192.16.4.177:443
或 400 错误。
答案1
你确实需要添加一个用于监听 ws 流量的 vhost*:80
有一点,要么由于错误的 VHost-File 而失败,要么RewriteCond
由于错误的 VHost-File 而失败ProxyPass
。您的流量由您使用的证书加密。因此无法正确建立连接。您的远程主机无法读取它。
根据维基百科:
通信通过 TCP 端口号 80 [...] 完成。
您的附加 VHost 文件应如下所示:
<VirtualHost *:80>
ServerName localhost.localdomain
ProxyPreserveHost On
ProxyRequests Off
ProxyPassReverse / ws://192.16.4.177:6969/
ProxyPass / ws://192.16.4.177:6969/
</VirtualHost>
正如解释的那样。所有通过 http:80 的请求都将被重定向到 ws:6969。
答案2
最好的办法是告诉客户端使用正确的端口……但是如果您想在他们使用错误的端口时进行代理或重定向:
我对 ws:// 一无所知,但我相信你需要使用 a RewriteCond
,因为 aRewriteRule
和类似符号不包含要匹配的方案。请参阅指令引用。这可能仅在 ws:// 请求看起来像 HTTP 请求,或者您有一个专门处理 ws:// 请求的模块时才有效。(要使用RewriteCond
,您可以根据需要多次列出它,并且它仅适用于下一个 RewriteRule [或类似?])
例如代理:
RewriteEngine On
ProxyRequests Off
ProxyPreserveHost On
RewriteCond %{REQUEST_SCHEME} "^ws$"
RewriteRule "^(/?.*)$" ws://otherhost:6969/$1 [P]
答案3
不幸的是,我认为没有简单的方法可以做到这一点。Peter 的答案不起作用,因为 Websockets 通过 HTTP(S) 作为 GET 请求搭载特殊标题。无论mod_rewrite
使用什么逻辑来检测 URL 方案,都不足以检测到这一点,因此该方案始终显示为http
或https
。
理论上,您可以自己查找标题,使用类似以下语法:
RewriteCond %{HTTP:Upgrade} ^websocket$ [nocase]
RewriteRule ^(.*)$ ws://192.16.4.177:6969/$1 [proxy]
但是,虽然此规则确实与打开客户端握手匹配(已在我的日志中确认),但这并没有给我一个有效的 Websocket 重定向。我怀疑它mod_rewrite
实际上并不了解如何代理 Websocket 连接,即使您可以让握手到达正确的位置。
这让我们只剩下 JinnFox 的答案。如果您能够将 Websockets 端点移动到 以外的其他地方/
,这可能是一个可接受的解决方案。
PS 与此同时,我发现NGINX 几乎无缝地处理了这种情况(向下滚动到步骤 6 来找到适用于 HTTP 和 WS 的代码片段)。