From d70c3d61893d823410374e0197c601079f48d3cb Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 10 Oct 2021 12:34:55 +0200 Subject: [PATCH] Added more comments, plus renamed vars with better names --- dns.go | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/dns.go b/dns.go index db09337d..9826a414 100644 --- a/dns.go +++ b/dns.go @@ -8,9 +8,26 @@ import ( "tailscale.com/util/dnsname" ) -// generateMagicDNSRootDomains generates a list of DNS entries to be included in the -// routing for DNS in the MapResponse struct. This list of DNS instructs the OS -// on what domains the Tailscale embedded DNS server should be used for. +// generateMagicDNSRootDomains generates a list of DNS entries to be included in `Routes` in `MapResponse`. +// This list of reverse DNS entries instructs the OS on what subnets and domains the Tailscale embedded DNS +// server (listening in 100.100.100.100 udp/53) should be used for. +// +// Tailscale.com includes in the list: +// - the `BaseDomain` of the user +// - the reverse DNS entry for IPv6 (0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa., see below more on IPv6) +// - the reverse DNS entries for the IPv4 subnets covered by the user's `IPPrefix`. +// In the public SaaS this is [64-127].100.in-addr.arpa. +// +// The main purpose of this function is then generating the list of IPv4 entries. For the 100.64.0.0/10, this +// is clear, and could be hardcoded. But we are allowing any range as `IPPrefix`, so we need to find out the +// subnets when we have 172.16.0.0/16 (i.e., [0-255].16.172.in-addr.arpa.), or any other subnet. +// +// How IN-ADDR.ARPA domains work is defined in RFC1035 (section 3.5). Tailscale.com seems to adhere to this, +// and do not make use of RFC2317 ("Classless IN-ADDR.ARPA delegation") - hence generating the entries for the next +// class block only. + +// From the netmask we can find out the wildcard bits (the bits that are not set in the netmask). +// This allows us to then calculate the subnets included in the subsequent class block and generate the entries. func generateMagicDNSRootDomains(ipPrefix netaddr.IPPrefix, baseDomain string) (*[]dnsname.FQDN, error) { base, err := dnsname.ToFQDN(baseDomain) if err != nil { @@ -26,20 +43,20 @@ func generateMagicDNSRootDomains(ipPrefix netaddr.IPPrefix, baseDomain string) ( netRange := ipPrefix.IPNet() maskBits, _ := netRange.Mask.Size() - // lastByte is the last IP byte covered by the mask - lastByte := maskBits / 8 + // lastOctet is the last IP byte covered by the mask + lastOctet := maskBits / 8 - // unmaskedBits is the number of bits not under the mask in the byte lastByte - unmaskedBits := 8 - maskBits%8 + // wildcardBits is the number of bits not under the mask in the lastOctet + wildcardBits := 8 - maskBits%8 - // min is the value in the lastByte byte of the IP - // max is basically 2^unmaskedBits - i.e., the value when all the unmaskedBits are set to 1 - min := uint(netRange.IP[lastByte]) - max := uint((min + 1<= 0; i-- { + for i := lastOctet - 1; i >= 0; i-- { rdnsSlice = append(rdnsSlice, fmt.Sprintf("%d", netRange.IP[i])) } rdnsSlice = append(rdnsSlice, "in-addr.arpa.")