passenger icon indicating copy to clipboard operation
passenger copied to clipboard

WebSockets don't work on Apache

Open FooBarWidget opened this issue 10 years ago • 43 comments

If the response has the chunked transfer encoding, then WebSockets handshakes become corrupted. See https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/phusion-passenger/XtjxA8E1idw/Z029OysamjsJ for the report.

FooBarWidget avatar Jun 01 '14 15:06 FooBarWidget

See also https://github.com/phusion/passenger-nodejs-websocket-demo/issues/2

FooBarWidget avatar Jun 01 '14 15:06 FooBarWidget

The chunked encoding problem can be solved by setting Content-Length: 0 in the response, which will prevent Apache from setting Transfer-Encoding.

// Process WebSocket upgrade.
Header upgrade = lookupHeader(headerData, "Upgrade", "upgrade");
if (!upgrade.empty()) {
    RH_TRACE(client, 2, "WebSocket upgrade detected.");
    headerData.append("Content-Length: 0\r\n");
}

However, it looks like the problem is more complicated than just solving this. The current Apache module currently does not support simultaneously forwarding request data and response data, so WebSockets still doesn't work. Worse, instead of triggering an error, the connection just freezes.

Fixing this is non-trivial. I'm postponing it to a later release.

FooBarWidget avatar Jun 02 '14 07:06 FooBarWidget

:+1: Waiting for this eagerly.

captn3m0 avatar Nov 25 '14 06:11 captn3m0

+1

kiranos avatar Dec 17 '14 14:12 kiranos

any news on this?

kiranos avatar Feb 26 '15 19:02 kiranos

Unfortunately not. If you need WebSockets, for the time being we recommend using Nginx, or using Passenger Standalone behind Apache + mod_proxy.

FooBarWidget avatar Feb 26 '15 19:02 FooBarWidget

See https://github.com/phusion/passenger-ruby-websocket-demo/issues/2, appears WebSockets are still not working under Apache mod_passenger in 5.0.18? (It's very possible that I am doing something wrong in my Apache .conf) Thanks for Passenger - it's incredible!

vanboom avatar Sep 19 '15 14:09 vanboom

@vanboom That is correct, WebSockets do not work yet in the Apache version. For the time being, we recommend that you use the Nginx version, or Apache + Standalone in a reverse proxy setup, if you need WebSockets.

FooBarWidget avatar Sep 23 '15 04:09 FooBarWidget

It has been almost a year since the last update. Did the upgrade to apache 2.4.x improve this?

ThaddeusAid avatar Jul 09 '16 00:07 ThaddeusAid

There is a websocket proxy module now for Apache 2.4, however we have not found it to be robust enough to recommend yet.

CamJN avatar Aug 09 '16 19:08 CamJN

Just discovered passenger, sounds like a gift from heaven. :+1: In the project I want to use to explore passenger, I can set specific ports (or env var names to read the ports from) for WebSockets and EventSource, will that help? It's meant as a work-around to use with Apache's mod_proxy, but maybe passenger can intercept to sanitize and monitor stuff.

mk-pmb avatar Aug 14 '16 19:08 mk-pmb

Just for the record, some people seem to have managed to use websockets in apache with wstunnel.

mk-pmb avatar Oct 14 '16 23:10 mk-pmb

Yes, that's the websocket proxy module I mentioned, however it only works for some people. We'll consider recommending it when it is more robust.

CamJN avatar Nov 11 '16 01:11 CamJN

@CamJN - out of interest, what issues did you have with the websocket module in Apache? I presume there's some work involved on the Passenger side to integrate (if possible) with that so ActionCable will work through Passenger directly. We're looking at a future development project that will require ActionCable and ideally we'd like Passenger to support this if possible.

jamgregory avatar Dec 21 '16 10:12 jamgregory

As one example since this module is just a websocket-aware proxy, you need proxy support in your websocket library so it won't just work for everyone.

CamJN avatar Dec 22 '16 17:12 CamJN

you need proxy support in your websocket library

What features will that consist of? Can I test all those features on a per-app level, independent of which ws lib it uses? Would it help to have a shims option where I can configure what workarounds to use until some feature is available?

One feature I might imagine as "proxy support" would be about determining the IP from which a connection arrives. A work-around might be to specify the network interface from which the proxy should send its packets, to ensure it uses an interface (and thus IP address) that my statistics can identify as "not a real visitor" and which the app doesn't assume as privileged in any way. The setting might have an optional "allow localhost" flag which determines whether to fail loudly in case the specified interface will be undistinguishable from localhost.

mk-pmb avatar Dec 22 '16 21:12 mk-pmb

What features will that consist of?

Generating urls for links and js that refer to the proxy's url/port not the app's.

Can I test all those features on a per-app level, independent of which ws lib it uses?

No, because they have to come from the ws lib.

Would it help to have a shims option where I can configure what workarounds to use until some feature is available?

Yes, but I don't know if such a thing exists.

CamJN avatar Dec 23 '16 16:12 CamJN

I'll share my idea since I couldn't finish my research on it: A lot of web apps have their websockets behind very few, short URL prefixes like /ws/ (http://api.example.com/ws/chat). If we can make the browser and potential proxies send the websocket request as the first request in the TCP connection (a randomly selected subdomain should suffice), a netfilter string match or l7-filter should be able to pick up on the request URL and NAT it to bypass Apache. (Please make double sure to avoid false positive matches.)

For HTTPS, we could hope that browsers that support websockets will also use Server Name Indication (SNI), so netfilter might be able to detect a hostname that an app can use exclusively for its websockets, and then redirect that port 443 connection to the app directly, or an auxiliary web server, again bypassing Apache. Update: SNI hostname transmission happens too late (usually not in the first packet) for easy methods of port redirection.

mk-pmb avatar Aug 17 '17 19:08 mk-pmb

Anyone having any luck with this? mod_wstunnel has been around for a while now. We've had no problem getting websockets to work over an Apache reverse proxy using mod_wstunnel. However, still not sure how to get this to work using Passenger in Apache integration mode.

blevine avatar Nov 15 '17 18:11 blevine

Any one have luck to get websocket work with Apache? This is my Apache configure get from: https://www.phusionpassenger.com/library/walkthroughs/deploy/meteor/ownserver/apache/oss/xenial/deploy_app.html#edit-apache-configuration-file

But the websocket won't work.. I'm using Ubuntu 16.04, Apache 2.4.18, Phusion Passenger 5.2.0

heangratha avatar Feb 02 '18 03:02 heangratha

@heangratha - the only solution we could come up with was to run a separate instance of the app in Puma, then proxy all WebSocket requests to that using mod_wstunnel.

jamgregory avatar Feb 02 '18 06:02 jamgregory

Any movement on this issue?

thomasbalsloev avatar Aug 07 '18 08:08 thomasbalsloev

Not right now, it is unfortunately not a priority at the moment. People are recommended to use nginx if they need websockets, as it's still a pain with Apache.

CamJN avatar Aug 07 '18 13:08 CamJN

@CamJN

OK, I see. Thank you for the update.

thomasbalsloev avatar Aug 07 '18 13:08 thomasbalsloev

Update on my research (it's on the back burner though): We could probably write a module like fdpass to get the socket descriptors. We'd then have to exfiltrate the connection's SSL context (ideally: compile Apache with an SSL lib that officially supports this; worst case: dump worker's process memory, then recover forensically) and send that along with the connection socket file descriptor to a server that can receive both and continue the SSL session. The metasploit codebase probably has useful parts to reuse here.

Generating urls for links and js that refer to the proxy's url/port not the app's.

I'm optimistic that URL rewriting might be an option for people with a bit of backgorund knowledge about the app – which the app's admin should have.

mk-pmb avatar Aug 07 '18 14:08 mk-pmb

Is this a wontfix?

siegy22 avatar Mar 25 '19 10:03 siegy22

@siegy22 not exactly, but it's blocked on the Apache project improving their module.

CamJN avatar Mar 25 '19 14:03 CamJN

@vanboom That is correct, WebSockets do not work yet in the Apache version. For the time being, we recommend that you use the Nginx version, or Apache + Standalone in a reverse proxy setup, if you need WebSockets.

@FooBarWidget how can i do it (Apache + Standalone in a reverse proxy setup)?"still newer in servers configs"

annymosse avatar Nov 27 '19 15:11 annymosse

@annymosse How to install Passenger Standalone Once you have that running, it gives a web server. You'll want to ensure it is not reachable directly from the outside. To achieve this, you can use explicit interface binding (to a non-public interface) and/or firewall rules. The Apache Reverse Proxy Guide shows how to make a publicly reachable apache forward traffic for some parts of your URL space, to the guarded private Passenger server.

mk-pmb avatar Nov 28 '19 00:11 mk-pmb

Does this apply to cpanel ?

beppe9000 avatar Mar 24 '20 14:03 beppe9000