3

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 admin@admin.admin
        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?

johannchopin
  • 13,720
  • 10
  • 55
  • 101
  • first check the server is listening on port 8888 and that you can telnet to it from the client server, eg telnet api.domain.com 8888 – Darren Smith Oct 14 '19 at 22:01
  • `ERR_CONNECTION_TIMED_OUT` usually points to a firewall or host resolver error. Can you change `new Ratchet\App('localhost', 8888);` to be `new Ratchet\App('api.domain.com', 8888);`? Also, can you check your firewall with `iptables -L -n` and make sure port 8888 is opened – Raul Oct 14 '19 at 22:02
  • @Raul Ok first error is that the port is not open :sad:. I open it and try again – johannchopin Oct 14 '19 at 22:16
  • @Raul Its done adding `Listen 8888` to `ports.conf` but now Ratchtet can't no more listen to it since apache uses this port -> `Failed to listen on "tcp://127.0.0.1:8888"` – johannchopin Oct 14 '19 at 22:26
  • Ok, so obviously, you can't have both on the same IP and port. So, if both are on the same server, change the webserver to be on 8888 and the websocket server to 8889 for example. – Raul Oct 14 '19 at 22:30
  • @Raul Ok but then I'm going to be in the same situation as before where I have a port that is not listen by apache but used by Ratchet – johannchopin Oct 14 '19 at 22:38
  • I hope i'm not mistaken here, but the Ratchet app runs by running it in CLI, no? like `php bin/something.php`? That has nothing to do with the apache port where your requests are coming in. My apologies if I'm misunderstanding your setup – Raul Oct 14 '19 at 22:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200871/discussion-between-johannchopin-and-raul). – johannchopin Oct 14 '19 at 22:42

2 Answers2

2

Your above configuration has to be changed at least to:

<VirtualHost *:80>
        ServerAdmin admin@admin.admin
        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).

EOhm
  • 626
  • 4
  • 11
  • I made the modifications and now my websocket is able to connect to my server but it return me an `404` error. – johannchopin Nov 03 '19 at 10:09
  • I don't know Your app. Possibly it is expecting that You write something after the `ws://localhost:8888/wss/homews/`? Can You see the response is coming from Your app (look for something in the headers that point to that or try same request when backend app is not running). What is Your httpd log now showing? Did You enable the necessary proxy modules in webserver config or did You check that they are they enabled? – EOhm Nov 03 '19 at 10:25
  • Ok it's work great it was an error from my code so now I'm able to connect to my server with websocket. Thanks a lot – johannchopin Nov 03 '19 at 10:31
1

First and foremost, try to simplify things, DO NOT edit or touch any of the configuration files from the server, leave it by default as it is, that will do

I will post all the precautions steps needed in order make the socket up and running, please follow steps one by one, they are as follows:

  1. Check whether your server supports Web Socket on shared hosting, otherwise you may need to go for Dedicated hosting service or Virtual private server(VPS) Eg: AWS, GCP. If your server supports running a web service scripts like phpwebsocket within a web service, then follow next steps

  2. On the terminal, Update the composer to the latest one, then try to execute $composer require cboden/ratchet So that the required dependency will load efficiently and do not try to upload any archived dependencies. In my case, "cboden/ratchet": "^0.4.3" was loaded on localhost, But on production site it was "cboden/ratchet": "^0.4.1" when compared both from the composer.json file

  3. Try to connect to port 8282, In most cases, the server traffic, both from the inbound & outbound are kept open by default, in case, if the port 8080, could not bind to the TCP

  4. At Last, Try to reboot your cloud hosted server instance and execute the websocket script $php <yourWebSocketScript.php>

I had used mod_proxy_wstunnel to make sure the communications goes encrypted, apart from it, I was able to up & run the Websocket socketo.me on AWS and our private dedicated server smoothly

Thanks for contacting, I do appreciate your efforts, apart from your concerned comment to reply via johannchopin@protonmaildotcom, this is not my part of the business ethics


Edit

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

Try changing the manually assigned localhost from your <yourWebSocketScript.php> from the above snippet to

$app = IoServer::factory(
    new HttpServer(new WsServer(new Chat())),
    8282
);
$app->run();

Try binding to the HttpServer, it defaults to localhost or 0.0.0.0 and run (if necessary, eliminate $app->route())

On your code you need to modify

  1. Port Number in yourWebSocketScript.php

  2. Change from localhost to the Server IP or DNS in someChatFilexyz.php

    Eg:
    let websocket_server = new WebSocket("ws://my.domain.com:8282");
    or
    let websocket_server = new WebSocket("ws://xxx.xxx.xxx.xxx:8282");
  1. Kill all the previous established socket specific to port 8282 and then run yourWebSocketScript.php

Here is the partial code of someChatFilexyz.php

jQuery(function($){
// Websocket_Controller
var websocket_server = new WebSocket("ws://xxx.xxx.xxx.xxx:8282");
websocket_server.onopen = function(e) {
websocket_server.send(
...
);
};

websocket_server.onerror = function(e) {
// Errorhandling
...
}

websocket_server.onmessage = function(e) {

...
}
}

Setting up the above config, I was able to run on an Amazon Web Service with LAMP stack configured by me and with private dedicated server with ease.

Note: Any minor changes in the code, you need to restart the running websocket script $php <yourWebSocketScript.php> i.e., either by terminating the running process or killing the process specific to port number assigned

Nɪsʜᴀɴᴛʜ ॐ
  • 2,756
  • 4
  • 33
  • 57
  • Thanks you a lot for your response. For the first step I have a VPS under Debian. Then on localhost and on my server I have the same Ratchet version but it's the `^0.4.1` (I don't think it's the problem but I'm just pointing out). For the third step I'm a little bit confusing. Nothing is listenning on port `8282` so I get nothing when I ping it `ping api.domain.com:8282`. Do I have to open this port for websockets ? – johannchopin Nov 02 '19 at 14:21
  • How do you ping taking port number, disable the firewall completely test it via JavaScript console and later you can enable it. Both outbound and inbound must be considered – Nɪsʜᴀɴᴛʜ ॐ Nov 02 '19 at 16:53
  • From JS console execute `let conn = new WebSocket('ws://xxx.xxx.xxx.xxx:8282'); conn.onopen = function(e) { console.log("Connection established!"); };` where x denotes server IP. See towards in the console what does it display. – Nɪsʜᴀɴᴛʜ ॐ Nov 02 '19 at 17:07
  • And also Web Service doesn't depend upon whether you are hosting it in a sub domain or with different sub directory. It will be made globally available specific to your DNS or IP. In order to receive you need to specify connecting port number to the established socket @johannchopin – Nɪsʜᴀɴᴛʜ ॐ Nov 02 '19 at 17:23
  • Sadly I have no response on port 8282 :sad: I got as error the famous `net::ERR_CONNECTION_TIMED_OUT` – johannchopin Nov 02 '19 at 17:36
  • Had you disabled the firewall and changed port no from `yourWebSocketScript.php` file and rebooted your server and ran the command on the terminal as `$php ` and tested it in JS Console There are several test you can try it out to test whether the port 8282 is open or not from the UI or from the terminal prompt @johannchopin – Nɪsʜᴀɴᴛʜ ॐ Nov 02 '19 at 17:53
  • I actually have no firewall and yes Ratchet is normally running on port 8282 but nothing changed has before :( – johannchopin Nov 02 '19 at 18:06
  • Without knowing the root cause, I cannot grind it with axe. Look for latest server logs generated at this movement and you need to test the JS console in non-https domain and Ngnix acts as reverse proxy nothing to do with. Main communications are done from the Apache server check both the logs and do not make an attempt to override the default configuration files with overloaded data. This is the least minimum config that you should have to make the websocket up & run – Nɪsʜᴀɴᴛʜ ॐ Nov 02 '19 at 18:23
  • I have no error on my apache logs :( I only use apache on my server I don't have nginx and according to [this post](https://stackoverflow.com/a/24042195/8583669) I have to enable some configuration to it is that true ?4 – johannchopin Nov 02 '19 at 18:34
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/201776/discussion-between-ns--and-johannchopin). – Nɪsʜᴀɴᴛʜ ॐ Nov 03 '19 at 04:47