ipn/ipnlocal: plumb fallback DNS in as a workaround for split DNS issues.

Cause of #1743.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson 2021-04-19 21:58:26 -07:00 committed by Dave Anderson
parent 28ba20d733
commit 1e5c608fae
2 changed files with 32 additions and 6 deletions

View File

@ -1581,14 +1581,18 @@ func (b *LocalBackend) authReconfig() {
// If CorpDNS is false, dcfg remains the zero value. // If CorpDNS is false, dcfg remains the zero value.
if uc.CorpDNS { if uc.CorpDNS {
for _, resolver := range nm.DNS.Resolvers { addDefault := func(resolvers []tailcfg.DNSResolver) {
for _, resolver := range resolvers {
res, err := parseResolver(resolver) res, err := parseResolver(resolver)
if err != nil { if err != nil {
b.logf(err.Error()) b.logf("skipping bad resolver: %v", err.Error())
continue continue
} }
dcfg.DefaultResolvers = append(dcfg.DefaultResolvers, res) dcfg.DefaultResolvers = append(dcfg.DefaultResolvers, res)
} }
}
addDefault(nm.DNS.Resolvers)
if len(nm.DNS.Routes) > 0 { if len(nm.DNS.Routes) > 0 {
dcfg.Routes = map[dnsname.FQDN][]netaddr.IPPort{} dcfg.Routes = map[dnsname.FQDN][]netaddr.IPPort{}
} }
@ -1635,6 +1639,27 @@ func (b *LocalBackend) authReconfig() {
set(peer.Name, peer.Addresses) set(peer.Name, peer.Addresses)
} }
} }
// Set FallbackResolvers as the default resolvers in the
// scenarios that can't handle a purely split-DNS config. See
// https://github.com/tailscale/tailscale/issues/1743 for
// details.
switch {
case len(dcfg.DefaultResolvers) != 0:
// Default resolvers already set.
case len(dcfg.Routes) == 0 && len(dcfg.Hosts) == 0 && len(dcfg.AuthoritativeSuffixes) == 0:
// No settings requiring split DNS, no problem.
case (version.OS() == "iOS" || version.OS() == "macOS") && !uc.ExitNodeID.IsZero():
// On Apple OSes, if your NetworkExtension provides a
// default route, underlying primary resolvers are
// automatically removed, so we MUST provide a set of
// resolvers capable of resolving the entire world.
// https://github.com/tailscale/tailscale/issues/1713
addDefault(nm.DNS.FallbackResolvers)
case version.OS() == "android":
// We don't support split DNS at all on Android yet.
addDefault(nm.DNS.FallbackResolvers)
}
} }
err = b.e.Reconfig(cfg, rcfg, &dcfg) err = b.e.Reconfig(cfg, rcfg, &dcfg)

View File

@ -852,6 +852,7 @@ type DNSConfig struct {
// FallbackResolvers is like Resolvers, but is only used if a // FallbackResolvers is like Resolvers, but is only used if a
// split DNS configuration is requested in a configuration that // split DNS configuration is requested in a configuration that
// doesn't work yet without explicit default resolvers. // doesn't work yet without explicit default resolvers.
// https://github.com/tailscale/tailscale/issues/1743
FallbackResolvers []DNSResolver `json:",omitempty"` FallbackResolvers []DNSResolver `json:",omitempty"`
// Domains are the search domains to use. // Domains are the search domains to use.
// Search domains must be FQDNs, but *without* the trailing dot. // Search domains must be FQDNs, but *without* the trailing dot.