From e03a6541ced593b6c19a875f3fe59139d193a41c Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Fri, 5 Jun 2020 13:45:50 -0400 Subject: [PATCH] Don't make autoconfig/autodiscover subdomains and SRV records when the parent domain has no user accounts These subdomains/records are for automatic configuration of mail clients, but if there are no user accounts on a domain, there is no need to publish a DNS record, provision a TLS certificate, or create an nginx server config block. --- CHANGELOG.md | 4 ++++ management/dns_update.py | 28 +++++++++++++++------------- management/mailconfig.py | 14 ++++++++------ management/web_update.py | 8 ++++---- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01f860fe..04cfb753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ Mail: * An MTA-STS policy for incoming mail is now published (in DNS and over HTTPS) when the primary hostname and email address domain both have a signed TLS certificate installed. * MTA-STS reporting is enabled with reports sent to administrator@ the primary hostname. +DNS: + +* autoconfig and autodiscover subdomains and CalDAV/CardDAV SRV records are no longer generated for domains that don't have user accounts since they are unnecessary. + v0.45 (May 16, 2020) -------------------- diff --git a/management/dns_update.py b/management/dns_update.py index 5fdb3e0f..80273a12 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -281,28 +281,30 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en if not has_rec(dmarc_qname, "TXT", prefix="v=DMARC1; "): records.append((dmarc_qname, "TXT", 'v=DMARC1; p=reject', "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @%s." % (qname + "." + domain))) - # Add CardDAV/CalDAV SRV records on the non-primary hostname that points to the primary hostname. + # Add CardDAV/CalDAV SRV records on the non-primary hostname that points to the primary hostname + # for autoconfiguration of mail clients (so only domains hosting user accounts need it). # The SRV record format is priority (0, whatever), weight (0, whatever), port, service provider hostname (w/ trailing dot). - if domain != env["PRIMARY_HOSTNAME"]: + if domain != env["PRIMARY_HOSTNAME"] and domain in get_mail_domains(env, users_only=True): for dav in ("card", "cal"): qname = "_" + dav + "davs._tcp" if not has_rec(qname, "SRV"): records.append((qname, "SRV", "0 0 443 " + env["PRIMARY_HOSTNAME"] + ".", "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.")) - # Adds autoconfiguration A records for all domains. + # Adds autoconfiguration A records for all domains that there are user accounts at. # This allows the following clients to automatically configure email addresses in the respective applications. # autodiscover.* - Z-Push ActiveSync Autodiscover # autoconfig.* - Thunderbird Autoconfig - autodiscover_records = [ - ("autodiscover", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), - ("autodiscover", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), - ("autoconfig", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig."), - ("autoconfig", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig.") - ] - for qname, rtype, value, explanation in autodiscover_records: - if value is None or value.strip() == "": continue # skip IPV6 if not set - if not has_rec(qname, rtype): - records.append((qname, rtype, value, explanation)) + if domain in get_mail_domains(env, users_only=True): + autodiscover_records = [ + ("autodiscover", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), + ("autodiscover", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), + ("autoconfig", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig."), + ("autoconfig", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig.") + ] + for qname, rtype, value, explanation in autodiscover_records: + if value is None or value.strip() == "": continue # skip IPV6 if not set + if not has_rec(qname, rtype): + records.append((qname, rtype, value, explanation)) # If this is a domain name that there are email addresses configured for, i.e. "something@" # this domain name, then the domain name is a MTA-STS (https://tools.ietf.org/html/rfc8461) diff --git a/management/mailconfig.py b/management/mailconfig.py index 5f253c14..dd597cd6 100755 --- a/management/mailconfig.py +++ b/management/mailconfig.py @@ -258,13 +258,15 @@ def get_domain(emailaddr, as_unicode=True): pass return ret -def get_mail_domains(env, filter_aliases=lambda alias : True): +def get_mail_domains(env, filter_aliases=lambda alias : True, users_only=False): # Returns the domain names (IDNA-encoded) of all of the email addresses - # configured on the system. - return set( - [get_domain(login, as_unicode=False) for login in get_mail_users(env)] - + [get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ] - ) + # configured on the system. If users_only is True, only return domains + # with email addresses that correspond to user accounts. + domains = [] + domains.extend([get_domain(login, as_unicode=False) for login in get_mail_users(env)]) + if not users_only: + domains.extend([get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ]) + return set(domains) def add_mail_user(email, pw, privs, env): # validate email diff --git a/management/web_update.py b/management/web_update.py index 4a07dc9e..78f86f4c 100644 --- a/management/web_update.py +++ b/management/web_update.py @@ -24,13 +24,13 @@ def get_web_domains(env, include_www_redirects=True, exclude_dns_elsewhere=True) # the topmost of each domain we serve. domains |= set('www.' + zone for zone, zonefile in get_dns_zones(env)) - # Add Autoconfiguration domains, allowing us to serve correct SSL certs. + # Add Autoconfiguration domains for domains that there are user accounts at: # 'autoconfig.' for Mozilla Thunderbird auto setup. # 'autodiscover.' for Activesync autodiscovery. - domains |= set('autoconfig.' + maildomain for maildomain in get_mail_domains(env)) - domains |= set('autodiscover.' + maildomain for maildomain in get_mail_domains(env)) + domains |= set('autoconfig.' + maildomain for maildomain in get_mail_domains(env, users_only=True)) + domains |= set('autodiscover.' + maildomain for maildomain in get_mail_domains(env, users_only=True)) - # 'mta-sts.' for MTA-STS support. + # 'mta-sts.' for MTA-STS support for all domains that have email addresses. domains |= set('mta-sts.' + maildomain for maildomain in get_mail_domains(env)) if exclude_dns_elsewhere: