programing

WebSockets 및 Apache 프록시: mod_proxy_wstunnel을 구성하는 방법은 무엇입니까?

yellowcard 2023. 10. 27. 21:52
반응형

WebSockets 및 Apache 프록시: mod_proxy_wstunnel을 구성하는 방법은 무엇입니까?

나는 다음을 가지고 있습니다.

  1. 내 서버의 포트 80에서 Apache 2.4(mod_proxy 및 mod_proxy_wstunnel 사용)

  2. Node.js +socket.io동일한 서버의 포트 3001에

액세스example.com(포트 80 포함)은 다음과 같은 Apache 구성을 사용하는 이 메서드 덕분에 2.로 리디렉션됩니다.

<VirtualHost *:80>
    ServerName example.com
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/
    ProxyPass / ws://localhost:3001/
    ProxyPassReverse / ws://localhost:3001/
</VirtualHost>

웹소켓 부분을 제외한 모든 부분에서 작동합니다.ws://...프록시가 전송해야 하는 것처럼 전송되지 않습니다.

페이지에 액세스할 때example.com, 내가 가지고 있습니다.

Impossible to connect ws://example.com/socket.io/?EIO=3&transport=websocket&sid=n30rqg9AEqZIk5c9AABN.

질문:.Apache 프록시를 WebSockets로 만드는 방법?

는 이 주제 덕분에 마침내 해낼 수 있었습니다.작업 항목:

1) Apache 2.4를 설치하고(2.2에서는 작동하지 않음) 다음을 수행합니다.

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

2) 가지다nodejs포트 3001에서 실행

3) Apache 구성에서 이 작업 수행

<VirtualHost *:80>
  ServerName example.com

  RewriteEngine On
  RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
  RewriteCond %{QUERY_STRING} transport=websocket    [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]

  ProxyPass / http://localhost:3001/
  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

참고: 웹 소켓을 사용하는 동일한 서버에 둘 이상의 서비스가 있는 경우 를 분리하여 사용할 수 있습니다.

URL로 필터링하는 대신 HTTP 헤더로 필터링할 수도 있습니다.이 구성은 소켓을 사용하지 않는 경우에도 웹 소켓을 사용하는 모든 웹 응용 프로그램에서 작동합니다.io:

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:3001/$1 [P,L]

  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

유용할 것입니다.모든 쿼리가 ws를 통해 노드로 전송됩니다.

<VirtualHost *:80>
  ServerName www.domain2.com

  <Location "/">
    ProxyPass "ws://localhost:3001/"
  </Location>
</VirtualHost>

소켓 기준.IO 1.0(2014년 5월), 모든 연결은 HTTP 폴링 요청으로 시작됩니다(자세한 내용은 여기).즉, WebSocket 트래픽을 전달하는 것 외에 다음과 같은 것을 전달해야 합니다.transport=pollingHTTP 요청.

아래 솔루션은 다른 트래픽을 리디렉션하지 않고 모든 소켓 트래픽을 올바르게 리디렉션해야 합니다.

  1. 다음 Apache2 모드를 사용하도록 설정합니다.

    sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
    
  2. *.conf 파일에서 이 설정을 사용합니다(예:/etc/apache2/sites-available/mysite.com.conf 각 하기 위해 :). 각 작품을 설명하기 위해 코멘트를 넣었습니다.

    <VirtualHost *:80>
        ServerName www.mydomain.com
    
        # Enable the rewrite engine
        # Requires: sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
        # In the rules/conds, [NC] means case-insensitve, [P] means proxy
        RewriteEngine On
    
        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:3001/$1 [P]
    
        # When socket.io wants to initiate a WebSocket connection, it sends an
        # "upgrade: websocket" request that should be transferred to ws://
        RewriteCond %{HTTP:Upgrade} websocket               [NC]
        RewriteRule /(.*)           ws://localhost:3001/$1  [P]
    
        # OPTIONAL: Route all HTTP traffic at /node to port 3001
        ProxyRequests Off
        ProxyPass           /node   http://localhost:3001
        ProxyPassReverse    /node   http://localhost:3001
    </VirtualHost>
    
  3. 루팅을 위해 추가 섹션을 추가했습니다./node편리한 교통, 자세한 정보는 여기를 참조하십시오.

이러한 답변을 통해 Ubuntu Mate와 Apache2가 작동하는 Raspberry Pi에서 실행되는 Node-RED의 역방향 프록시를 마침내 얻었습니다.

<VirtualHost *:80>
    ServerName nodered.domain.com
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:1880/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:1880/$1 [P,L]
</VirtualHost>

또한 다음과 같은 모듈을 활성화해야 했습니다.

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel

저의 경우 아래와 같이 httpd.conf에서 한 만 추가하면 됩니다( 굵은 줄).


<VirtualHost *:80>
    ServerName: xxxxx

    #ProxyPassReverse is not needed
    ProxyPass /log4j ws://localhost:4711/logs
<VirtualHost *:80>

아파치 버전은 CentOS에서 2.4.6입니다.

정적, 휴식 및 웹소켓 컨텐츠를 실행하는 스프링 애플리케이션에 대해 다음과 같은 작업을 수행했습니다.

Apache는 다음 URI의 Proxy 및 SSL Endpoint로 사용됩니다.

  • /app → 정적 컨텐츠
  • /api → REST API
  • /api/ws → 웹소켓

아파치 구성

<VirtualHost *:80>
    ServerName xxx.xxx.xxx    

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    <Proxy *>
         Require all granted
    </Proxy>

    RewriteEngine On

    # websocket 
    RewriteCond %{HTTP:Upgrade}         =websocket                      [NC]
    RewriteRule ^/api/ws/(.*)           ws://localhost:8080/api/ws/$1   [P,L]

    # rest
    ProxyPass /api http://localhost:8080/api
    ProxyPassReverse /api http://localhost:8080/api

    # static content    
    ProxyPass /app http://localhost:8080/app
    ProxyPassReverse /app http://localhost:8080/app 
</VirtualHost>

SSL 구성에 동일한 vHost 구성을 사용하므로 프록시 관련 내용을 변경할 필요가 없습니다.

스프링구성

server.use-forward-headers: true

내 설정:

  • Apache 2.4.10(Debian 실행)
  • Node.js(버전 4.1.1) 경로에서 WebSockets를 허용하는 포트 3000에서 실행되는 앱/api/ws

@Basj가 위에서 언급한 대로 a2enmod 프록시와 ws_tunnel이 활성화되었는지 확인합니다.

다음은 내 문제를 해결한 Apache config 파일의 스크린샷입니다.

Apache config

텍스트로서 관련된 부분:

<VirtualHost *:80>
  ServerName *******
  ServerAlias *******
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/

  <Location "/api/ws">
      ProxyPass "ws://localhost:3000/api/ws"
  </Location>
</VirtualHost>

도움이 되길 바랍니다.

주요 답변 외에도 웹 소켓을 사용하는 동일한 서버에 둘 이상의 서비스가 있는 경우 사용자 지정 경로(*)를 사용하여 서비스를 분리할 수 있습니다.

노드 서버:

var io = require('socket.io')({ path: '/ws_website1'}).listen(server);

클라이언트 HTML:

<script src="/ws_website1/socket.io.js"></script>
...
<script>
var socket = io('', { path: '/ws_website1' });
...

Apache 구성:

RewriteEngine On

RewriteRule ^/website1(.*)$ http://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule ^(.*)$ ws://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteRule ^(.*)$ http://localhost:3001$1 [P,L]

(*) 참고: 기본값 사용RewriteCond %{REQUEST_URI} ^/socket.io웹사이트에 특정한 것이 아닐 것이고, 웹소켓 요청은 다른 웹사이트들 사이에서 뒤섞일 것입니다!

ws https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html 의 완벽한 솔루션을 위해 이 링크를 사용합니다.

아래 단계만 하면 됩니다.

에 가다/etc/apache2/mods-available

단계...1

가능하게 하다mode proxy_wstunnel.load아래 명령을 사용하여

$a2enmod proxy_wstunnel.load

단계...2

에 가다/etc/apache2/sites-available

가상 호스트 내부의 .conf 파일에 아래 줄을 추가합니다.

ProxyPass "/ws2/"  "ws://localhost:8080/"

ProxyPass "/wss2/" "wss://localhost:8080/"

참고: 8080은 연결을 원하기 때문에 Tomcat이 포트를 실행하고 있음을 의미합니다.wstomcat과 tomcat serve apache에 우리의 war 파일을 넣은 곳.ws.감사해요.

내 구성

ws://localhost/ws2/ALLCAD-Unifiedcommunication-1.0/chatserver?userid=4 =Connected

"폴링" 운송용입니다.

Apache 측면:

<VirtualHost *:80>
    ServerName mysite.com
    DocumentRoot /my/path


    ProxyRequests Off

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass /my-connect-3001 http://127.0.0.1:3001/socket.io
    ProxyPassReverse /my-connect-3001 http://127.0.0.1:3001/socket.io   
</VirtualHost>

클라이언트 측:

var my_socket = new io.Manager(null, {
    host: 'mysite.com',
    path: '/my-connect-3001'
    transports: ['polling'],
}).socket('/');

작업 항목:

  1. Apache 2.4를 설치해야 합니다(2.2에서는 작동하지 않음).a2enmod proxy그리고.a2enmod proxy_wstunnel.load

  2. Apache 구성에서 이 작업 수행
    8080이 tomcat 실행 포트인 파일에 두 줄만 추가하면 됩니다.

    <VirtualHost *:80>
    ProxyPass "/ws2/" "ws://localhost:8080/" 
    ProxyPass "/wss2/" "wss://localhost:8080/"
    
    </VirtualHost *:80>
    

Windows에서 동일한 문제가 발생하는 경우 http.conf에서 아래 행의 코멘트를 해제하기만 하면 됩니다.

enter image description here

그런 다음 아래 줄을 Apache config에 추가합니다.

    LoadModule proxy_module modules/mod_proxy_wstunnel.so

먼저 필요한 Apache 모듈을 활성화합니다.

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

그런 다음 다음 템플릿을 사용하여 Apache 역방향 프록시 사이트 구성(기존 호스트-포트 조합 사용)localhost:3000), socket.io 웹소켓 작동(socket.io v4 공식 설명서에서 adapted):

<VirtualHost *:80>
  # redirect anything HTTP-without-S to HTTPS-with-S
  ServerName websocket.example.com

  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  # see https://httpd.apache.org/docs/2.4/rewrite/flags.html
  # see https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule

  ErrorLog ${APACHE_LOG_DIR}/websocket-http-error.log
  CustomLog ${APACHE_LOG_DIR}/websocket-http-access.log combined
</VirtualHost>

<VirtualHost *:443>
  ServerName websocket.example.com

  SSLEngine On
  SSLProxyCheckPeerName On

  # assuming let's encrypt certificate
  SSLCertificateFile /etc/letsencrypt/live/websocket/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/websocket/privkey.pem
  SSLCertificateChainFile /etc/letsencrypt/live/websocket/chain.pem

  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/

  # setup websocket socket.io configuration
  # see https://socket.io/docs/v4/reverse-proxy/#apache-httpd
  RewriteEngine on
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteCond %{HTTP:Connection} upgrade [NC]
  RewriteRule ^/?(.*) "ws://localhost:3000/$1" [P,L]

  ProxyTimeout 3

  ErrorLog ${APACHE_LOG_DIR}/websocket-https-error.log
  CustomLog ${APACHE_LOG_DIR}/websocket-https-access.log combined
</VirtualHost>

언급URL : https://stackoverflow.com/questions/27526281/websockets-and-apache-proxy-how-to-configure-mod-proxy-wstunnel

반응형