yjs / y-websocket

Websocket Connector for Yjs
https://docs.yjs.dev/ecosystem/connection-provider/y-websocket
MIT License
524 stars 262 forks source link

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

Closed micrology closed 9 months ago

micrology commented 4 years ago

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.

Huly®: YJS-561

micrology commented 4 years ago

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

dmonad commented 4 years ago

NP, only I can do that :wink:

mikkorantalainen commented 4 years ago

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.

canadaduane commented 4 years ago

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

micrology commented 4 years ago

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?

canadaduane commented 4 years ago

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
}
mikkorantalainen commented 4 years ago

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

rozek commented 1 year ago

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

tim-hilt commented 10 months ago

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

rozek commented 10 months ago

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.

dmonad commented 9 months ago

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:

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

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:

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