kpreid / shinysdr

Software-defined radio receiver application built on GNU Radio with a web-based UI and plugins. In development, usable but incomplete. Compatible with RTL-SDR.
https://shinysdr.switchb.org/
GNU General Public License v3.0
1.07k stars 115 forks source link

Build in reverse proxy or other solution for not requiring two ports #142

Open kpreid opened 4 years ago

kpreid commented 4 years ago

The requirement to configure two server ports is occasionally problematic. It would be nice if we could eliminate it. Options:

  1. Migrate WebSocket server code from txWS to Autobahn, another Twisted library which integrates WebSockets and HTTP instead of requiring separate transports. I made some attempt at doing this in https://github.com/kpreid/shinysdr-morgue/tree/autobahn but was stymied by various cases of unhandled errors being silently discarded as I attempted to migrate the code.

  2. Launch a reverse proxy as a subprocess, configuring it to talk to autoassigned local ports, so that the user only needs to specify the single port they want. (Supporting reverse proxies at all was issue #92.)

This issue will probably be about the second option.

fmoessbauer commented 4 years ago

I had success running ShinySDR behind a nginx reverse proxy using just one port for exposing both the HTTP and the websocket endpoint. The trick is to use a path-rewrite to dispatch the requests:

Assuming HTTP runs on 8100, websocket on 8101:

shinysdr:

    http_endpoint='tcp:8100',
    ws_endpoint='tcp:8101',

    http_base_url='https://fqdn.org/',
    ws_base_url='wss://fqdn.org/ws/',

nginx site:

location ~ ^/ws/(.*) {
                proxy_pass_request_headers on;
                proxy_pass http://127.0.0.1:8101/$1$is_args$args;
                proxy_http_version 1.1;

                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 $scheme;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";

                proxy_cache_bypass $http_upgrade;
                proxy_buffering off;
                proxy_ignore_client_abort off;
                break;
        }

        location / {
                proxy_pass http://127.0.0.1:8100;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                break;
        }

This setup can further be used to add SSL, but there careful tuning is necessary to achive low latency:

listen 443 ssl http2; # important: use http2
ssl_session_cache shared:SSL:1m; # holds approx 4000 sessions
ssl_session_timeout 1h; # 1 hour during which sessions can be re-used
ssl_session_tickets on;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
gzip off; # when using http, we should disable gzip (already compressed)

The only issue is that when using SSL I regularly run into issue #125 during startup of the web-gui in Chrome. However, when the startup is successful, everything runs smooth. In Firefox, this issue does not appear.

kpreid commented 4 years ago

Thanks for the info!

May I have your permission to incorporate that nginx configuration as a template into ShinySDR under ShinySDR's GPL license? (I'm asking explicitly because it's not in the form of a pull request and I'm not sure whether that counts for the automatic licensing in GitHub's TOS.)

fmoessbauer commented 4 years ago

Hi @kpreid, yes you can freely use this configuration. If it helps, I can also create a pull request but I'm fine if you just include that.