I’m building a personal web server that needs to be privately accessible from any of the user’s machines. So, for example, it might be running on a Macbook, but accessed from a nearby PC, with both sitting on a public WI-Fi network.
I’d like to provide an easy, low ceremony way for the user to set up Let’s Encrypt on the server (i.e., generate a pair of key and certificate files). FWIW, my implementation is in Safari. Advice, comments, suggestions?
No real plan, as yet. I suppose that I could define each user’s domain as a sub-domain of a domain that I control, but that seems a bit funky (eg, brittle, not scalable, probably insecure). Problem is, these are personal web servers, being run by and for the end user. Alice has hers; Bob has his, etc. I only distribute the server app.
We’ve had a couple of discussions about this and I’m still looking into how various people have done this. One of the most sophisticated solutions that I was told about was
although simpler options may be possible.
But I think figuring out the naming scheme is going to be an important prerequisite here; it’s one of the biggest challenges for LAN applications and it also significantly affects how you can make use of a certificate authority.
The web PKI that we have is unfortunately not that well adapted to this kind of application; there was an idea that internal (non-public) names ought to use an internal (non-public) PKI, which makes a lot of sense in a large organization but is very tricky in a personal or small-business application, as well as any situation where the server is a mobile device that will be present on different networks at different times. (Unfortunately, it’s not that clear what means should be used to establish cryptographic trust in some of these cases. For example, anyone in mDNS can claim to be joe.local and I don’t know that there’s even a way to adjudicate disputes between rival claimants to the name. If two devices on a LAN say they are mymediaserver.local, how does a client know which of the two the user wanted to connect to?)
Thanks for your efforts! By way of background, the app (AxAp) is an “accessibility application” which uses web technology to mediate access to both local and Internet content. It has a Login page (etc), so it can protect itself somewhat from unauthorized use, but there is still a possibility that someone might be snooping. So, having folks run without HTTPS isn’t a really great option.
Making matters worse, the users in question may be blind or visually impaired. If the browser puts up its scary warnings in the form of inaccessible popups, the users may have no way to know that they are being asked to click through to gain access.
I’ve managed to create and install a self-signed certificate. It lets me browse in from either the host machine or another machine on the LAN. So, I have a solution for the moment, but I’d still prefer to use a “real” certificate (eg, from Let’s Encrypt). Let me know what you find out…
@Rich_Morin, the self-signed cert is a great solution if you control both the browser and the web server—in principle it’s actually better than a CA certificate because you’re not extending trust to a third party in order to communicate between your own machines.
The trouble is that if you use self-signed certs like this for an application you distribute to other people, they won’t really have a basis for deciding whether or not to add the certs in their own browsers, or at least the user interface for doing so is likely to be cumbersome (perhaps especially so for blind users, given the multiple layers of dialogs that may appear, as you were alluding to). In this scenario, “you” (as the application developer) don’t actually control the browser side, if you anticipate users using unmodified web browsers that came with their operating systems or that they downloaded from major browser vendors.
If you don’t want a self-signed cert but rather one that the browser will trust automatically, you need a public domain name and a way to
let users discover this name on their LAN
associate a locally-generated cryptographic key with a public name, and
perform an interaction with a CA like Let’s Encrypt to cause issuance of a certificate that reflects that association
This is a pretty tricky set of requirements. It seems that Plex has found one way to satisfy them, but it wasn’t particularly easy. CAs should be quite strict about these requirements because the industry standards that govern them make clear that they have to actually verify control of the name, and that the name has to actually exist in the public DNS. That should now be true for all certificate issuance under all of the roots that browsers trust by default.