Skip to content
This repository has been archived by the owner on Feb 7, 2024. It is now read-only.

Pusher http compatibility #102

Closed
jlsjonas opened this issue Feb 4, 2019 · 13 comments
Closed

Pusher http compatibility #102

jlsjonas opened this issue Feb 4, 2019 · 13 comments

Comments

@jlsjonas
Copy link

jlsjonas commented Feb 4, 2019

image
It looks like there's some incompatibilities with the pusher/echo client.

Above is trying to make a POST request to the url, however only GET & HEAD is allowed

@stayallive
Copy link
Contributor

That looks like it's falling back to XHR streaming which is not implemented by this package only websockets.

https://pusher.com/docs/fallbacks

Try adding the enabledTransports key to your Pusher config (below an example for Laravel Echo) with the value: ['ws', 'wss'] so it does not try to fallback to other methods Pusher.com does support.

window.Echo = new Echo ({
	broadcaster: 'pusher',
	key: 'my-key',
	wsHost: window.location.hostname,
	wsPort: 6001,
	wssPort: 6001,
	disableStats: true,
    enabledTransports: ['ws', 'wss'], // <-- only use ws and wss as valid transports
});

Then there is probably a connection error of some sort for it to resort to XHR streaming and not able to connect to you websockets server.

@jlsjonas
Copy link
Author

jlsjonas commented Feb 4, 2019

That makes sense (probably should be in the docs though?)

For some reason the websocket connection is indeed not established on the server (works fine locally)
websockets:serve command shows no output whatsoever (except for the listening message), firewall is open, SELinux set correctly; tried permissive & firewall off just to be sure; any ideas what might be causing it?
(using apache + let's encrypt, ports & hosts set correctly; ssl config (in config/websockets.php) contains the local_cert)

@stayallive
Copy link
Contributor

Yeah that should be in the docs (considering the many issues about it...).

That can have a million reasons really :)

Make sure you are using the certificate files (#92 (comment)) this bit a few people already and also you have both the local cert and pk config option set.

If certificate is all good check if there are any message in the developer console of the browser that might give some insight in could be breaking.

If there is no output at all in your browser console make sure you are not using a port that is not allowed by the browser (more about that here: https://alex.bouma.me/installing-laravel-websockets-on-forge/#a-note-about-ports).

@jlsjonas
Copy link
Author

jlsjonas commented Feb 4, 2019

image

I did derp up and only included the PK. not the cert; however the issue seems to remain exactly the same after correcting the mistake. I've also (as per linked comment in #92) checked with more permissive permissions, to no avail.
Very strange that I get no output whatsoever on :serve though (although likely intentional?)

@jlsjonas
Copy link
Author

jlsjonas commented Feb 4, 2019

image

looks like my firewall was really acting up, opening port 6001 & disabling the firewall didn't seem to have been applied. so it's no longer timing out (thanks good old telnet for discovering that 😅 )
However, still no errors whatsoever, but it's cancelling out instead 😅

Note: as webmin generates the let's encrypt certificates, I don't have a "fullchain" as per the linked comment; however Let's Encrypt should be a recognized CA so I'm not sure if related, especially as I disabled client-side checks. (and without logs/errors it's very hard to debug)

@stayallive
Copy link
Contributor

stayallive commented Feb 4, 2019

Looking at this it does still look like a certificate error: https://stackoverflow.com/questions/31664366/chrome-failing-to-connect-to-websocket-server-opcode-1-handshake-was-cancele. I don't think you need to do anything the accepted answer says, but do need to make sure the certificate (file) is correct.

Maybe you could try to create your own fullchain.pem combining the contents of letsencrypt-cert.pem, letsencrypt-ca.pem (in that order), however it does look like /etc/letsencrypt/live/ could contain your domain name as folder and could have the fullchain.pem file inside of there looking at webmin threads.

There is currently no error if you supply an invalid or incomplete certificate (#92 (comment)) so that definitely doesn't help, but of a hit and miss right now :)

@jlsjonas
Copy link
Author

jlsjonas commented Feb 4, 2019

I just checked and it seems to match with chrome failing; it works just fine under firefox
guess the most popular browsers will remain cursed with odd bugs (now that IE became less of an issue, chrome is becoming one 😅 )

I'll check; but that won't be a sustainable solution as our LE certificates change bi-monthly
/etc/letsencrypt doesn't exist on my system, btw

@stayallive
Copy link
Contributor

stayallive commented Feb 4, 2019

Running the concatenation in a cron should help with that (you need to restart your websocket server each the the certificate changes anyhow), but this is more a problem with webmin than this package I think (except the error reporting for an incorrectly configured certificate ofcourse).

@jlsjonas
Copy link
Author

jlsjonas commented Feb 5, 2019

The concatenated version ended up with a failed: Error in connection establishment: net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH
and SSL_ERROR_NO_CYPHER_OVERLAP on firefox

further investigations lead me... nowhere 😅
I'll create a cert using certbot for l-w I guess.

Either way, I do believe having an option to include the intermediate certificates as a parameter instead of requiring to provide a combined file would be a more lenient solution; there's several CA's that don't provide a combined file, similar to what apache requires

image

Above is a working configuration, to combine them I tried
cat letsencrypt-cert.pem letsencrypt-ca.pem > letsencrypt-combined.pem
along with the pk defined separately and
cat letsencrypt-key.pem letsencrypt-cert.pem letsencrypt-ca.pem > letsencrypt-combined.pem
with no success

Thanks for the help so far, the issue might be broader than this package indeed; though I do believe if the configuration works for apache it should arguably work out for this too.

@stayallive
Copy link
Contributor

Now I'm all out of ideas too, great problem! If you do find something it would be really useful to leave here or PR a documentation change to include your findings!

Thanks for the help so far, the issue might be broader than this package indeed; though I do believe if the configuration works for apache it should arguably work out for this too.

Well the current config for this package works for NGINX, so I guess arguments could be made for every server software that handles SSL just a bit differently (don't even get me started about IIS).

As a general note, I would always place your websockets server behind a reverse proxy like NGINX (or I believe Apache can do the same) so the websockets server doesn't have to handle SSL at all and offload those CPU cycles to more competent and faster applications designed for that work, this way you also don't have to worry about restarting your websockets server when a certificate or config changes but restarting the proxy server (be it Apache or NGINX) is enough. This also has the benefit if your app being able to speak in plain text to the websockets server making it slightly faster. For inspiration: I wrote this blog for Forge & NGINX, that might give you some ideas on how to replicate it for Apache if you want to go that route.

@jlsjonas
Copy link
Author

jlsjonas commented Feb 5, 2019

It looks like I missed Apache's support for reverse-proxying websockets before, and since (luckily) I don't seem to have a collision with /app on my existing routes I just had to add ProxyPass "/app/" "ws://127.0.0.1:6001/app/" to my existing SSL directives. (or alternatively create a separate virtualhost for this purpose, you'd use "/" instead then)

Thanks a lot!

as for documentation ideas/notes:

  • make a reverse-proxy recommendation (maybe also hint at requiring a restart after let's encrypt update otherwise)
  • note on using http://127.0.0.1:6001 for broadcasting.php (I made a localpusher connection for that purpose, as my code takes the Echo FE variables from the pusher connection)
        'localpusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'host' => '127.0.0.1',
                'port' => 6001,
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'scheme' => 'http',
            ],
        ],
  • ProxyPass "/app/" "ws://127.0.0.1:6001/app/" (docs) and/or your blogpost for Forge/NGINX

EDIT: note that, for some reason, I had to remove the proxypass, save, reload, add it again, save, reload for everything to work.

@jlsjonas jlsjonas closed this as completed Feb 5, 2019
@amirreza1751
Copy link

Hello @jlsjonas .
I have this problem with laravel websockets and it has taken my time. I still get this error on web browser and I don't know what must be changed. can you help me fix this problem by explaining more about your solution?
Here is my error.

@amirreza1751
Copy link

WebSocket connection to 'wss://domain:6001/app/ABCDEFG?protocol=7&client=js&version=4.3.1&flash=false' failed: Error in connection establishment: net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH

I will send my configs if you need.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants