From d53eabedf85ef4608f4d10fa48d6b3d4f817c58e Mon Sep 17 00:00:00 2001 From: "David R. Andersen" Date: Mon, 17 Oct 2016 14:24:48 -0500 Subject: [PATCH] Add TLSA records for locally-hosted domains This commit adds TLSA records for all locally-hosted (sub)domains (those with A or AAAA records that match the local box). TLSA records are computed using the build_tlsa_record() method based on the default certificate (or key). Since the default key is the same for all domains hosted on the box, and the TLSA criteria used are 3 1 1, the TLSA record will be the same for all domains. At this point, there is no opt-out mechanism. I'm not sure if this is necessary, nor what would be the best way to do it if it is necessary. --- management/dns_update.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/management/dns_update.py b/management/dns_update.py index 784a5b08..a230f7b1 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -227,6 +227,7 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en defaults += [ ("www", "A", env["PUBLIC_IP"], "Optional. Sets the IP address that www.%s resolves to so that the box can provide a redirect to the parent domain." % domain), ("www", "AAAA", env.get('PUBLIC_IPV6'), "Optional. Sets the IPv6 address that www.%s resolves to so that the box can provide a redirect to the parent domain." % domain), + ("_443._tcp.www", "TLSA", build_tlsa_record(env), "Optional. When DNSSEC is enabled, provides out-of-band HTTPS certificate validation for a few web clients that support it."), ] for qname, rtype, value, explanation in defaults: if value is None or value.strip() == "": continue # skip IPV6 if not set @@ -282,6 +283,17 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en 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.")) + # Add TLSA records for all locally-resolved qnames except the nameservers + locally_resolved_ips = [env["PUBLIC_IP"]] + if env.get("PUBLIC_IPV6"): + locally_resolved_ips += [env["PUBLIC_IPV6"]] + all_locally_resolved_qnames = set(r[0] for r in records if r[1] in ("A", "AAAA") and r[2] in locally_resolved_ips) + for qname in all_locally_resolved_qnames: + tlsa_qname = "_443._tcp" + ("" if qname is None else "." + qname) + if ".ns1" in tlsa_qname or ".ns2" in tlsa_qname: continue # don't include the nameservers + if not has_rec(tlsa_qname, "TLSA"): + records.append((tlsa_qname, "TLSA", build_tlsa_record(env), "Optional. When DNSSEC is enabled, provides out-of-band HTTPS certificate validation for a few web clients that support it.")) + # Sort the records. The None records *must* go first in the nsd zone file. Otherwise it doesn't matter. records.sort(key = lambda rec : list(reversed(rec[0].split(".")) if rec[0] is not None else ""))