ratchetphp / Ratchet

Asynchronous WebSocket server
http://socketo.me
MIT License
6.26k stars 734 forks source link

Ratchet websocket SSL connect? #100

Closed vietnguyen09 closed 11 years ago

vietnguyen09 commented 11 years ago

Hi cboden!

I have a ratchet chat server file


use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use MyAppChat\Chat;
    require dirname(__DIR__) . '/vendor/autoload.php';
    $server = IoServer::factory(
        new WsServer(
            new Chat()
        )
      , 26666
    );
    $server->run();

i using JS Websocket connect success throw http

if ("WebSocket" in window) {
    var ws = new WebSocket("ws://ratchet.mydomain.org:8888");
    ws.onopen = function() {
        // Web Socket is connected. You can send data by send() method.
        ws.send("message to send");
    };
    ws.onmessage = function (evt) { 
        var received_msg = evt.data;
    };
    ws.onclose = function() { 
        // websocket is closed. 
    };
} else {
  // the browser doesn't support WebSocket.
}

I will install SSL in my webserver and try connect via SSL but failed

if ("WebSocket" in window) {
    var ws = new WebSocket("wss://ratchet.mydomain.org:8888");
    ws.onopen = function() {
        // Web Socket is connected. You can send data by send() method.
        ws.send("message to send");
    };
    ws.onmessage = function (evt) { 
        var received_msg = evt.data;
    };
    ws.onclose = function() { 
        // websocket is closed. 
    };
} else {
  // the browser doesn't support WebSocket.
}

My question is how can using ratchet for websocket SSL connection?

Thanks

cboden commented 11 years ago

The best solution would be to use Nginx as your web server. Have Nginx listen on port 80 for incoming connections and have it handle your SSL. Nginx will forward incoming connections to PHP-FPM for your regular website and if it detects a connection is a WebSocket connection have it proxy to your running Ratchet application on a port of your choice. Your javascript could then connect via wss://mydomain.org

Nginx SSL docs Nginx WebSocket docs

cboden commented 11 years ago

Closing this issue in favour of Mailing List thread since this is more documentation than it is a bug.

karborator commented 9 years ago

And what about if I'm using Apache 2.2.5. Any options ?

cboden commented 9 years ago

You could try mod_proxy_wstunnel

mohsinmr commented 7 years ago

I am using IIS for this and used URL rewriting but still getting 400 bad request error :( any help?

mohsinmr commented 7 years ago
$server = IoServer::factory(
            new HttpServer(
                new WsServer(
                    new Chat()
                )
            ),
            8888,
            SERVER_IP
        );

SSL is installed on port 8844

Under https configured project in IIS, i have added a rewrite rule IIS - URL Rewriting Inbound Rule Action http://000.000.00.000:8888/{R1}

blackerfin commented 7 years ago

For me, the solutions was:

Open /etc/apache2/sites-enabled nano 000-default-le-ssl.conf and add ProxyPass /wss2/ ws://mydomain.es:8888/

In javascript new WebSocket("wss://mydomain/wss2/:8888");

I hope this can be usefull for somebody.

regards.

Updated.

icyz commented 7 years ago

why use new WebSocket("wss://mydomain/wss2/8888"); ?

blackerfin commented 7 years ago

Sorry! I copy-paste,

Is WebSocket("wss://mydomain/wss2/:8888").

8888 is the port.

blackerfin commented 7 years ago

This is my javascript to try (not is a optimal code, is only for tries)

<script>

    jQuery(document).ready(function($){
        var WebSocketKK = {
            CONECTANDO: 0,
            CONECTADO : 1,
            CERRANDO  : 2,
            CERRADO   : 3,
            url: "yourdomain/wss2/", 
            puerto: "8888",
            protocolo: "wss",
            conn : null,
            finalUrl: "",
            init: function(){
                $("#estado-websocket").val("DESCONECTADO");
                this.finalUrl = this.protocolo+"://"+this.url;
                if (parseInt(this.puerto)>0){
                    this.finalUrl= this.finalUrl+":"+this.puerto;
                }

                if (this.conn==null){
                    this.conectarWebSocket();
                }

                this.setManejadores();

                $("#ip").val(this.url);
                $("#puerto").val(this.puerto);
        },
        setManejadores: function(){
            $("#envia-mensaje-prueba").click(function(){
                WebSocketKK.enviarMensaje(WebSocketKK);
            });

            $("#conectar-websocket").click(WebSocketKK.conectarWebSocket);
            $("#desconectar-websocket").click(WebSocketKK.desconectarWebSocket);

            $("#ip").on("change", function(){
                WebSocketKK.url = $("#ip").val();

                WebSocketKK.finalUrl = WebSocketKK.protocolo+"://"+WebSocketKK.url;
                if (parseInt(WebSocketKK.puerto)>0){
                    WebSocketKK.finalUrl= WebSocketKK.finalUrl+":"+WebSocketKK.puerto;
                }

            });

             $("#puerto").on("change", function(){
                WebSocketKK.puerto = $("#puerto").val();

                WebSocketKK.finalUrl = WebSocketKK.protocolo+"://"+WebSocketKK.url;
                if (parseInt(WebSocketKK.puerto)>0){
                    WebSocketKK.finalUrl= WebSocketKK.finalUrl+":"+WebSocketKK.puerto;
                }

            });

            $("#protocolo").on("change", function(){
                WebSocketKK.protocolo = $("#protocolo").val();

                WebSocketKK.finalUrl = WebSocketKK.protocolo+"://"+WebSocketKK.url;
                if (parseInt(WebSocketKK.puerto)>0){
                    WebSocketKK.finalUrl= WebSocketKK.finalUrl+":"+WebSocketKK.puerto;
                }

            });

        },
        conectarWebSocket: function(){
            var $self = WebSocketKK;

            $("#estado-websocket").val("CONECTANDO");

            if (typeof $self.conn!="undefined" && $self.conn!=null && $self.is(WebSocketKK.CONECTADO)){
                $("#estado-websocket").val("YA ESTÁS CONECTADO!");
                return false;
            }

            $self.conn = new WebSocket($self.finalUrl);

            $self.conn.onopen = function(e){
                $("#estado-websocket").val("CONECTADO!");
                console.log("Conexión establecida con el WebSocket", e);
            };

            $self.conn.onmessage = function(e){
                /*e have a key named data. Is a JSON object with date, from and msg keys.*/
                console.log("Mensaje recibido: "+e.data, e);
                var mensaje = JSON.parse(e.data);
                $("#dialogo").append(
                    $("<p/>").html("("+mensaje.date+") "+mensaje.from+": "+mensaje.msg)
                )
            }

            $self.conn.onclose = function(e){
                console.log("Conexión cerrada: ", e);
                $("#estado-websocket").val("DESCONECTADO");
            }

            $self.conn.onerror = function(e){
                console.log("Se ha producido un error: ", e);
                $("#estado-websocket").val("ERROR");
            }
        },
        desconectarWebSocket: function(){
            var $self = WebSocketKK;
            console.log("Desconectando websocket");
            if ($self.is($self.CONECTADO)){
                $self.conn.close();
            }else{
                $("#estado-websocket").val("NO ESTA CONECTADO");
            }

        },
        is:function(estado){
            var $self = WebSocketKK;
            return estado===$self.conn.readyState;
        },
        enviarMensaje: function($self){
            var mensaje = $("#mensaje").val();

            if (!$self.is($self.CONECTADO)){
                $("#estado-websocket").val("PRIMERO CONECTA");
                return false;
            }

            if (mensaje.length>0){
                $self.conn.send(mensaje);
                $("#dialogo").append(
                    $("<p/>").html("TÚ: "+mensaje)
                );
            }else{
                $("#estado-websocket").val("MENSAJE VACIO");
            }
        }

    };

        WebSocketKK.init();
    });

</script>

`

I have tried to paste the html but github post not allow the html tags. Then I have replace the < and > with #.

`#select id="protocolo"#

option value="wss"#WSS#/option

#option value="ws"#WS#/option#

/select

input type="text" id="ip"

input type="text" id="puerto"

input type="text" disabled id="estado-websocket"

button id="conectar-websocket"#Conectar#/button

button id="desconectar-websocket"#Desconectar#/button

input type="text" id="mensaje"

button id="envia-mensaje-prueba"#Enviar#/button#`

Maybe can be usefull for somebody.

Bye.

icyz commented 7 years ago

Thanks for your reply

I have tried this but doesn't works:

sites-enabled/000-default-le-ssl.conf: ProxyPass /wss2/ ws://test.fasys.it:8888/

my ratchet socket php file: $app = new Ratchet\App('test.fasys.it', '8888', '0.0.0.0');

and js client: wss://test.fasys.it/wss2/:8888/chat

also tried: wss://test.fasys.it/wss2/

blackerfin commented 7 years ago

I think that the correct way is the second options (wss://test.fasys.it/wss2/) but you must to add the port (8888), then, de final url for websocket is (wss://test-fasys.it/wss2/:8000.

I need try but I think that if you want pass parameters (chat) at url you must change the ProxyPass.

In this moment I'm working but this afternoon I write a post with the steps that I have did to configure my DigitalOcean's Droplet and the PHP code of my example. Maybe can help you.

PD: Sorry for my english :D

regards.

icyz commented 7 years ago

Thanks you so much. I really appreciate your help. I have tried but nothing. Without SSL it works, with SSL not.

blackerfin commented 7 years ago

Hello again,

Fisrt I need explain that I have install Lets Encrypt certificate and, I think that, for this reason, mi conf file is named 000-default-le-ssl.conf.

You have the same file? Your file must see like this more or less:

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        <Directory /var/www/html/>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_dir.c>
            DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm
        </IfModule>

SSLCertificateFile /etc/letsencrypt/live/yourdomain.xxx/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.xxx/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ServerName yourdomain.xxx
ProxyPass /wss2/ ws://yourdomain.xxx:8888/
</VirtualHost>
</IfModule>

You can see that I have put 8888, the same port that I must put in the chat-server.php file later.

I have a DigitalOcean's Droplet with Lamp.

I supose that the steps are similars in others distributions of linux.

The steps that I have made are (after install Lets Encrypt):

1) Create a folder for websocket files. For example /var/www/html/websocket 2) Goto inside this folder. 3) Install composer: 3.1 php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 3.2 php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" 3.3 php composer-setup.php 3.4 php -r "unlink('composer-setup.php');"

4) Install Ratchet WebSocket (I use this link http://socketo.me/docs/install). Type the next command inside of websocket folder: 4.1 php composer.phar require cboden/ratchet

In this moment you should see that, inside websocket folder, have the next files: composer.json composer.lock composer.phar vendor

5) Create, inside websocket folder, the folders src and bin and, inside src, create a MyApp folder (this steps is obtain from this url: http://socketo.me/docs/hello-world)

Then, you have the next files/folders: composer.json composer.lock composer.phar vendor src/MyApp bin

6) Edit composer.json file: type nano composer.json in the console. Your file must see similar to:

{
    "autoload": {
        "psr-0": {
            "MyApp": "src"
        }
    },
    "require": {
        "cboden/ratchet": "0.3.*"
    }
}

The steps 7 and 8 are extracted from Ratchet web.

7) Create an file named server-chat.php inside websocket/bin folder. Your file must see similar to:

<?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()
            )
        ),
        8888
    );

    $server->run();

I have put 888, the same port that the ProxyPass line.

8) Create an file named Chat.php inside websocket/src/MyApp folder. Your file must see similar to:

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }
}

9) Type the next comand inside websocket folder: php composer.phar install. This command execute the composer.json. If you dont type this command and run chat-server.php you will see errors in the execution.

10) Create a index.php file inside the websocket folder. This file is only to try your websocket connection. This file should contain the code that I have put in the last post (HTML and JavaScript)

11) Type the next command inside websocket folder: php bin/server-chat.php

If you dont have problems the console is waiting.

Now open in your web browser the path of websocket, for example: http://www.yourdomain.xxx/websocket/ and you must see the content of index.php

If you have copy/paste my javascript and html code you can see the "Conectado!" message inside a input text.

The attached zip have all files from my project. This work with wss and ws.

websocket.zip

I think that is all! This work for me. I hope that this can help you.

Regards!

Edit:

If you want to do permanent the chat-server.php you can type this command inside the websocket/bin folder:

nohup php chat-server.php &

If you can stop the web socket you can type:

ps aux | less | grep ratchet

Find the pid process and kill it.

If after all this, you can not connect, try to type this command (only if not work):

iptables -A INPUT -p tcp --dport 8888 --jump ACCEPT

nishanth6 commented 5 years ago

After installing lets Encrypt Will some one answer to this issue Click Here

@blackerfin @cboden

paamayim commented 5 years ago

@blackerfin In addition to the above config, I'd like to add:

Make sure the appropriate Apache modules are enabled. That includes proxy and _proxywstunnel.

nstechns commented 5 years ago

if you are using laravel library cboden/ratchet for socket then go to app/Console/Commands/WebSocketServer.php Replace handle function with these lines of code and use your certification file path 'local_cert' and 'local_pk'


public function handle()
{

    $loop   = Factory::create();
    $webSock = new SecureServer(
        new Server('0.0.0.0:8090', $loop),
        $loop,
        array(
            'local_cert'        => '/opt/ssl/chamberstock_com.crt', // path to your cert
            'local_pk'          => '/opt/ssl/server.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 WebSocketController()
            )
        ),
        $webSock
    );
    $loop->run();

}
hugomesquita-dev commented 4 years ago

Hello, I was able to solve the problem by creating a reverse proxy access the apache2 configuration file related to the site, cd / etc / apache2 / sites-enabled / nano 000-default.conf adding the line: ProxyPass / wss2 / ws: //yourdomain.com: 8383 / at the end of the tag

in the javascript script.js file configure the link to access the websocket as follows:   var conn = new WebSocket ('wss: //yourdomain.com/wss2/: 8383 / chat');

in this example the entire code is only in the chat folder

periyasamy2git commented 3 years ago

For me, the solutions was:

Open /etc/apache2/sites-enabled nano 000-default-le-ssl.conf and add ProxyPass /wss2/ ws://mydomain.es:8888/

In javascript new WebSocket("wss://mydomain/wss2/:8888");

I hope this can be usefull for somebody.

regards.

Updated.

Its not wokring for me !!!

nassian commented 3 years ago

For me, the solutions was: Open /etc/apache2/sites-enabled nano 000-default-le-ssl.conf and add ProxyPass /wss2/ ws://mydomain.es:8888/ In javascript new WebSocket("wss://mydomain/wss2/:8888"); I hope this can be usefull for somebody. regards. Updated.

Its not wokring for me !!!

try this format in javascript wss://mydomain:443/wss2/

itquelle commented 3 years ago

I had the same problems! Here is my solution

I use

  1. I add a ProxyPass to httpd.conf (but in my case, on Plesk -> Project Apache/Nginx Settings (Additional directives for HTTPS ) )
  2. Set: ProxyPass /wss2/ ws://ip.domain.com:8888/
  3. Plesk restart apache2 after save settings (service apache2 restart)
  4. I start the websocket server with Port 8888 (Ratchet Websocket PHP)
  5. After then i check (etc/apache2/sites-available/default-ssl.conf) -> My SSL Port is 7081, not 443 (And that's the problem why it doesn't work) (Got a 500 Error with Port 443)
  6. Then JS: var socketConnection = new WebSocket('wss://ip.domain.com:7081/wss2/'); ...

Then it works for http:// and https://

Sorry for my english.

Greetings Stevie Ray

simillo01 commented 2 years ago

My solution in 2022: 1) PHP file server.php for WSS must look like: `$app = new HttpServer( new WsServer( new Chat() ) );

$loop = Loop::get();
$secure_websockets = new React\Socket\SocketServer('127.0.0.1:8090', [
    'local_cert' => 'server.crt', // path to your cert
    'local_pk' => 'server.key', // path to your server private key
    'verify_peer' => false
], $loop);

$secure_websockets_server = new IoServer($app, $secure_websockets, $loop);
$secure_websockets_server->run();`

this is done using php 8.1.6 .

2) JS part must look like this: var conn = new WebSocket('wss://127.0.0.1/wss2/'); where "wss2" is your virtual folder, so you could set "chat" or "wss" or whatever you want.

3) Apache latest version, httpd-ssl.conf file: since i want only HTTPS i put ProxyPass /wss2/ ws://127.0.0.1:8090/ in the config at the end... i know it's a bit rough/raw but i have to made it work by the end of the day. PS. the "wss2" word must coincide with the "wss2" folder wrote in the JS file.

4) Start the server.php and load the front end page with the other stuff, then enjoy.

Questions that i have to answer:

m66g commented 2 years ago

Thank you very much, @simillo01, your solution worked for me, altough I needed some more settings. Thanks as well to all who have contributed before. Here es my complete code:

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
use React\Socket\SecureServer;

use Service\WebSocket\Chat;

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

$app = new HttpServer(
   new WsServer(
      new Chat()
   )
);

$loop = Factory::create();
$secure_websockets = new React\Socket\SocketServer('127.0.0.1:8080', [
    'local_cert' => 'server.crt', // path to your cert
    'local_pk' => 'server.key', // path to your server private key
            'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production)
            'verify_peer' => FALSE 
], $loop);

$secure_websockets_server = new IoServer($app, $secure_websockets, $loop);
$secure_websockets_server->run();

In addition, I had to add these lines to my apache config file: SSLProxyEngine on ProxyPass /wss/ ws://127.0.0.1:8080/

and run this commands, in order to allow the ProxyPass sudo a2enmod proxy_http sudo a2enmod proxy_wstunnel sudo service apache2 restart

The javascript client then calls websocket with ws = new WebSocket("wss://LOCALIPADDRESS/wss/");

Cheers!

nausixkiz commented 2 years ago

Hi @m66g , Thank you for your solution. But as I know \React\EventLoop\Factory was be deprecated. Is it okay if we use it?

WyriHaximus commented 2 years ago

@nausixkiz Yes it's deprecated, but if you use \React\EventLoop\Loop::get() instead of \React\EventLoop\Factory::create() you're going to be fine for the future. If you continue to use \React\EventLoop\Factory::create() for the time being you're also going to be fine. It will only be an issue if you try to create more than one event loop with it.

nausixkiz commented 2 years ago

Hi everyone, I know it's old question but I really don't know why I can't connect via wss://mydomain.com:8888 in Javascript after deploy it to production

Here is my Nginx Config block

fastcgi_cache_path /home/mydomainuser/mydomain.com.com/cache levels=1:2 keys_zone=mydomain.com.com:300m max_size=2g inactive=60m;

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream socketserver{
    server 127.0.0.1:6868; 
}

server {
    listen 80;
    server_name www.mydomain.com.com mydomain.com.com ;
    include /home/mydomainuser/mydomain.com.com/public_html/*.conf;

    include /etc/nginx/site/mydomain.com.com/*.conf;
    include /etc/nginx/server/*.conf;
    return 301 https://mydomain.com.com$request_uri;
}

...

server {
    listen 8888 ssl http2;
    listen [::]:8888 http2 ssl;

    server_name mydomain.com.com ;
    charset utf-8;

    ssl_certificate /root/.acme.sh/mydomain.com.com/fullchain.cer;
    ssl_certificate_key /root/.acme.sh/mydomain.com.com/mydomain.com.com.key;

    root /home/mydomainuser/mydomain.com.com/public_html/public;
    index index.php index.html index.htm;

    include /etc/nginx/site/mydomain.com.com/*.conf;
    include /etc/nginx/server/*.conf;
    include /home/mydomainuser/mydomain.com.com/public_html/*.conf;

    location / {       
        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_pass_request_headers on;
        # prevents 502 bad gateway error
        proxy_buffers 8 32k;
        proxy_buffer_size 64k;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header X-Forwarded-Proto $scheme;
        reset_timedout_connection on;

        proxy_pass             http://socketserver;
        proxy_set_header Host  $host;
        proxy_read_timeout     86400;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        error_log /home/mydomainuser/mydomain.com.com/logs/wss_error.log;
        access_log /home/mydomainuser/mydomain.com.com/logs/wss_access.log;
    }

    error_log /home/mydomainuser/mydomain.com.com/logs/error.log;
}

It look seem be fine . I have opened all the ports above and made sure it's in LISTEN mode. I am configuring Ratchet with Laravel Console using port 6868. It works properly under local and ws . environment

Here is my code that init ws server

use App\Listeners\SocketEventListener;
use Illuminate\Support\Facades\Config;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Loop;

class SocketServer
{
    protected $server;

    public function start($port): void
    {
        $wsLoop = Loop::get();
        $wsSecure = new \React\Socket\SocketServer('127.0.0.1:' . $port, [
            'local_cert' => Config::get('socket.ssl.local_cert'),
            'local_pk' => Config::get('socket.ssl.local_pk'),
            'allow_self_signed' => Config::get('socket.ssl.allow_self_signed'),
            'verify_peer' => Config::get('socket.ssl.verify_peer')
        ], $wsLoop);

        $wsServer = new WsServer(
            new SocketEventListener(
                new SocketResponse(new LaravelEventPublisher())
            )
        );
        if (Config::get('socket.ssl.ssl_enabled')) {
            $this->server = new IoServer(new HttpServer($wsServer), $wsSecure, $wsLoop);
        } else {
            $this->server = IoServer::factory(
                new HttpServer($wsServer), $port
            );
        }

        $wsServer->enableKeepAlive($wsLoop, 30);
    }

    public function run(): void
    {
        $this->server->run();
    }

}

Can someone help me with this on Nginx? My sole purpose is to be able to connect to the production server as wss://mydomain.com:{port}

Thanks you for reading my issue

newmediacrew commented 1 year ago

This is what we use, to connect to the socket server without any nginx configuration;

        // create stuff
        $loop = Loop::get();
        $wsServer = new WsServer(new SocketApp());
        $wsServer->enableKeepAlive($loop, 5);
        $app = new HttpServer($wsServer);
        $secure_websockets = new \React\Socket\SocketServer('tls://0.0.0.0:9000), [
            'tls' => [
                'local_cert' => 'certfile',
                'local_pk' => 'keyfile',
                'allow_self_signed' => false,
                'verify_peer' => FALSE
            ]
        ], $loop);
        $secure_websockets_server = new IoServer($app, $secure_websockets, $loop);

        // run the server
        $secure_websockets_server->run();

You can create a new web socket connection wss://yourdomain:9000

m66g commented 1 year ago

@nausixkiz, @WyriHaximus Thank you for your comments on my posting. Here is my updated code:

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
// use React\EventLoop\Factory; // --> deprected
use React\EventLoop\Loop;
use React\Socket\SecureServer;

use Service\WebSocket\Chat;

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

CONST WEBSOCKET_SERVER_DEFAULT_PORT = '8080';

$app = new HttpServer(
   new WsServer(
      new Chat()
   )
);

$port = getenv('PHP_PORT_WEBSOCKET');
if (!$port) {
   $port = WEBSOCKET_SERVER_DEFAULT_PORT;
}

// $loop = Factory::create(); // --> deprecated
$loop = Loop::get();
$secure_websockets = new React\Socket\SocketServer('127.0.0.1:'.$port, [
      'local_cert' => '/etc/ssl/localcerts/apache-public-certificate.crt', // path to your cert
      'local_pk' => 'opt/ssl/localcerts/apache-private.key', // path to your server private key
                    'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production)
                    'verify_peer' => FALSE 
   ], $loop);

$secure_websockets_server = new IoServer($app, $secure_websockets, $loop);
$secure_websockets_server->run();

As said above, it is required to add these lines to my apache config file:

SSLProxyEngine on
ProxyPass /wss/ ws://127.0.0.1:8080/

and run these commands, in order to allow the ProxyPass

sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo service apache2 restart

The javascript client then calls websocket with ws = new WebSocket("wss://LOCALIPADDRESS/wss/");

Cheers!

GadoGadoEnjoyer commented 1 year ago

@m66g I tried your code but it doesn't work :( do I need to change 127.0.0.1 to my server ip? I also cant find the .crt file so I am using /etc/letsencrypt/live/www.domain.name/cert.pem and /etc/letsencrypt/live/www.domain.name/privkey.pem

Thanks.

m66g commented 1 year ago

@GadoGadoEnjoyer Hi, impossible to say without an error message. Of course, you need to create your own certificate, and its path depends on where you save it. Assumed that the server you connect to is localhost, stay with 127.0.0.1. Otherwise you need to change the ip address.

GadoGadoEnjoyer commented 1 year ago

@m66g My JS

var conn = new WebSocket("wss://WEBSITENAME/wss/");
conn.onopen = function(e) {
    console.log("Connection established!");
};

conn.onmessage = function(e) {
    console.log(e.data);
};

My Apache config

SSLProxyEngine on
ProxyPass /wss/ ws://WEBSITENAME:8080/

My Server.php

?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
use React\EventLoop\Loop;
use React\Socket\SecureServer;

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

    CONST WEBSOCKET_SERVER_DEFAULT_PORT = '8080';

    $app = new HttpServer(
       new WsServer(
          new Chat()
       )
    );

    $port = getenv('PHP_PORT_WEBSOCKET');
    if (!$port) {
       $port = WEBSOCKET_SERVER_DEFAULT_PORT;
    }

    $loop = Loop::get();
    $secure_websockets = new React\Socket\SocketServer('WEBSITE_IP:'.$port, [
          'local_cert' => '/etc/letsencrypt/live/WEBSITENAME/cert.pem', // path to your cert
          'local_pk' => '/etc/letsencrypt/live/WEBSITENAME/privkey.pem', // path to your server private key
                        'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production)
                        'verify_peer' => FALSE 
       ], $loop);

    $secure_websockets_server = new IoServer($app, $secure_websockets, $loop);
    $secure_websockets_server->run();
m66g commented 1 year ago

Hi, as I said, it's impossible to say something without error message. Moreover, I have hardly time these days, but maybe the community can help (provided you have a clear error description and message).

alyAds commented 9 months ago

@GadoGadoEnjoyer is the problem solved? I'm also looking into the problem

(Edited by @clue: Please take the time to write in English to avoid any misunderstandings)

GadoGadoEnjoyer commented 9 months ago

@GadoGadoEnjoyer is the problem solved? I'm also looking into the problem

Havent found any solution yet, I gave up

All-1 commented 5 months ago

@m66g Thank you so much. You can't imagine how much time I wasted before I found your solution. More than two weeks.