Назад | Перейти на главную страницу

Прокси-сервер Apache для всех подключений ws к другому порту

В моем хосте Apache 2.4 я пытаюсь получить все 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.

К сожалению, я не думаю, что есть простой способ сделать это. Ответ Питера не работает, потому что 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 куда-нибудь, кроме /, это может быть приемлемым решением.

P.S. Тем временем я обнаружил, что NGINX справляется с этим практически без проблем (прокрутите вниз до шага 6, чтобы найти фрагмент кода, который работает как для HTTP, так и для WS).

Вам действительно нужно добавить vhost для трафика ws, который прослушивает *:80

Есть одна точка, которая терпит неудачу либо с RewriteCond или с ProxyPass в неправильном VHost-файле. Ваш трафик зашифрован сертификатом, который вы используете. Следовательно, соединение не будет установлено правильно. Ваш удаленный хост не может его прочитать.

На основании документации в википедия:

Связь осуществляется через 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.

Лучший способ сделать это - сказать клиенту, чтобы он использовал правильный порт ... но если вы хотите использовать прокси или перенаправить, когда они используют неправильный порт:

Я ничего не знаю о ws: //, но считаю, что вам нужно использовать RewriteCond для этого, поскольку RewriteRule и аналогичные не содержат схемы для сопоставления. Увидеть директива ссылка. Это, вероятно, будет работать только в том случае, если запросы ws: // выглядят как запросы HTTP или у вас есть модуль, который специально обрабатывает запросы ws: //. (Использовать RewriteCond, вы можете перечислять его столько раз, сколько хотите, и оно применяется только к следующему RewriteRule [или подобному?])

например. для проксирования:

RewriteEngine On
ProxyRequests Off
ProxyPreserveHost On

RewriteCond %{REQUEST_SCHEME} "^ws$"
RewriteRule "^(/?.*)$" ws://otherhost:6969/$1 [P]