Dantevg / WebStats

Spigot plugin to display the scoreboard, PlaceholderAPI and other plugin statistics on the web
https://dantevg.nl/mods-plugins/WebStats
MIT License
19 stars 10 forks source link

HTTPS support #23

Closed Dantevg closed 1 year ago

Dantevg commented 2 years ago

Support serving the stats over https natively, somehow. Without relying on manual configuration.

For the internal web server, this is not needed because everything is unencrypted. For an external web server this is also not needed because you can set up a reverse proxy. Native HTTPS support is only needed for external websites created with services like Wix, Squarespace or Weebly, where you cannot set up a reverse proxy.

It is possible (and easy) to generate a self-signed certificate and use that. But, browsers will give you a big fat warning. So, we need to somehow get a validated certificate from something like letsencrypt. The problem is that they use DV (domain validation), which seems to not be available for IPs, only domains.

Challenge types: https://letsencrypt.org/docs/challenge-types/

The HTTP-01 and TLS-ALPN-01 challenge types use port 80 or 443 to verify the certificate, which you do not have access to unless you self-host.

DNS-01 challenge

We can use the DNS-01 challenge in manual mode. Downside: need to manually renew the certificate every few months. How to get a letsencrypt certificate with DNS validation: [IN PROGRESS] https://eff-certbot.readthedocs.io/en/stable/using.html#manual

sudo certbot certonly --manual --preferred-challenges dns

sudo openssl pkcs12 -export -out webstats.p12 -in /etc/letsencrypt/live/tlstest.equinoxmc.nl/fullchain.pem -inkey /etc/letsencrypt/live/tlstest.equinoxmc.nl/privkey.pem -name webstats

sudo keytool -importkeystore -srckeystore webstats.p12 -srcstoretype pkcs12 -srcalias webstats -destke
ystore webstats.jks -deststoretype jks -deststorepass webstats -destalias webstats

DNS-01 with DuckDNS

DuckDNS is a free DNS provider with an API to change A and TXT records. This means you can use a DuckDNS subdomain as the domain for the WebStats plugin on your server.

DNS TXT record URL format: (https://www.duckdns.org/spec.jsp)

https://www.duckdns.org/update?domains=<SUBDOMAIN>.duckdns.org&token=<DUCKDNS_TOKEN>&txt=<DNS_CHALLENGE>

Java ACME challenge library

To automatically renew the certificate, the plugin needs to use a Java library. Acme4J is listed in the letsencrypt list of Java libraries. [IN PROGRESS]

ZeroSSL

ZeroSSL seems to be an alternative to letsencrypt that does support TLS certificates for IP addresses: https://zerossl.com/documentation/api/create-certificate/. This still does not work because we would need to get a certificate for only the WebStats port.

Resources

NickMesser commented 2 years ago

You mentioned using redirects to bypass https? When did you mean exactly. I want to embed this into my webpage that uses https but I cannot. I had to make a new page that was http to get this to work properly. Is there a workaround I can do?

Dantevg commented 2 years ago

If you have your own hosting (i.e. not services like squarespace), you can set up a reverse proxy, which works a bit like this:

your stats page ---https---> your reverse proxy ---http---> WebStats on your MC server

The basics are explained in the wiki, but I may be able to help if you can't make it work.

Olen commented 1 year ago

I understand the rationale, but should not certificate maintenance really be "someone elses problem"? If you make it easy to supply a certificate (or fullchain) as a file, then how the admin gets the certificate is really not something that should be solved by this plugin? Some people will use existing certificates - maybe even wildcard certs - so a way to say something like

https: True
cert_file: foo.cert
cert_keyfile: bar.key

would be a good start. When that is in place we can look at implementing acme or other certiifcate providers.

Dantevg commented 1 year ago

That seems like a good idea now that I think about it. Although the number of people that will use it in this form is probably near zero, it does provide a good starting point. I'll see how I can make it work with just the basics.

Olen commented 1 year ago

I agree that it would be a corner case, but implementing certificate management and renewals and everything does not really feel like something each plugin should do. If you really need to run this as https, and do not have an option to run a reverse proxy, scripting something that uses e.g certbot and DNS-challenges and just copies the certificate to the right location is probably easier to do outside of the plugin. So one thing that maybe could be an idea would be to implement webstats restart (or just webstats reload cert) as an API request, so you don't need to manually reload the plugin after replacing the certificate.

Dantevg commented 1 year ago

It would indeed be weird if each plugin would manage the certificate itself (and I agree that that functionality doesn't belong in a plugin like WebStats). But it is also weird that there is no way to show the live statistics on a https page (every normal webpage nowadays) without a reverse proxy. The issue with running a certbot script on the server is that that is only possible for self-hosted servers. Smaller servers (including mine πŸ™ƒ) hosted at cheap game hosting providers need to do everything through java plugins.

I'm very hesitant on adding web requests that perform some action on the server, without any authentication. Right now all requests only read data which feels a lot more comfortable. webstats reload cert as an in-game command seems like a better option. It could even be automated to execute daily or something.

Olen commented 1 year ago

Are you allowed to run shell-scripts? If so, you could maybe implement something that runs acme.sh from the Java-plugin? The good thing is that it is very easy to use, and that it supports a HUGE list of dns providers: https://github.com/acmesh-official/acme.sh/wiki/dnsapi

That way, you don't need to worry about how to update the DNS servers and complete renewals etc. But of course, it means that you need to have a domain name, but that might not be a big issue? After all, a domain name costs next to nothing, and since you do not use any standard ports here, there is probably nothing that blocks requests to your own domain name.

Dantevg commented 1 year ago

I don't think I can run shell scripts, but it is worth a try.

As for the domain name, that seems to be required anyway for a tls certificate so that shouldn't be a problem πŸ˜„. (also, without a domain name you're using the internal web server so everything is served over plain http anyway.)