Apache 将所有 ws 连接代理到不同的端口

Apache 将所有 ws 连接代理到不同的端口

在我的 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 方案,都不足以检测到这一点,因此该方案始终显示为httphttps

理论上,您可以自己查找标题,使用类似以下语法:

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 的代码片段)。

相关内容