Split the one TLS certificate so a caddy compromise cannot impersonate mail #40
Labels
No labels
area/backups
area/ci
area/containers
area/mail
area/minecraft
area/network
area/observability
area/tls
area/tofu
kind
bug
kind
chore
kind
feature
kind
investigation
kind
security
priority
high
priority
low
priority
medium
status/blocked
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
hutao/vps#40
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
modules/acme.nixissues one certificate,certs.${domain}, with every name ininfra.certSubdomainsas a SAN: the public sites,mailandsmtp, and the tailnet-only names (dozzle,grafana,syncthing). Caddy and the mailserver both mount the same/var/lib/acme/<domain>directory.So one private key impersonates everything. Caddy is the most exposed process on the box, since it parses every public byte of HTTP, TLS and QUIC. Code execution in caddy therefore yields a key that is also valid for the mail server, which caddy never serves. No sandbox helps there, because reading that key is caddy's legitimate job.
Proposal
Split into certificates by who uses them:
mail,smtp, read only by the mailserverdozzle,grafana,syncthing, served by caddy's second listenerEach is its own
security.acme.certsentry, withgroupandreloadServicesscoped to its users. Caddy then mounts only web and tailnet, and the mailserver only mail. A compromised caddy can impersonate the web names until revocation, and nothing else.infra.certSubdomainsis currently the single list that feeds the one cert; it becomes one list per cert, or a name-to-cert map. Caddy'scertDirand the mailserver's mount follow.Also worth a look
hu-tao.dev, so an issuance nobody here asked for is noticed.Check
openssl x509 -noout -ext subjectAltName) match its list, and no name appears in two.