K3NN3TH
K3NN3TH

Reputation: 1496

Ratchet Websocket Apache2 SSL unable to make connection to PHP websocket

Been researching the issue with Ratchet over SSL and have been trying to get my Apache2 server configuration working by enabling proxy.load and proxy_wstunnel.load mods.

/etc/apache2/mods-enabled:
     proxy.conf -> ../mods-available/proxy.conf
     proxy.load -> ../mods-available/proxy.load
     proxy_wstunnel.load -> ../mods-available/proxy_wstunnel.load

I've added the following line to the end of my apache2.conf:

ProxyPass /wss2/ ws://domain.com:8080

The PHP socket-server.php file:

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Websocket\SocketControl;
use Ratchet\Session\SessionProvider;
use Symfony\Component\HttpFoundation\Session\Storage\Handler;

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

    $memcache = new Memcache;
    $memcache->connect('localhost', 11211);

    $session = new SessionProvider(
        new SocketControl,
        new Handler\MemcacheSessionHandler($memcache)
    );

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

    $server->run();

The relevant JS code that attempts to connect to the socket server:

var websocket = {
    wsUri:"wss://domain.com/wss2/NNN",
    socket:null,
    cryptKey:null,
    init:function(){
        try {
            if (typeof MozWebSocket == "function")
                WebSocket = MozWebSocket;
            if ( websocket.socket && websocket.socket.readyState == 1 )
                websocket.socket.close();

            websocket.socket = new WebSocket( websocket.wsUri );
            websocket.socket.onopen = websocket.onopen.bind();
            websocket.socket.onclose = websocket.onclose.bind();
            websocket.socket.onmessage = websocket.onmessage.bind();
            websocket.socket.onerror = websocket.onerror.bind();

        } catch (exception) {
            console.log("ERROR: " + exception);
        }
    },

The error I receive when attempting to connect:

WebSocket connection to 'wss://domain.com/wss2/NNN' failed: Error during WebSocket handshake: Unexpected response code: 502

Upvotes: 0

Views: 1897

Answers (3)

Ido
Ido

Reputation: 21

I had been looking for a secure websocket application myself as well... Perhaps a cleaner setup. No need to proxy. Here's what I figured out:

<?php

require __DIR__ . '/vendor/autoload.php';

// SSL configuration
$context = array(
    'tls' => array(
        'local_cert' => "-path-to-ssl-certificate.crt",
        'local_pk' => "-path-to-ssl-privatekeyfile.key",
        'allow_self_signed' => true, // Set to false in production
        'verify_peer' => false
    )
);

// Set up websocket server
$loop = React\EventLoop\Factory::create();
$application = new Ratchet\App('your.domain.com', 8443, 'tls://0.0.0.0', $loop, $context);

// Set up controller component (instance of MessageComponentInterface or WsMessageComponentInterface)
$controller = new MyControllerObject();
$application->route('/any_desired_path', $controller, array('*'));

$application->run();
die('-server stopped-');

Now you can set up your client secure websocket connection, and get your application running!

var conn = new WebSocket('wss:your.domain.com:8443/any_desired_path');

Note: the SSL setup can be hard, as no error messages appear e.g. when the crt or key file are missing, or the allow_self_signed/verify_peer values are non-boolean. The client simply closes the connection, or is unable to connect.

Upvotes: 1

Hussein Taha
Hussein Taha

Reputation: 11

I guess i am late posting this one, but I have here a working example with routing also. the code is working well as per the latest ratchet version.

<?php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
require __DIR__ . '/vendor/autoload.php';

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Psr\Http\Message\RequestInterface;
use Ratchet\Http\Router;
use Ratchet\Http\HttpServerInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\HttpFoundation\Request;

$routes = new RouteCollection;
$loop = React\EventLoop\Factory::create();

$decorated = new WsServer(new ChatRoom);
$decorated->enableKeepAlive($loop);
$routes->add('chat-room', new Route('/chat-room', array('_controller' => $decorated), array('Origin' => $GLOBALS['Address']), 
    array(), $GLOBALS['Address'], array(), array('GET')));

$decorated = new WsServer(new SingleChat);
$decorated->enableKeepAlive($loop);
$routes->add('single-chat', new Route('/single-chat', array('_controller' => $decorated), array('Origin' => $GLOBALS['Address']), 
    array(), $GLOBALS['Address'], array(), array('GET')));

$decorated = new WsServer(new Ratchet\Server\EchoServer);
$decorated->enableKeepAlive($loop);
$routes->add('echo', new Route('/echo', array('_controller' => $decorated), array('Origin' => $GLOBALS['Address']), 
    array(), $GLOBALS['Address'], array(), array('GET')));


$app = new HttpServer(new Router(new UrlMatcher($routes, new RequestContext)));

$secure_websockets = new \React\Socket\Server('0.0.0.0:8091', $loop);
$secure_websockets = new \React\Socket\SecureServer($secure_websockets, $loop, [
    'local_cert' => 'path/to/certificate.crt',
    'local_pk' => '/path/to/your-key.key',
    'verify_peer' => false
]);

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

Regards

Upvotes: 1

mitchken
mitchken

Reputation: 800

The problem is in the URL you are using:

wsUri:"wss://domain.com/wss2/NNN",

you could try:

wsUri:"wss://domain.com/wss2",

since you link to that URL in your config

Upvotes: 0

Related Questions