Search code examples
phpapachewebsocketratchet

websockets connections fail with apache and Ratchet


I wrote a php websockets server using the library Ratchet that I call with javascript using the websocket object.

Everything worked perfectly locally but it was impossible to run my project on my Debian server under apache.

To enable websocket connections I read that I have to use mod_proxy_wstunnel module. So I rewrite my apache conf for my subdomain api.domain.com like this:

<VirtualHost *:80>
        ServerAdmin [email protected]
        DocumentRoot /var/www/api.domain.com
        ServerName api.domain.com

        # Enable Websocket connections on port 8888
        ProxyPass "/wss/homews/" "ws://api.domain.com:8888/"

        <Directory /var/www/api.domain.com>
                Options FollowSymLinks
                AllowOverride All
                Order allow,deny
                Allow from all
                Satisfy all
        </Directory>
</VirtualHost>

Then I call my php script with this code insight that start Ratchet websocket server:

// ...
// Some code ...
$app = new Ratchet\App('localhost', 8888);
$app->route('/wss/homews/', $myClass, array('*'));
$app->run();

Then when I try to connect to it on the javascript client side with the url ws://api.domain.com:8888/wss/homews/ I always get Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT.

Do you have any ideas how I could debug this type of error ? Are there any logs on apache showing a bad configuration?


Solution

  • Your above configuration has to be changed at least to:

    <VirtualHost *:80>
            ServerAdmin [email protected]
            DocumentRoot /var/www/api.domain.com
            ServerName api.domain.com
    
            # Enable Websocket connections on port 8888
            ProxyPass "/wss/homews/" "ws://localhost:8888/wss/homews/"
    
            <Directory /var/www/api.domain.com>
                    Options FollowSymLinks
                    AllowOverride All
                    Order allow,deny
                    Allow from all
                    Satisfy all
            </Directory>
    </VirtualHost>
    

    And on the javascript client side to the url ws://api.domain.com:80/wss/homews/.

    Otherwise probably (or lets say hopefully for a server setup) the target from webserver config api.domain.com:8888 tries to reach upstream the websocket on public IP of the server while websocket is bound to localhost. Eighther it's just not listening there (what is fine as You nromally only want to expose Your webservers ports to the public and not directly Your app ports) or even worse it tries to reach a public NAT IP which involves a trip to a firewall where the port 8888 should be blocked, which may not allow this stuff, can be expensive (eg. AWS EC2) and ist at very least inperformant.

    On the other hand You will want to direct the client code to the webserver on port 80 which does the tunnelling to Your websocket app so Your client cannot directly access port 8888 of Your server (it's blocked in the public firewall hopefully - and You are listening on localhost only).

    Try with Your original setup and tell how the results changed, maybe there is an additional issue (but You should not get a socket timeout anymore at least and a connection from client to websocket app).