msimerson / Mail-Toaster-6

Mail Toaster 6
https://github.com/msimerson/Mail-Toaster-6/wiki
BSD 3-Clause "New" or "Revised" License
46 stars 16 forks source link

Adding alternate domains to the SSL cert #528

Closed greenshrike closed 1 year ago

greenshrike commented 1 year ago

For servers which host multiple domains, users of alternate domains to the toaster's primary hostname are forced to either use a different domain to access the server from their email address's domain -- which makes mail client setup more onerous as automatic server identification fails, as well as making webmail a chore as users have to remember to type some other domain's URL rather than their own -- or to suppress "wrong domain" SSL warnings.

Yes, mail client support for checking domains against the "X509v3 Subject Alternative Name" field (in addition to the standard "Subject/CN" field) is spotty, but one presumes it will get better and using subject alt names doesn't make things worse than they currently stand. And web clients support alternative names just fine.

acme.sh itself supports adding multiple domains into a cert, but MT6 doesn't expose this functionality.

For toaster admins not wishing to be locked to a single domain in their SSL cert, the following may be of use:

--- mail-toaster.conf.old       2022-12-22 10:38:10.000848000 -0500
+++ mail-toaster.conf   2022-12-22 10:37:58.874104000 -0500
@@ -1,5 +1,6 @@
 export TOASTER_ORG_NAME="Sparky the Toaster"
 export TOASTER_HOSTNAME="mail.primarydomain.com"
+export TOASTER_HOSTNAME_ALT="mail.secondary.com vmail.otherdomain.org smtp.yetanother.com"
 export TOASTER_MAIL_DOMAIN="primarydomain.com"
 export TOASTER_ADMIN_EMAIL="postmaster@primarydomain.com"
 export TOASTER_SRC_URL="https://raw.githubusercontent.com/msimerson/Mail-Toaster-6/master"
--- provision/letsencrypt.sh.old        2022-12-22 10:39:39.176060000 -0500
+++ provision/letsencrypt.sh    2022-12-22 10:35:28.913630000 -0500
@@ -391,9 +391,14 @@
        local _HTTPDIR="$ZFS_DATA_MNT/webmail"
        local _acme="/root/.acme.sh/acme.sh"

+       local _hostname_alts=""
+       for _alt in $TOASTER_HOSTNAME_ALT; do
+               _hostname_alts="$_hostname_alts -d $_alt"
+       done
+
        $_acme --set-default-ca --server letsencrypt

-       if $_acme --issue --force -d "$TOASTER_HOSTNAME" -w "$_HTTPDIR"; then
+       if $_acme --issue --force -d "$TOASTER_HOSTNAME" -w "$_HTTPDIR" $_hostname_alts; then
                update_haproxy_ssld
                $_acme --deploy -d "$TOASTER_HOSTNAME" --deploy-hook mailtoaster
        else

Probably obvious, but it changes the acme.sh issue command into:

/root/.acme.sh/acme.sh --issue --force -d mail.primarydomain.com -w /data/webmail  -d mail.domain1.com -d vmail.otherdomain.org -d smtp.yetanother.com

That's pretty much all that needs to be done.

Let's Encrypt will, of course, check the validity of the alternate domains, so they need to be pointed at the toaster. HAProxy detects LE challenges by the file path, not domain, so alt domain checks are directed to the same webroot as the primary domain. And once the cert is issued, nothing changes with the cert deployment and acme.sh will automatically renew the cert with all configured domains.

Getting this added to MT6 would be great, for the usual "now I don't have to maintain separate patches" reasons. :-)

Cheers.

tuffnatty commented 1 year ago

I also have such a change, but yours seems to be better factored.

msimerson commented 1 year ago

I won't be adding this to MT6. I've have used dozens of certs with numerous alternate names in the past and I don't recommend it unless all the alt names are within the same domain name. Why? If one alternate name in your cert-of-many-alternates stops resolving, perhaps because its a client domain and they didn't renew it, now that entire cert will fail to renew. If your monitoring is set up to notice, you'll catch it before it impacts customers, but that's still a far-less-than-great failure mode. Instead, just create a cert for every domain name. Haproxy, dovecot, and Haraka all have SNI support so that they'll return the TLS certificate that matches the hostname the client asked for.