We are attempting to use Apache 2.6.18 as a Load Balancer / Proxy to front end a cluster of Tomcat application servers. The back end servers are running an application that uses WebSockets to increase performance. We have been unable
to find an Apache Web Server configuration that will not strip out the WebSocket Upgrade headers (Connection: Upgrade and Upgrade: websocket). In an effort to understand the problem, we have installed another Load Balancer / Proxy (HAProxy). This second
system seems to work with web sockets - the following scenario shows the result of a WebSocket upgrade request from a client processed through the working Load Balancer / Proxy: Working scenario with HAProxy: 1. Client browser requests WebSocket protocol upgrade from Load Balancer / Proxy: GET /TestApp/AsynchEPSGeneric HTTP/1.1 Host: austenite.wellsnet.org Connection: Upgrade Pragma: no-cache Cache-Control: no-cacheUpgrade: websocket Origin: http://austenite.wellsnet.org Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/48.0.2564.82 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 Cookie:JSESSIONID=B~91D59D42D9718239B1FD0F2725C3E4EF.jvm2 Sec-WebSocket-Key: FbhlH5QHSyOPgkjqnNYNeA== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits 2. The Load Balancer / Proxy forwards the request to one of the back end servers: GET /TestApp/AsynchEPSGeneric HTTP/1.1 Host: austenite.wellsnet.org Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: http://austenite.wellsnet.org Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/48.0.2564.82 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 Cookie: JSESSIONID=91D59D42D9718239B1FD0F2725C3E4EF.jvm2 Sec-WebSocket-Key: FbhlH5QHSyOPgkjqnNYNeA== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits X-Forwarded-For: 172.16.1.173 3. The selected back end server processes the request for an upgrade to the WebSockets protocol and sends the appropriate response: HTTP/1.1 101 Switching Protocols Server: Apache-Coyote/1.1 Upgrade: websocket Connection: upgrade Sec-WebSocket-Accept: wJZKVAVOsNe9ASj3LX34SHsbP9o= Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15 Date: Tue, 26 Jan 2016 22:42:52 GMT 4. The response is then forwarded on to the client browser, and everything proceeds normally: HTTP/1.1 101 Switching Protocols Server: Apache-Coyote/1.1 Upgrade: websocket Connection: upgrade Sec-WebSocket-Accept: wJZKVAVOsNe9ASj3LX34SHsbP9o= Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15 Date: Tue, 26 Jan 2016 22:42:52 GMT When using Apache 2.6.18, the WebSocket upgrade request fails due to stripped html headers: 1. Client browser requests WebSocket protocol upgrade from Load Balancer / Proxy: GET /TestApp/AsynchEPSGeneric HTTP/1.1 Host: austenite.wellsnet.org Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: http://austenite.wellsnet.org Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/48.0.2564.82 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 Cookie: JSESSIONID=05A2F44A2887677F1AD3C0A3337A3725.jvm2 Sec-WebSocket-Key: ZsVIsQ7X7+3i5LeiqO4yXQ== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits 2. The Load Balancer / Proxy forwards the request to one of the back end servers. Notice that among other things, the "Connection: Upgrade"
and "Upgrade: websocket" headers have been stripped: GET /TestApp/AsynchEPSGeneric HTTP/1.1 Host: dianthus.wellsnet.org:8080 Pragma: no-cache Cache-Control: no-cache Origin: http://austenite.wellsnet.org Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 Cookie: JSESSIONID=05A2F44A2887677F1AD3C0A3337A3725.jvm2 Sec-WebSocket-Key: ZsVIsQ7X7+3i5LeiqO4yXQ== Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits X-Forwarded-For: 172.16.1.173 X-Forwarded-Host: austenite.wellsnet.org X-Forwarded-Server: austenite.wellsnet.org Connection: Keep-Alive 3. Since the WebSocket headers have been stripped, the selected back end server attempts to process the URI as a physical file, and fails with 404: HTTP/1.1 404 Not Found Server: Apache-Coyote/1.1 Content-Type: text/html;charset=utf-8 Content-Language: en Content-Length: 1060 Date: Tue, 26 Jan 2016 22:55:23 GMT 4. This reply is then passed to the client, with the end result that the websocket connection fails: HTTP/1.1 404 Not Found Date: Tue, 26 Jan 2016 22:55:23 GMT Server: Apache-Coyote/1.1 Content-Type: text/html;charset=utf-8 Content-Language: en Content-Length: 1060 We have tried various configuration settings as well as adding the mod_proxy_wstunnel module and configuration example settings from the
Apache help. So far none of these changes have prevented the headers from being stripped out in the WebSocket request. Does the Apache Web Server support
Proxy / Load balancing of WebSocket connections? Thanks, Tom Thomas S. Bumbernick Office +1 404-648-7580 |