On 2022/12/15 13:56:00 -0700, Ashlen <euryd...@riseup.net> wrote: > Hi all, so I'm wondering how to securely deal with TLS certificates on a > server > that's grown to host multiple services (website, XMPP, soon email as well). > Specifically how to handle permissions and to what degree certificates should > be > separated. > > (I recognize this is a long email. I'm unsure how to break down my thoughts > further) > > I know that I could add a load of Subject Alternative Names to one big > certificate, but I have a couple of concerns with this. > > 1) If I understand it right, if there's a security issue with one program and > an > attacker gains arbitrary read, and the effective user id can read the private > key, the exposure is greater than it has to be (that is to say, domains that > are > completely unrelated to the insecure program are exposed). Daemons outside of > base unfortunately often lack privilege separation to the extent that it > exists > in base, so there may not be a separate user to handle private keys, and then > the whole thing has the potential to blow up later. > > 2) A long list of Subject Alternative Names means that anyone connecting to > the > web server can see all of the additional subdomains that are unrelated to the > web server being hosted. This is really a nitpick compared to the first point, > as even without this being the case there are other methods of enumeration and > discovery (nmap and friends), and relying on DNS entries being hidden seems > like > a bad idea. > > The best way I can think of how to handle this so far, and "best" is used very > loosely since I don't think it's a perfect solution, is to split the keys up, > add a separate group, and modify `/etc/ssl/private`. > > ``` > # groupadd tls > # usermod -G tls _prosody > # chown root:tls /etc/ssl/private > # chmod 750 /etc/ssl/private > ``` > > Then the private keys within would all have 0400 permissions, user and group > being the same (so _prosody:_prosody for XMPP-related TLS). I noted that the > default is 700 permissions on `/etc/ssl/private` with root:wheel ownership. Is > the approach I've just outlined with adding a group and modifying permissions > a > bad idea?
Personally, I wouldn't deviate from the os defaults by changing the permission on /etc/ssl/private. it seems fragile, and you'd also need to make sure permissions are kept when updating the certificates. > Even if it makes sense to do it this way, I still have a separate issue in > that > when two or more services need the certificate for the root domain, they'll > end > up sharing it, and I'm unclear what the right way to fix that problem is. If > it's only services in the base system, that's one thing. But Prosody also has > this issue with the way I set it up. Currently it's configured so that > usernames > can be in the form "u...@example.com" rather than "u...@xmpp.example.com" > (similar to how email usernames use the root domain). This means it needs the > certificate for the root domain so that authentication can take place over > TLS, > and that breaks the separation. you can just issue multiple certificates. A compromised prosody would still be able to leak the certificate for "example.com", but there's no other way around it as it needs the certificate. > For some services, it can make sense to use relayd(8) and let that handle TLS > instead, which simplifies things since relayd has proper privilege separation > and can even use SNI. But I'm unsure how this could be done with something > like > Prosody since XMPP uses STARTTLS (outside of exceptions to that rule like > XEP-0368). > > What can I do to manage this better? Any ideas/suggestions are very welcome. > Thank you for reading all of this if you made it here. Can only speak for prosody as it's the only non-base daemon I'm getting TLS certificates for; my strategy with it has been to generate a different certificate and to deliver it in a place where only prosody can read it. Luckily, the prosody package installs /etc/prosody/certs owned by _prosody alone. # /etc/acme-client.conf domain xmpp { domain name example.com alternative names { room.example.com upload.example.com } domain key "/etc/prosody/certs/example.com.key" domain full chain certificate "/etc/prosody/certs/example.net.crt" sign with letsencrypt } note the `domain' name is "xmpp" because I have another `domain' block for the same domain (but different alt names) for httpd: # only for httpd domain example.com { alternative names { www.example.com } ... } all handled by cron as usual: ~ * * * * acme-client example.com && rcctl reload httpd ~ * * * * acme-client xmpp && rcctl restart prosody in prosody.conf.lua i have certificates = "certs" I also have some symlinks in /etc/prosody/certs in the form: {room,upload}.example.com.crt -> example.com.crt {room,upload}.example.com.key -> example.com.key so that prosody can look up the certs by itself without extra configuration. Can probably do it without the symlinks, but I was lazy and this worked for me. HTH