httpd-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jon Harper <jon.harpe...@gmail.com>
Subject [users@httpd] mod_proxy_wstunnel hijacks subsequent http requests in same tcp connection after websocket handshake error
Date Wed, 25 Nov 2020 13:21:46 GMT
Hi list,

I'm seeking help for the following problem. I have an httpd doing two things:
- serving files
- reverse proxying websockets to a backend server.
In the general case, things work fine.

However, when the websocket server refuses the websocket handshake
with httpd by replying 401 Unauthorized, if the client sends another
request for files (**not websocket**) in the same TCP connection (http
keepalive), then the second request is incorrectly reverse proxied to
the websocket server.

Is there a solution to this?

The problem is visible with this very simple following configuration:

Listen 8080
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
<VirtualHost *:8080>
    # an explicit worker
    ProxyPass /ws/gateway/ ws://BACKEND:9000/
</VirtualHost>

If you run this and check with curl:
# first getting a file works
$ curl 'http://localhost:8080/'
<html><body><h1>It works!</h1></body></html>

# but here, connecting a websocket that is refused by the server and
then getting the file
# in the same tcp connection is incorrectly routed to the websocket
server, which answers
# with a 404
$ curl -v  -H 'Connection: Upgrade' -H 'Upgrade: websocket'
'http://localhost:8080/ws/gateway/notification/notify'   --next
'http://localhost:8080/' ; echo
{"timestamp":"2020-11-25T11:43:28.097+0000","path":"/","status":404,"error":"Not
Found","message":null,"requestId":"dacfa51f-33"}


Note that using the following configuration also show the problem:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule rewrite_module modules/mod_rewrite.so
<VirtualHost *:8080>
    # same problem with reverse proxying with the default worker
    RewriteEngine On
    RewriteRule /ws/gateway/(.*) ws://BACKEND:9000/$1 [P]
</VirtualHost>


If you want to reproduce locally, please feel free to use the
following docker images:
# my backend, a spring-boot gateway.
# use this or any other websocket server that refuses the websocket handshake
# but keeps the tcp connection open.
$ docker run -p 9000:9000 gridsuite/gateway

# using the official httpd image with the configuration above with trace8 logs
# 172.17.0.1 is the default ip of your computer on the docker network
$ docker run -p 8080:8080 httpd:2.4 bash -c 'echo -ne "Listen
8080\nLogLevel trace8\nLoadModule proxy_module
modules/mod_proxy.so\nLoadModule proxy_wstunnel_module
modules/mod_proxy_wstunnel.so\n<VirtualHost *:8080>\n ProxyPass
/ws/gateway/ ws://172.17.0.1:9000/\n\n</VirtualHost>\n" >>
/usr/local/apache2/conf/httpd.conf; httpd-foreground'

# run the curl commands to show the problem
$ curl 'http://localhost:8080/'
$ curl -v -H 'Connection: Upgrade' -H 'Upgrade: websocket'
'http://localhost:8080/ws/gateway/notification/notify'   --next
'http://localhost:8080/' ; echo


I have tried many things, setting a ttl, turning keepalive Off
globaly, adding disablereuse=On but nothing worked. Thanks in advance,
Jon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Mime
View raw message