jellyfin / Swiftfin

Native Jellyfin Client for iOS and tvOS
Mozilla Public License 2.0
2.5k stars 272 forks source link

Allow signing into https server with self-signed certificate #379

Closed tkafka closed 1 year ago

tkafka commented 2 years ago

Describe the feature you'd like I would like to have an option to sign into server running on https (on my NAS) with self-signed certificate. Currently I cannot continue signing in after entering my Jellyfin server url, presumably due to certificate error - connection just fails silently, and I never get to a second screen where I enter the user name and password.

Additional context I have Jellyfin running on NAS with https exposed to internet on a non-standard port. As I am behind the NAT and multiple people (customers of a same ISP) are exposed to internet on a single IP (everyone has a random port range), I cannot generate a valid certificate with letsencrypt, so I use a self-signed certificate.

Other apps sometimes have a toggle for allowing the use of self-signed https certificates.

Thank you for considering!

hendrik1120 commented 2 years ago

@tkafka Hi, I am not part of the dev team for Swiftfin, but I might be able to help you with your certs since my ISP is even worse :D (double NAT with no port forwarding at all). If you got a FQDN, the following will work for you: You could use the free cloudflare argo tunnel for the certbot to verify through to your server. Just point the tunnel to your server or reverse proxy and create a wildcard cert for your whole domain. The tunnel however is restricted to HTML content only, so don't route jellyfin directly through it! Use your port forwarding as before, but now with a symlink to the valid certs. I hope this will help you until self-signed certs get accepted by the app.

tkafka commented 2 years ago

@hendrik1120 Ooof, thank you, it's not pretty but it's at least an existence proof of a possible solution :). I'll probably keep using the web UI when not at home, and hope we could get this improved.

Sapd commented 2 years ago

As I am behind the NAT and multiple people (customers of a same ISP) are exposed to internet on a single IP (everyone has a random port range), I cannot generate a valid certificate with letsencrypt, so I use a self-signed certificate.

You can acquire a certificate via DNS: https://www.digitalocean.com/community/tutorials/how-to-acquire-a-let-s-encrypt-certificate-using-dns-validation-with-acme-dns-certbot-on-ubuntu-18-04

tkafka commented 2 years ago

@Sapd Thank you, I should clarify though that I don't own the domain (it's the ISP's domain), so I understand there is no way of me getting a valid certificate for a domain I don't own (I just have a port range exposed on it).

Sapd commented 2 years ago

@Sapd Thank you, I should clarify though that I don't own the domain (it's the ISP's domain), so I understand there is no way of me getting a valid certificate for a domain I don't own (I just have a port range exposed on it).

Ahh I see. What I recommend then is that you get a domain with a cheap TLD. A lot of (better) domain providers provide DynDNS support. With that you can install ddclient on Linux/Your NAS/PI which will update your IP automatically to the domains NS servers. I just saw on your Github Page that you already have a domain, just check wether your registrar/DNS-provider has DynDNS support. You can use then a subdomain for that. Signing LetsEncrypt with TXT will even work when your HTTP server is on a non-standard port on a IP you don't own.

tkafka commented 2 years ago

@Sapd Signing LetsEncrypt with TXT will even work when your HTTP server is on a non-standard port on a IP you don't own. Thank you! This is the info I was missing, I thought there is no way to generate a certificate if I don't control the 80/433 ports.

ddnomad commented 1 year ago

Would love to see support for this. Going through all the hoops with LetsEncrypt just to be able to use TLS in the local network seems to be a bit of an overkill, especially as it involves purchasing a domain name and leaking meta information through DNS.

There is, of course, another option: roll local PKI, and while it is probably "the correct" solution for many, marrying it with Apple TV etc. will definitely be even more involved than going LetsEncrypt route.

So yes, using self-signed certs is naughty but it is better than nothing. As it stands right now, people will most probably pick "no security" (HTTP only) which is not ideal.

Sapd commented 1 year ago

Would love to see support for this. Going through all the hoops with LetsEncrypt just to be able to use TLS in the local network seems to be a bit of an overkill, especially as it involves purchasing a domain name and leaking meta information through DNS.

You can use a free domain from duckdns. Issuing a letsencrypt certificate is actually quite easy, you can simply use CertBot which - if used with nginx - even provides an automated one-line way. A better way than simply allowing self-signed certificates would probably be the writing of a plugin for certbot for Jellyfin.

As it stands right now, people will most probably pick "no security" (HTTP only) which is not ideal.

Self-Signed HTTPS is only better when the user verifies the certificate he gets (and does not simply click away warnings if the certificate changed).

However enforcing the use of valid certificates with no overwrite (somewhere hidden in settings) is also a bit worrisome bc. of the full dependency to certificate providers. But given Lets encrypt from the Mozilla Foundation is there its probably negligible.

thornbill commented 1 year ago

None of the official Jellyfin apps support self-signed certificates beyond what the system supports by default (i.e. you may be able to install the generated CA to the devices trust store for some platforms). I would be inclined to close this as not planned but defer to the maintainers here.

ddnomad commented 1 year ago

@Sapd

You can use a free domain from duckdns. Issuing a letsencrypt certificate is actually quite easy, you can simply use CertBot which - if used with nginx - even provides an automated one-line way. A better way than simply allowing self-signed certificates would probably be the writing of a plugin for certbot for Jellyfin.

From my research (though quite limited), to do certbot without exposing any ports basically means doing verification via DNS TXT record, which requires keeping DNS provider API key or other credentials local on the server to periodically update the TXT record. This is not ideal, as you either trust some "free domain provider" or trust yourself enough to keep your DNS API keys on the host at all times.

Additionally, a lot of people prefer running their own private DNS server and that does not require having a "real" domain at all.

Self-Signed HTTPS is only better when the user verifies the certificate he gets (and does not simply click away warnings if the certificate changed).

It all comes down to individual's threat model, in my view, if I host Jellyfin strictly in my LAN and trust my DNS, there's near 0 risk of somebody managing to MITM my devices and masquerade as one of the services I run. It is still possible, but additional friction of accommodating this possibility is not worth the grief from where I stand.

ddnomad commented 1 year ago

@thornbill

None of the official Jellyfin apps support self-signed certificates beyond what the system supports by default (i.e. you may be able to install the generated CA to the devices trust store for some platforms). I would be inclined to close this as not planned but defer to the maintainers here.

I've tried manually installing and trusting my self-signed certificate on macOS, iOS, iPadOS and tvOS. MacOS worked fine when accessing Jellyfin via the browser, while both Swiftfin and Infuse on all other operating systems straight up refused to connect without providing any additional details.

After shelling out and purchasing a proper wildcard certificate for my homelab and using it for Jellyfin, everything just worked as expected. A bit of a shame but I guess that's the only solution that I find worthwhile at the moment.

Still, allowing to trust the self-signed certificate on the first use with pinning (à la SSH) would be lovely, as it would check most of the boxes without forcing people to jump through quite unnecessary hoops to just get their homelab setup up and running.

sjorge commented 1 year ago

There is, of course, another option: roll local PKI, and while it is probably "the correct" solution for many, marrying it with Apple TV etc. will definitely be even more involved than going LetsEncrypt route.

Unfortunately this might not work, I have my own CA (via step-ca) I use in my homelab, but you will hit https://github.com/jellyfin/jellyfin/issues/8340

LePips commented 1 year ago

I do apologize, but I have no intention of implementing anything related to custom client certificate selection or its maintenance.

Interestingly though, I remember seeing that somebody did attempt to implement it in their own fork with the old API. However I can't find it in the GitHub Network Graph anymore since it's been so long.

Patt92 commented 4 months ago

this doesn't work at all anyway even with legit Lets Encrypt certs. I have a nginx proxying port 8096 and every single app works, except swiftfin's native player. The certificate is legit and all checks are passing. Every other app for Jellyfin works out of the box. No warnings for example for the certificate. It just works, while Swiftfin stays black when starting to play. The only app, I must allow http, which is less secure then selfsigned certs just my thoughts.

rwjack commented 3 months ago

@Patt92 something is wrong with your config then. I had an issue where I couldn't even add my server on ATV, so I connected directly via ip:port - then I realized I can import my self signed CA into ATV: https://lucaslegname.github.io/mitmproxy/2020/04/10/certificate-tvos.html

And now it works without issue.