y-websocket icon indicating copy to clipboard operation
y-websocket copied to clipboard

Use wss:// protocol as an option for y-websocket

Open micrology opened this issue 3 years ago • 7 comments

Both for additional security and because if one is running a https:// server, it is essential, it would be good if y-websocket could provide websocket services using TLS as an option.

micrology avatar Jul 28 '20 21:07 micrology

Apologies - I had intended to assign this issue to myself, but it seems that this is not something I can do.

micrology avatar Jul 28 '20 21:07 micrology

NP, only I can do that :wink:

dmonad avatar Jul 28 '20 22:07 dmonad

Is there are real need for y-websocket to do the TLS stuff by itself? In real production, I'd expect everybody to run haproxy in front of y-websocket anyway so a good documentation to do that should be enough.

mikkorantalainen avatar Aug 07 '20 08:08 mikkorantalainen

I use nginx (with certbot doing the SSL configuration) in front of y-websocket and it works well.

canadaduane avatar Aug 11 '20 19:08 canadaduane

Yes, AFAIK, that would also be a good way of doing it - and I agree that documentation would be very helpful. I've added some hints for apache in the README for this branch - maybe you could add more relating to nginx?

micrology avatar Aug 12 '20 09:08 micrology

Here is my nginx proxy setup:

server {
        listen 80 ;
        # listen [::]:80 ipv6only=on;

        root /var/www/html;
        index index.php index.html index.htm;

        server_name y.relm.us;

        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_pass http://localhost:1235;

                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_connect_timeout 7d;
                proxy_send_timeout 7d;
                proxy_read_timeout 7d;

                client_max_body_size 10m;
        }

        error_page 413 @filetoobig;
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
                root /usr/share/nginx/html;
        }

        location @filetoobig {
                add_header Access-Control-Allow-Origin * always;
        }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/y.relm.us/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/y.relm.us/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

canadaduane avatar Aug 12 '20 15:08 canadaduane

Example config for Apache reverse-proxy doing TLS termination (if you use Ubuntu, you need to do sudo a2enmod proxy_wstunnel to enable websocket proxying because it's not enabled by default):

<VirtualHost _default_:443>
SSLEngine on
SSLCertificateChainFile /path/to/cert/chain.crt
SSLCertificateFile /path/to/cert/public.crt
SSLCertificateKeyFile /path/to/private.key
RewriteEngine On
RewriteRule ^/path/prefix/for/websocket/traffic(.*)$ ws://example.localdomain:1234$1 [P]
</VirtualHost>

If you want to use encrypted connection from reverse proxy to backend server, too, replace the ws:// above with wss://.

As an additional note, if you use HTTP Basic Auth, you'll find that Safari cannot access your websocket because of bug https://bugs.webkit.org/show_bug.cgi?id=80362

mikkorantalainen avatar Oct 06 '20 14:10 mikkorantalainen

well, for testing at home in one's local network between several PCs, being capable of using wss can come in quite handy - I had to do so today. If interested, look into my own fork of y-websocket

rozek avatar Apr 03 '23 14:04 rozek

@rozek I tried out your modifications to server.js, but couldn't get it to run. I simply can't connect to anything. This is what I'm seeing in the console:

WebSocket connection to 'wss://localhost:1234/6d17a764-980d-4f6f-b53d-e42491e5f067' failed

In my case no proxies are in use.

tim-hilt avatar Dec 29 '23 23:12 tim-hilt

well, since you are using localhost I assume that you did not prepare any certificate for your server.

I recommend installing "wscat":

npm install -g wscat
wscat -c "wss://localhost:1234/6d17a764-980d-4f6f-b53d-e42491e5f067"

to see what it reports.

If I am right, please, follow the instructions found in rozek/y-websocket to install proper certificates.

rozek avatar Dec 31 '23 23:12 rozek

I highly recommend running nodejs servers in production behind a proxy. nodejs is not good at handling connections directly. A proxy is also much better suited for handling certificates. If you use something like heroku, they will actually create a certificate for you using let's encrypt. Also, all proxies support let's encrypt using some kind of extension. The advantage is that you don't have to copy-paste certificates manually. Also, let's encrypt certificates are free. I you buy a certificate, you have to remember exchanging it every 1-2 years.

For local development, I've never seen a use-case where you need encryption. Of course, Chrome's Lighthouse will complain. But you should run Lighthouse on production anyway (which hopefully runs behind an encrypted proxy).

If you still want to add encryption to y-websocket directly, you can extend the server part of y-websocket quite easily. There is an example in yjs-demos where I add a static file server:

  • https://github.com/yjs/yjs-demos/blob/main/demo-server/demo-server.js

The default is quite plain and simple and does nothing but websocket:

  • https://github.com/yjs/y-websocket/blob/master/bin/server.js

You only need to adapt server.js and switch out require('http') with require('https'). Also, you have to generate and supply the certificates as described here:

  • https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener

I don't think I want to add this feature upstream though. I want to keep it minimalistic.

dmonad avatar Jan 15 '24 23:01 dmonad