Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ratchet + nginx + SSL/secure websocket

I've been trying to run Ratchet.io over SSL (this problem: php ratchet websocket SSL connect?).

My webserver is running at myhost.mobi, and I have created a separate virtual host for websocket service "wws.myhost.mobi".

My web socket:

$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            new Ratchet\Wamp\WampServer(
                $pusher
            )
        )
    ),
    $webSock
);

My nginx config (I'm on nginx 1.5.8):

upstream websocketserver {
        server localhost:8080;
}

server {
    server_name wss.myapp.mobi;

    listen 443;
    ssl on;
    ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
    ssl_certificate_key /etc/ssl/myapp-mobi.key;

    access_log /var/log/wss-access-ssl.log;
    error_log /var/log/wss-error-ssl.log;
    location / {
                proxy_pass http://websocketserver;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto https;
                proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
                proxy_redirect off;
        }
}

My client-side script:

var conn = new ab.Session('wss://wss.myapp.mobi', function(o) {

    // ...

}, function() {
    console.warn('WebSocket connection closed');
}, {
    skipSubprotocolCheck: true
});

So, when I load the page in Firefox, I see an outgoing connection to wss://wss.myapp.mobi:8080/, which is hanging (the spinner) and never completes or dies. I do not see any trace of request arriving on the backend in the logs.

What am I missing there?

Thanks!

EDIT I have realized that I should be connecting to wss://wss.myapp.mobi, but now I am getting "101 Switching Protocols" status.

EDIT 2 Everything is working now with the config above. "101 Switching Protocols" status turns out to be a normal message. PROBLEM SOLVED!

like image 976
temuri Avatar asked Mar 19 '14 00:03

temuri


People also ask

How do I use nginx with Ratchet?

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.

How does Nginx work as a WebSocket proxy?

Here is a live example to show NGINX working as a WebSocket proxy. This example uses ws, a WebSocket implementation built on Node.js. NGINX acts as a reverse proxy for a simple WebSocket application utilizing ws and Node.js.

Is there a way to enable SSL in Ratchet?

The problem is that React (which Ratchet is built on) does not support direct SSL connections. See this issue. There is a simple workaround. Use stunnel with a config like: Stunnel will handle SSL traffic on port 8443 and port them to your websocket server. Show activity on this post. The best solution would be to use Nginx as your web server.

How do I add SSL to a WebSocket server?

Use stunnel with a config like: Stunnel will handle SSL traffic on port 8443 and port them to your websocket server. Show activity on this post. 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.


1 Answers

By checking question edit history, it is clear that, the configuration in the question was correct, temuri was trying to connect from client with port set in,

upstream websocketserver {
        server localhost:8080;
}

but this code block tells Nginx there is a tcp server running on port 8080, represents it as websocketserver alias, but the running server is not accessible to public.

Check the below configuration,

server {
    server_name wss.myapp.mobi;

    listen 443;
    ssl on;
    ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
    ssl_certificate_key /etc/ssl/myapp-mobi.key;

    access_log /var/log/wss-access-ssl.log;
    error_log /var/log/wss-error-ssl.log;
    location / {
                proxy_pass http://websocketserver;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto https;
                proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
                proxy_redirect off;
        }
}

this configuration binds the domain wss.myapp.mobi to port 443 enabling ssl and proxying the requests to the local websocket server via proxy_pass directive, rest directives are for connection upgrades handling.

So the websocket server can be accessed from browser client with

// connect through binded domain
// instead of wss.myapp.mobi:8080 which will not work
var url = 'wss://wss.myapp.mobi';
like image 62
Renjith Thankachan Avatar answered Oct 29 '22 13:10

Renjith Thankachan