Ratchet icon indicating copy to clipboard operation
Ratchet copied to clipboard

Can't connect to websocket with wss

Open mariobros1349 opened this issue 4 years ago • 27 comments

I'm having problems adding SSL/WSS support to my app

this is my chat-server.php:

$loop = Factory::create();

$secure_websockets = new Server($loop);
$secure_websockets->listen('8080', '0.0.0.0');
$webSock = new SecureServer($secure_websockets, $loop, [
    'local_cert' => 'path-to-file\server.crt',
    'local_pk' => 'path-to-file\server.key',
    'verify_peer' => false,
    'allow_self_signed' => true
]);

$webServer = new IoServer(
    new HttpServer(
        new WsServer(
            new Chat()
            )
        ),
    $webSock
    );
$loop->run();

On client side in javascript I'm trying to connect to the websocket with this:

connection = new WebSocket('wss://ip-address:8080');

I know that ip-address is correct and port is open

On firefox console, I'm getting this error when I try to connect to the websocket:

error { target: WebSocket, isTrusted: true, srcElement: WebSocket, eventPhase: 0, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, timeStamp: 2213441, type: "error"}

I'm not sure how to get this working, can someone help me please?

mariobros1349 avatar Apr 23 '20 23:04 mariobros1349

Try: $webServer->run();, not $loop->run();

TalR98 avatar Apr 26 '20 14:04 TalR98

You also need to add a proxy to your server. See top answer here.

TechOverflow avatar Apr 26 '20 16:04 TechOverflow

the client side error is not really helping, try looking into the server-side errormessages like this:

$secure_websockets->on('error', function (Exception $e) {
    echo 'Error' . $e->getMessage() . PHP_EOL;
});

Also, did you include "wss://" in your connection attempt?

nineff avatar Apr 30 '20 18:04 nineff

the client side error is not really helping, try looking into the server-side errormessages like this:

$secure_websockets->on('error', function (Exception $e) {
    echo 'Error' . $e->getMessage() . PHP_EOL;
});

Also, did you include "wss://" in your connection attempt?

Yes, I'm usung "wss://"

Just added the code you're suggesting, but it's not showing anything

mariobros1349 avatar May 01 '20 22:05 mariobros1349

Hey @mariobros1349 did you find any solution I am facing the same issue, works excellent on localhost but on server I get problems:

$server = IoServer::factory(new HttpServer( new WsServer( new LCMessages() ) ),8080); $server->run();

as I said on local works fine but on server not, I tried telnet serverip 8080 to test connection so I know server is available on the port. on Firefox: Firefox can’t establish a connection to the server at wss://mydomain:8080/. On Chrome: VM536:1 WebSocket connection to 'wss://mydomain:8080/' failed: WebSocket opening handshake timed out

Tried on amazon lightsail(letsencrypt secured) as well as google cloud platform(company purchased certificate).

Another detail: If I connect via php client which is running on same host I am able to connect with localhost:8080 but not from browser.

mayanktiwaridotcom avatar May 17 '20 22:05 mayanktiwaridotcom

If I connect via php client which is running on same host I am able to connect with localhost:8080 but not from browser.

The Websocet protocoll requires browsers to not give feedback on specific erros to not potentially disclose server settings or security issues. see here: https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol In this case it sounds like some issues with your SSL / TLS setup cause the browser to (correctly) refuse the connection without further detail.

This is by design, but makes debugging quite a bit harder. Some non-browser tools are more verbose however, and the server itself has any relevant information available.

nineff avatar May 23 '20 08:05 nineff

Hey @nineff

Thanks for info, I have made adjustments, and passed the milestone, but now stuck on new one.

$loop = Factory::create(); $webSock = new SecureServer( new Server('0.0.0.0:'.getenv('SOCKET_PORT'), $loop), $loop, array( 'local_cert' => getenv('CERT_PATH_CERT'), // path to your cert 'local_pk' => getenv('CERT_PATH_KEY'), // path to your server private key 'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production) 'verify_peer' => FALSE ) ); // Ratchet magic $webServer = new IoServer( new HttpServer( new WsServer( new LCMessages() ) ), $webSock ); $loop->run();

I configured like this now and it worked, websocket is able to connect and client is able to connect and everything. But this was on staging server with letsencrypt ssl. When i moved to production server It stopped working again.

On production I am using godaddy issued certificate, I made it work with the Server and Socket from Browser but PHP Client end is broken now.

\Ratchet\Client\connect(getenv('SOCKET_URL').':'.getenv('SOCKET_PORT'))->then(function ($conn) { $conn->send('test message'); $conn->close(); echo "closed"; }, function ($e) { var_dump("Could not connect: {$e->getMessage()}\n"); });

But i get "Could not connect: Connection to :8080 failed during TLS handshake: Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed "

mayanktiwaridotcom avatar May 24 '20 12:05 mayanktiwaridotcom

see here: https://stackoverflow.com/questions/32211301/ssl-error-ssl3-get-server-certificatecertificate-verify-failed

nineff avatar May 24 '20 12:05 nineff

Found this but didn't work, had to do little differently, https://github.com/ratchetphp/Pawl/issues/72 this helped, and now got it working however sometimes still getting an error (unable to write to stream: fwrite(): ssl operation failed with code 1) but working for now.

mayanktiwaridotcom avatar May 24 '20 13:05 mayanktiwaridotcom

Found this but didn't work, had to do little differently, ratchetphp/Pawl#72 this helped, and now got it working however sometimes still getting an error (unable to write to stream: fwrite(): ssl operation failed with code 1) but working for now.

Can you assist me on this here is my code:

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

    require dirname(__DIR__) . '/vendor/autoload.php';

    $server = IoServer::factory(
        new HttpServer(
            new WsServer(
                new Chat()
            )
        ),
        8080
    );

    $server->run();

don't know what to import and how to make it work with ssl and wss .. any help is appreciated a lot 👍

akramg478 avatar Oct 24 '20 18:10 akramg478

<?php

//ReactPHP Event Loop
$loop   = React\EventLoop\Factory::create();

$webSock = new React\Socket\SecureServer(
	new React\Socket\Server('0.0.0.0:8080', $loop),
	$loop,
	array(
        'local_cert' => '/home/username/public_html/certsfolder/server.crt',
		'local_pk' => '/home/username/public_html/certsfolder/server.key',
		'allow_self_signed' => false,
		'verify_peer' => false
	)
);
						
// Ratchet magic
$webServer = new Ratchet\Server\IoServer(
	new Ratchet\Http\HttpServer(
		new Ratchet\WebSocket\WsServer(
			new Chat()
		)
	),
	$webSock
);

$loop->run();

You need to copy the TLS Certificates (Letsencrypt generated or other) into a folder that is accessible to this ssh user and provide the absolute path over there.

local_cert -> path to certificate local_pk -> path to private key

for me, self signed certificates did not work somehow, probably due to some other errors in that time, and everything worked, after trying Letsencrypt certificates and some experimentation.

raghuveer avatar Feb 21 '21 20:02 raghuveer

Found this but didn't work, had to do little differently, ratchetphp/Pawl#72 this helped, and now got it working however sometimes still getting an error (unable to write to stream: fwrite(): ssl operation failed with code 1) but working for now.

Can you assist me on this here is my code:

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

    require dirname(__DIR__) . '/vendor/autoload.php';

    $server = IoServer::factory(
        new HttpServer(
            new WsServer(
                new Chat()
            )
        ),
        8080
    );

    $server->run();

don't know what to import and how to make it work with ssl and wss .. any help is appreciated a lot 👍

did you find a way to solve it?

WeaboeBucin avatar Jul 28 '21 15:07 WeaboeBucin

@WeaboeBucin do try the sample code in my comment that is above your message https://github.com/ratchetphp/Ratchet/issues/799#issuecomment-782917258

While I did not post use statements there, you can use that code sample after adding use statements (if you choose to) along with the composer autoload statement. A point to add is that, this works as so if you use Letsencrypt ssl certificates. The same concept can be used with ssl certificates that are signed by any other Certificate authority.

Note: Self Signed Certificates didnot work for me when I tried even in dev perspective as web browsers blocked accessing web socket server when self signed certificates are enabled. While I remember seeing others who used them in dev scenario, it didnot work in my attempt in the past.

Hope this helps

raghuveer avatar Jul 28 '21 15:07 raghuveer

@WeaboeBucin do try the sample code in my comment that is above your message #799 (comment)

While I did not post use statements there, you can use that code sample after adding use statements (if you choose to) along with the composer autoload statement. A point to add is that, this works as so if you use Letsencrypt ssl certificates. The same concept can be used with ssl certificates that are signed by any other Certificate authority.

Note: Self Signed Certificates didnot work for me when I tried even in dev perspective as web browsers blocked accessing web socket server when self signed certificates are enabled. While I remember seeing others who used them in dev scenario, it didnot work in my attempt in the past.

Hope this helps

i use ws, is it possible?

WeaboeBucin avatar Jul 28 '21 15:07 WeaboeBucin

@WeaboeBucin

  1. if you want to use ws then you need to run that on a port like 8080 while wss runs on port 443 using nginx as reverse proxy wherein you will install Letsencrypt ssl certificate along with certbot for ssl certificate renewal.

  2. Alternatively if you want to use wss directly then you can use the code sample that is shared in https://github.com/ratchetphp/Ratchet/issues/799#issuecomment-782917258

In my application, I had used wss through out development and before it came to an end, keeping scalability in mind and to offload responsibility of securing web sockets, I had installed nginx in reverse proxy mode while running my websocket server in ws mode, as specified in point 1.

raghuveer avatar Jul 28 '21 15:07 raghuveer

@WeaboeBucin

I was able to make it work using proxy pass on nginx

I put this in my nginx config, under ssl part: location /socket/ { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } And then i was able to connect from browser on wss://myurl.com/socket

mayanktiwaridotcom avatar Jul 28 '21 16:07 mayanktiwaridotcom

@WeaboeBucin

  1. if you want to use ws then you need to run that on a port like 8080 while wss runs on port 443 using nginx as reverse proxy wherein you will install Letsencrypt ssl certificate along with certbot for ssl certificate renewal.
  2. Alternatively if you want to use wss directly then you can use the code sample that is shared in Can't connect to websocket with wss #799 (comment)

In my application, I had used wss through out development and before it came to an end, keeping scalability in mind and to offload responsibility of securing web sockets, I had installed nginx in reverse proxy mode while running my websocket server in ws mode, as specified in point 1.

do you have a solution for apache? Because i have never used nginx even this is the first time i hear about nginx. I've run it on port 8080 while apache is running on port 443 but it's still the same.

WebSocket connection to 'ws://localhost:8080/' failed:

and this is my first time using WebSocket and I'm still learning, Sorry if I look like a fool

WeaboeBucin avatar Jul 29 '21 12:07 WeaboeBucin

Found this but didn't work, had to do little differently, ratchetphp/Pawl#72 this helped, and now got it working however sometimes still getting an error (unable to write to stream: fwrite(): ssl operation failed with code 1) but working for now.

Can you assist me on this here is my code:

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

    require dirname(__DIR__) . '/vendor/autoload.php';

    $server = IoServer::factory(
        new HttpServer(
            new WsServer(
                new Chat()
            )
        ),
        8080
    );

    $server->run();

don't know what to import and how to make it work with ssl and wss .. any help is appreciated a lot 👍

did you find a way to solve it?

You don't have to use ssl certificate on wss sever. Just run it without a certificate and use nginx reverse proxying + letsencrypt to make it ssl compatible. You can proxy paths like something.com/wss/ to your wss server 'ws://localhost:8080/' and use wss connection on the browser because your nginx server will have a valid ssl certificate provided by letsencrypt. I think is this much easier then adding that ssl directly to the ratchet server.

ahmeteminkocal avatar Aug 13 '21 20:08 ahmeteminkocal

Here is a complete tutorial I created on my blog hope it will help anyone coming here. https://tutorialsjoint.com/php-websocket-ratchet/ in this one I have included everything I have learned by working on and implementing in my own app.

mayanktiwaridotcom avatar Aug 14 '21 03:08 mayanktiwaridotcom

@mayanktiwaridotcom your tutorial used ratchet in sync with symfony components and with nginx as reverse proxy :)

raghuveer avatar Aug 14 '21 04:08 raghuveer

@WeaboeBucin as shared by @ahmeteminkocal and by me and @mayanktiwaridotcom earlier, using nginx as reverse proxy before your web socket server that runs on port 8080 (in the scope of ws://websocketserver.com:8080 or ws://websocketserver.com/ws:8080) is better and you can manage letsencrypt there with nginx.

While @mayanktiwaridotcom shared a tutorial to deal the above in sync with symfony components, if you want a more basic one, especially the ratchet setup, I had modified nginx config that is generated using https://www.digitalocean.com/community/tools/nginx

By the by, you need not use Apache in the mix, when you are using Nginx as reverse proxy that runs on port 443 and that internally forwards to web socket server (WS) running on port 8080.

raghuveer avatar Aug 14 '21 04:08 raghuveer

@WeaboeBucin I did not have an organized notes as shared in tutorial of @mayanktiwaridotcom and even though my purpose is to build on the base ratchet and it's MessageComponentInterface that I used in sync with Redis Pubsub to create a web socket hosting service then.

By the by, if you are trying to do based on Laravel, you have some options

Laravel Web Sockets: https://freek.dev/1228-introducing-laravel-websockets-an-easy-to-use-websocket-server-implemented-in-php

https://github.com/beyondcode/laravel-websockets

https://beyondco.de/docs/laravel-websockets/basic-usage/pusher

We checked this before we decided to build in a more simple way ourselves, upon Ratchet

raghuveer avatar Aug 14 '21 04:08 raghuveer

HTTP/1.1 404 Not Found Server: nginx/1.14.0 (Ubuntu) Date: Mon, 20 Sep 2021 03:46:23 GMT Transfer-Encoding: chunked Connection: keep-alive X-Powered-By: Ratchet/0.4.3

erlangparasu avatar Sep 20 '21 03:09 erlangparasu

the client side error is not really helping, try looking into the server-side errormessages like this:

$secure_websockets->on('error', function (Exception $e) {
    echo 'Error' . $e->getMessage() . PHP_EOL;
});

Also, did you include "wss://" in your connection attempt?

thank you, i was able to see the error

Error Connection from tcp://xxx:7624 failed during TLS handshake: SSL_R_NO_SHARED_CIPHER: no suitable shared cipher could be used. This could be because the server is missing an SSL certificate (local_cert context option)

hayden-t avatar May 10 '23 01:05 hayden-t

I had to check my cert paths and permissions

hayden-t avatar May 10 '23 01:05 hayden-t

i m also facing the same issue. on HTTP it was working but on HTTPS it is not working. chat:352 WebSocket connection to 'wss://example.com:8080/?token=XXXXXXXXX9a00' failed:

my nginx server block location /chat/ { proxy_pass http://websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_read_timeout 300s; proxy_send_timeout 300s; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

used certbot certificate to implement HTTPS on domain stage.example.com.

can someone plz help to resolve this? I have applied all of the above configurations but still facing the issue.

NS000001 avatar Jun 08 '23 08:06 NS000001

For reference: See #1018 by @NS000001 for a continuation of this conversation.

SimonFrings avatar Jun 12 '23 07:06 SimonFrings