Secure websockets with stunnel and Ratchet. Connection is closed - php

I have a working websockets solution with Ratchet and ZeroMQ as documented in their push integration documentation. The problem I have is the production application is served through SSL and unsecured websockets don't work in Firefox when requested through secure websites. The issue is well known, and two suggestions are to use stunnel, or go with nginx for web server. I can't use nginx so my only option is stunnel, but clients can't connect.
Here's my stunnel configuration:
client = no
chroot = /var/lib/stunnel/
setuid = stunnel
setgid = nogroup
pid = /var/run/stunnel.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
cert = /etc/apache2/server.info.crt
key = /etc/apache2/server.info.key
[websocket]
accept = 8079
connect = 8080
Ratchet is configured to listen in 8080:
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, "0.0.0.0"); // Binding to 0.0.0.0 means remotes can connect
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
And client are trying to connect through wss://server.ip:8079 however no client can connect, as soon as the request is made, they are disconnected.
Any ideas?

I'm going through stunnel while using Ratchet for encryption too. My entire stunnel.conf looks like this. Using the same pem as my apache httpd server.
cert = /etc/apache2/ssl/cert.pem
[websocket]
accept = YOUR_PUBLIC_IP_ADDRESS:8079
connect = 127.0.0.1:8080
You may be missing the IP address before the ports. I combine the key and cert into a pem but using both should work.

I encountered the same problem in Mac OS, but just solved it by adding the certificate to the keychain access, so that the browsers (Chrome and Safari) will acknowledge the certificate and the connection will establish.

Related

how to make client connect to ratchet on live server?

I've googled about this for so many days and till now the client (browsers) cannot connect to the server.
But the server can run. I think its because its connected to itself(localhost).
I did find ratchet documentation which says:
If you want to open Ratchet up (not behind a proxy) set the third
parameter of App to '0.0.0.0'.
http://socketo.me/docs/troubleshooting
so i tried this in my server.php file. (doesn't work)
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8180,
'0.0.0.0'
);
Next i tried changing the app.php file which located here(doesn't work):
/vendor/cboden/ratchet/src/Ratchet/App.php
public function __construct($httpHost = '0.0.0.0', $port = 8180, $address = '0.0.0.0', LoopInterface $loop = null) {......
Then,i tried changing the port to something else. again the server can run but the client cannot connect.
I referred all these:
How to run Ratchet remotely or on a server?
How to run Ratchet remotely or on a server?
https://github.com/ratchetphp/Ratchet/issues/394
Someone please help. All I want is for the client to be able to connect to the ratchet websocket which is running on the server.

Ratchet Websocket for raspberry pi

I have written a websocket using ratchet. The webserver is nginx and lives on a raspberry pi. The raspberry pi has been connected to the internet with a router through port forwarding. When I access the site at work, all works well. The websocket connects, all the webpages launch. When I try to access the webpage outside of work the webpage works except the websocket. The worst part is I can't even debug it because I need to be outside the local network for the websocket to fail (i.e not at work). At work, I can connect to the server using two IP addresses, the private IP address that is only accessible locally and the public IP address that can be accessed from anywhere. Both IP addresses properly launch the websocket. When I am not at work, I can only access the webserver on the Public IP address and the websocket does not work.
I have been trying to make this work for a day and a half straight now with no success. Does anybody have any suggestions? Even to help me identify the problem?
The websocket code follows the Ratchet Push Server tutorial:
<?php
require '/var/www/html/vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$pusher = new MyApp\Pusher;
$context = new React\ZMQ\Context($loop);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message',array($pusher, 'onBlogEntry'));
$webSock = new React\Socket\Server($loop);
$webSock->listen(443, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\Websocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
$loop->run();
?>
The client side code is:
var conn = new ab.Session('ws://privateIPAddress:443',
function (){
console.log("Here");
conn.subscribe('client',function(topic,data) {
console.log("hey");
...
});
},
function() {
console.warn('Websocket connection closed');
},
{'skipSubprotocolCheck': true}
);
I suspect the issue is a security setting since both the public and private IP addresses work when I am at the work site.
This is a very late answer to my own question but in case anyone is still puzzling over the same issues. The answer is don’t use ratchet. Use nodejs with socket.io. All your troubles will fly away. Socket.io which also has a java implementation is simply a more developed package for WebSockets.

PHP Ratchet can't connect from other device

I'm starting using PhP Ratchet socket. Following the guides I could made a simple chat application and it's working within the same computer. Example, if I open up chrome and firefox, I can interact send and receive messages, ok.
The problem is when I try to use the chat app from another computer, but within the same internet connection, or even when I tried to test it online.
When on lan, the other computers can't connect with the socket and online no one can connect.
By looking around, I found about using '0.0.0.0' or even port 5555 to enable connections from anyone. But even when using this, I can't connect.
How can I solve this? This is my files:
server.php
<?php
use Ratchet\Server\IoServer;
use Ratchet\http\HttpServer;
use Ratchet\WebSocket\WsServer;
require __DIR__ . '/../vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
), 2000, '0.0.0.0'
);
$server->run();
?>
And client js file:
var socket = new WebSocket('ws://127.0.0.1:2000');
127.0.0.1 will always point to the local device, which, on devices other than the socket server, will not point to the device that is hosting the socket server. If the device that is running the socket server is not routeable from the internet, you will not be able to connect to the socket from the internet.
You can test from other devices on your LAN by figuring out what your network IP is for the device that is running the server. Then in your client code, connect to that IP. It will probably be something close to 192.168.x.x, e.g. 192.168.1.12 (it could also be in the 10.x.x.x or 172.16.x.x address spaces). Then simply use that address to connect from your client script for testing:
var socket = new WebSocket('ws://192.168.1.12:2000');
You may still run into trouble if, for whatever reason, your network is configured to drop packets on port 2000. If so, it should be fairly easy for you to change to a different port for both your server and client.

php websocket redirect with stunnel

I built a php websocket server javascript clients to connect to it. It's working fine without SSL. My next Step is to improve security with using wss instead of ws (an so enabling https on the website).
My intention is to decrypt incoming traffic and redirect it to the websocketserver using stunnel on CentOS 6.
The first step is to simply redirect the requests from the clients to the server:
client-request: ws://soundjack.eu:9030/wsServer2.php
server: socket created listening on 144.76.81.210:9090 running php -q wsServer2.php
coresponding stunnel config:
; Some security enhancements for UNIX systems - comment them out on Win32
chroot = /var/run/stunnel/
;setuid = nobody
;setgid = nobody
; PID is created inside the chroot jail
pid = /stunnel.pid
; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
;compression = zlib
; Some debugging stuff useful for troubleshooting
debug = 7
output = /var/log/stunnel/stunnel.log
; Use it for client mode
client = yes
; Service-level configuration
[wsServer]
accept = 127.0.0.1:9030
connect = 127.0.0.1:9090
stunnel starts correct and is listening to port 9030.
Every request that is sendet by a client gehts abortet (checked firebug console). On Chrome it says status: finished, without any further information.
I quite don't know what the error is, so any help would be great. Thanks!
It finaly works!!! Even with SSL it works great.
The clue was to chance the config of stunnel to work correct (Update using SSL now):
/etc/stunnel/stunnel.conf:
; Certificate/key is needed in server mode and optional in client mode
cert = /path/to/<myCert>.pem
key = /path/to/<myKey>.key
; Protocol version (all, SSLv2, SSLv3, TLSv1)
sslVersion = all
; Some security enhancements for UNIX systems - comment them out on Win32
chroot = /var/run/stunnel/
; PID is created inside the chroot jail
pid = /stunnel.pid
; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
;compression = zlib
; Some debugging stuff useful for troubleshooting
debug = 7
output = /var/log/stunnel/stunnel.log
;foreground = yes
; Use it for client mode
;client = yes !! turn to server mode
; Service-level configuration
[wsServer]
accept = 0.0.0.0:9030 !! listen to all addresses
connect = 127.0.0.1:9090
Note: marks with !! are no valid comments! I inserted them only to show the changes.
I just ran into this same problem and I wanted to add to this answer for someone else googling around because it was killing me. In my php I wrote a websocket using ratchet that I was invoking with a laravel artisan command. If you're developing locally, I believe you can add the stunnel.pem and CAFile to your keychain (if on a mac... on second thought I don't even think you necessarily need the CAFile if working locally) and you should be able to access your websocket with stunnel over wss. However, if you are working on your live webserver you need to get your keys certified. In my case I generated my stunnel keys for the stunnel.pem using openSSL and got them certified using positive SSL. I then added the CAFile option and linked the crt file they sent me back. If you are getting "stunnel vision", use the option foreground =yes in your stunnel.conf and remember as DrakeBlack pointed out DO NOT USE client = yes. You are not the client in this case you are the server.

Send request to 127.0.0.1 via HTTP which is forwarded on via HTTPS

I am using WampServer (Windows) and PHP pgsql, and apparently something wasn't compiled with SSL support, because I get this error:
Unable to connect to PostgreSQL server: sslmode value "require" invalid when SSL support is not compiled
This got me thinking... I wonder if I can ask pg_connect() to look for 127.0.0.1 on port 12345 (or something like that) using HTTP, and then some middle service could be run on my local system that would pass that on to the server using SSL.
Does anyone know how to do that?
NOTE
I'm trying to connect to the Heroku PostgreSQL server (which uses an Amazon Web Service URL) and requires an SSL connection. I had better luck Googling "amazonws.com postgresql stunnel" for relevant bulletin board messages.
UPDATE
Here is the stunnel.conf file that I used:
;See: https://medium.com/what-i-learned-building/580fdd492119
cert = stunnel.pem
options = NO_SSLv2
options = SINGLE_ECDH_USE
options = SINGLE_DH_USE
socket = r:TCP_NODELAY=1
options = NO_SSLv3
ciphers = HIGH:!ADH:!AECDH:!LOW:!EXP:!MD5:!3DES:!SRP:!PSK:#STRENGTH
[heroku-postgres]
client=yes
accept = 127.0.0.1:YOUR-CHOSEN-PORT
connect = THE-HOST-GOES-HERE:PORT
protocol=pgsql
retry = yes
Reference: https://medium.com/what-i-learned-building/580fdd492119
postgresql does neither use http nor https for its connection, but has its own protocol. But you could use something like stunnel to tunnel a normal tcp connection inside ssl, e.g. if your local pg_client library is not ssl-aware you could create an stunnel on localhost which then forwards the data via ssl to the remote postgresql server.

Categories