mregni / EmbyStat

Multiplatform statistics server for Emby server
MIT License
286 stars 21 forks source link

Possible to add setting to change port from 0: to loopback to avoid exposing EmbyStat on LAN? #1265

Closed solarchemist closed 4 years ago

solarchemist commented 4 years ago

Now that I have EmbyStat up and running, and I can see that there's no built-in authentication for the webapp, I would like to put it behind a reverse proxy that uses Apache basic auth (or something like that) like many of my other webapps.

My issue is that even with such a proxy in place, EmbyStat will remain open and accessible without authentication as long as it's accessed from inside my LAN due to its port binding to the ::0 interface (equivalent to ipv4 0.0.0.0).

Would it be possible to add a setting to allow changing the port binding to the loopback interface instead?

I have looked through all the *.config and *.json files in the EmbyStat archive and found no such setting.

mregni commented 4 years ago

At the moment I'm implementing authentication and I will release that soon. I did a full rework of the UI so some part (shows for example) will not be included in this release yet. I hope I can release it in a couple of days. Then you will have authentication with JWT tokens.

Would that fix your problem? I'm not sure what you mean with "changing the port binding to the loopback interface"

solarchemist commented 4 years ago

Adding built-in authentication sounds great, just please make it possible to disable it too.

My point is that for webapps that aren't multi-user, such as EmbyStat, Sonarr, and many others, it can be quite useful to disable any built-in auth, and place each service behind a reverse proxy that takes care of auth using a single-sign on (SSO) solution, such as Auth0 (which I use today) or Portier (which I'd like to switch to eventually).

With such a reverse proxy in place, the careful sysadmin will of course want to stop anyone from bypassing the authentication page of the reverse proxy. To achieve that, we must either make the webapp listen only to the localhost address, or else fiddle with firewall rules. The former is much easier to do and preferable, I think.

Since you asked, allow me to clarify with a short example of two common services: mysql and ssh. The default port of a mysql server is 3306, and should always be set to listen only to the localhost address. In contrast, the ssh server at port 22 listens on all addresses, because it is meant to be accessible from other machines. It may look like this (the ~third~ fourth column is the interesting one):

$ netstat -plnt
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1958/sshd           
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      1583/mysqld 

In short, if netstat shows that the webapp listens on 0.0.0.0:6555, that means it's listening on all interfaces/addresses (or the equivalent for ipv6, see my link in previous post), but if it listens only on loopback/localhost it would show as 127.0.0.1:6555 (or the equivalent for ipv6).

For a reverse proxy with authentication to make sense, we want to make sure the webapp is set to listen only on the loopback address. Otherwise, it would be trivial to get around said auth page (inside the LAN) by simply using http://<IP-of-host>:<port> as the URL.

Hope that explanation makes sense, and that it wasn't too verbose :-)

Right now, EmbyStat is listening on port 6555 on all addresses (the equivalent of 0.0.0.0 but using ipv6). Can we make a setting/toggle to allow switching EmbyStat to listen only on the localhost address? I think it would make EmbyStat a very flexible project, that could accomodate many different setups.

As for auth using JWT tokens, I must admit I'm not familiar with those. If you implement it, perhaps you could give a few pointers on how to use them in the docs ;-)

mregni commented 4 years ago

Thanks for the well-formed and clear explanation! I started creating EmbyStat without much knowledge of other systems so I'm still learning how people set up their systems (with pros and cons). I think I understand why you only want to listen to your loopback 😃

The fastest way to do this is by adding a startup option like --listening "http://127.0.0.1". It will then add the port number as well in code. Should that fix your problem partially?

Later I can add this setting to the EmbyStat settings page. But I first need a safe way of rebooting my own server because for the listening URLs to change I need a server reboot.

As for the authentication, currently, I made it so that you can't disable it. Sorry about that. It has just a simple username/password login. JWT tokens are just a way of sending user data and authentication info from server to client. You can find more information about it here: https://jwt.io/introduction/

Not sure how I will be able to completely disable it, maybe I can bypass the login system at some point but I will need some more time to investigate.

solarchemist commented 4 years ago

Adding a startup option like you suggest would be great, and more than enough to resolve this issue in my opinion. Thanks for listening!

As for the disableability (did I just make up that word?) of the authentication system you're working on, I suggest you don't worry too much about it. From what little I've seen of how EmbyStat is used, a built-in auth system (even if we can't disable it) is probably better than none.

mregni commented 4 years ago

No problem, thanks for testing my software and helping me to get it better step by step. It's a large project so it's going slow (steep learning curves everywhere for me :p )

A simple auth system is better than no auth system indeed. I also added some user roles support (some people were asking for a "viewer" account and "admin" account so I added that as well (only admin account is created now, multiple account support will be added later on)

FYI, I do like your word "disableability" :D

mregni commented 4 years ago

@chepec, can you check the beta.21 version to see if the --listen-urls parameters works for you?

solarchemist commented 4 years ago

Very nice :-)

For anyone else interested in running EmbyStat only on the localhost address, like this:

$ sudo netstat -plnt | grep -i emby
tcp        0      0 127.0.0.1:6555          0.0.0.0:*               LISTEN      31488/EmbyStat      
tcp6       0      0 :::8096                 :::*                    LISTEN      5376/EmbyServer

Which was achieved thanks to the newly added listen-urls parameter, as seen in the systemd service file:

$ cat /etc/systemd/system/emby-stat.service 
Description=Emby Stats service
[Service]
User=embystat
WorkingDirectory=/home/embystat
ExecStart=/home/embystat/EmbyStat --listen-urls "http://127.0.0.1"
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

PS @mregni I've written an Ansible role that installs EmbyStat (creates user account, downloads and unpacks the latest release, creates service file, and creates Apache reverse proxy vhost) that seems to work fine. Would you be interested to include it in your wiki?