How Plex is doing HTTPS for all its users

This week Plex, a self-hosted media server, announced that they now offer TLS to secure all connections, including those to the user's servers. This is actually pretty interesting.

Background

A quick overview of the Plex architecture to understand why this is different from the average HTTPS deployment.

The server is a piece of software that runs on your own machine, where you have all your movies and TV series. The server is linked to your Plex.tv account.

The clients connect to Plex.tv to discover the servers linked to your account, and then connect directly to the server.

For example, if you use the web app, you load http://plex.tv/web/app, the app asks Plex.tv the list of your servers and then connect to each of them with a XHR like http://1.2.3.4:32400/library/sections.

Why it's tricky

Let's say Plex sets up HTTPS for plex.tv and we load https://plex.tv/web/app instead. That part is easy.

The problem is that now the browser will block our XHR connections to the servers because they are HTTP connections initiated from a HTTPS page a.k.a. active mixed content.

Also the server connections need to be over HTTPS. And they need a valid public certificate: there is no UI to skip warnings generated by XHR and a self-signed certificate would be a quite poor security guarantee anyway.

But as we said above, the servers are run by the users on their own machines and IPs. We can't ask them to get a domain name and a certificate just to watch their movies over TLS.

How Plex solved it

They went nuclear. First they solved the problem of servers not having a domain name or a stable IP (they are mostly reached via bare dynamic IPs or even local IPs) by setting up a dynamic DNS space under plex.direct:

$ dig 1-2-3-4.625d406a00ac415b978ddb368c0d1289.plex.direct +short
1.2.3.4  
$ dig 10-10-10-10.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.plex.direct +short
10.10.10.10  

Basically any IP.*.plex.direct domain resolves to IP.

Then they partnered with Digicert to issue a wildcard certificate for *.HASH.plex.direct to each user, where HASH is - I guess - a hash of the user or server name/id.

For example see how my server presents a *.625d406a00ac415b978ddb368c0d1289.plex.direct certificate now.

my server certificate

It's interesting to see how Digicert minted a new Intermediate certificate for this deployment. Also note that they claim the number of servers is in the millions.

This way when a server first starts it asks for its wildcard certificate to be issued (which happened almost instantly for me) and then the client, instead of connecting to http://1.2.3.4:32400, connects to https://1-2-3-4.625d406a00ac415b978ddb368c0d1289.plex.direct:32400 which resolves to the same IP, but with a domain name that matches the certificate that the server (and only that server, because of the hash) holds.

console log of connections

This is actually pretty clever:

  • the "jolly" DNS setup allows the client to connect to the server with any IP it wants - for example 192.168.1.7 when at home, 1.2.3.4 when not - which can change without waiting for any DNS propagation time
  • the wildcard certificate is valid whatever the IP used
  • the user/server/whatever hash makes it so a certificate can only be used to authenticate a specific server (even if it can have any IP) which makes it safe to hand the private key to the user
  • since the root domain is plex.direct they won't have any trouble doing the required Domain Validation

It's important to note that for the user to be able to load https://plex.tv/web/app ALL their servers must support HTTPS, otherwise the HTTP ones will be unreachable because of the mixed-content block discussed above. They actually built this UI quite well IMHO: you will be automatically redirected to HTTPS only if all your servers are updated but can still force the HTTPS web app by loading it directly (a message will explain you can't connect to the old servers, and offer you to load the HTTP app instead).

P.S.: I finally figured out why they advise you might need to turn off DNS rebinding protections: a domain like 192-168-1-7.###.plex.direct which resolves to a local IP (that they use when you want to connect to a server on your LAN while still using the HTTPS web app) is exactly what a rebinding attack needs to access vulnerable services behind your firewall. See for example this post by Michele Spagnuolo.

The boring problems

Plex also notes how they had a hard time finding a configuration that worked with all their clients (which remember include Smart TVs, brrr...).

Even if I can totally feel their pain, this part is not really new, but well done for getting a A+ score nonetheless.

Conclusion

This is a pretty nice example of wide scale automated TLS certificate deployment. The technical feat might not be the first in its genre, but the UX is extremely well polished.

The result is an effortless, state-of-the-art secure deployment of TLS by default for millions of users. Well done.

Finally, it's meaningful that they were able to provide all this for free (as in, for their non-paying users). The era of paying for basic certificates is coming to an end.

And now I don't want to hear anyone say they can't offer HTTPS "because videos". There are now thousands of homebrew servers doing video transcoding AND streaming over TLS. Unless you are Netflix, shut up ;)

For more mildly interesting TLS posts, follow me on Twitter.