From 720c1ad0f0c5c95cfe8f3c725e5ad029271e907e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 7 Apr 2021 00:58:02 -0700 Subject: [PATCH] net/dns: insert OS base config when emulating split DNS. Part of #953. Signed-off-by: David Anderson --- net/dns/manager.go | 31 +++++++++++++++++++++++-------- net/dns/manager_test.go | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/net/dns/manager.go b/net/dns/manager.go index d55e973cf..e773415a3 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -76,7 +76,10 @@ func (m *Manager) Set(cfg Config) error { forceSplitDNSForTesting(&cfg) } - rcfg, ocfg := m.compileConfig(cfg) + rcfg, ocfg, err := m.compileConfig(cfg) + if err != nil { + return err + } m.logf("Resolvercfg: %+v", rcfg) m.logf("OScfg: %+v", ocfg) @@ -93,7 +96,7 @@ func (m *Manager) Set(cfg Config) error { // compileConfig converts cfg into a quad-100 resolver configuration // and an OS-level configuration. -func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig) { +func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig, error) { // Deal with trivial configs first. switch { case !cfg.needsOSResolver(): @@ -102,14 +105,14 @@ func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig) { // configs clear all Tailscale DNS settings. return resolver.Config{}, OSConfig{ SearchDomains: cfg.SearchDomains, - } + }, nil case cfg.hasDefaultResolversOnly(): // Trivial CorpDNS configuration, just override the OS // resolver. return resolver.Config{}, OSConfig{ Nameservers: toIPsOnly(cfg.DefaultResolvers), SearchDomains: cfg.SearchDomains, - } + }, nil case cfg.hasDefaultResolvers(): // Default resolvers plus other stuff always ends up proxying // through quad-100. @@ -127,7 +130,7 @@ func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig) { Nameservers: []netaddr.IP{tsaddr.TailscaleServiceIP()}, SearchDomains: cfg.SearchDomains, } - return rcfg, ocfg + return rcfg, ocfg, nil } // From this point on, we're figuring out split DNS @@ -144,7 +147,7 @@ func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig) { Nameservers: toIPsOnly(cfg.singleResolverSet()), SearchDomains: cfg.SearchDomains, MatchDomains: cfg.matchDomains(), - } + }, nil } // Split DNS configuration with either multiple upstream routes, @@ -170,10 +173,15 @@ func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig) { if m.os.SupportsSplitDNS() { ocfg.MatchDomains = cfg.matchDomains() } else { - rcfg.Routes["."] = []netaddr.IPPort{netaddr.MustParseIPPort("8.8.8.8:53")} + bcfg, err := m.os.GetBaseConfig() + if err != nil { + return resolver.Config{}, OSConfig{}, err + } + rcfg.Routes["."] = toIPPorts(bcfg.Nameservers) + ocfg.SearchDomains = append(ocfg.SearchDomains, bcfg.SearchDomains...) } - return rcfg, ocfg + return rcfg, ocfg, nil } func addFQDNDots(domains []string) []string { @@ -196,6 +204,13 @@ func toIPsOnly(ipps []netaddr.IPPort) (ret []netaddr.IP) { return ret } +func toIPPorts(ips []netaddr.IP) (ret []netaddr.IPPort) { + for _, ip := range ips { + ret = append(ret, netaddr.IPPort{IP: ip, Port: 53}) + } + return ret +} + func (m *Manager) EnqueueRequest(bs []byte, from netaddr.IPPort) error { return m.resolver.EnqueueRequest(bs, from) } diff --git a/net/dns/manager_test.go b/net/dns/manager_test.go index eb22d3844..7062b17ec 100644 --- a/net/dns/manager_test.go +++ b/net/dns/manager_test.go @@ -14,7 +14,8 @@ import ( ) type fakeOSConfigurator struct { - SplitDNS bool + SplitDNS bool + BaseConfig OSConfig OSConfig OSConfig ResolverConfig resolver.Config @@ -37,8 +38,7 @@ func (c *fakeOSConfigurator) SupportsSplitDNS() bool { } func (c *fakeOSConfigurator) GetBaseConfig() (OSConfig, error) { - // TODO - return OSConfig{}, nil + return c.BaseConfig, nil } func (c *fakeOSConfigurator) Close() error { return nil } @@ -54,6 +54,7 @@ func TestManager(t *testing.T) { name string in Config split bool + bs OSConfig os OSConfig rs resolver.Config }{ @@ -178,9 +179,13 @@ func TestManager(t *testing.T) { Routes: upstreams("corp.com", "2.2.2.2:53"), SearchDomains: strs("tailscale.com", "universe.tf"), }, + bs: OSConfig{ + Nameservers: mustIPs("8.8.8.8"), + SearchDomains: strs("coffee.shop"), + }, os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), - SearchDomains: strs("tailscale.com", "universe.tf"), + SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"), }, rs: resolver.Config{ Routes: upstreams( @@ -209,9 +214,13 @@ func TestManager(t *testing.T) { "bigco.net", "3.3.3.3:53"), SearchDomains: strs("tailscale.com", "universe.tf"), }, + bs: OSConfig{ + Nameservers: mustIPs("8.8.8.8"), + SearchDomains: strs("coffee.shop"), + }, os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), - SearchDomains: strs("tailscale.com", "universe.tf"), + SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"), }, rs: resolver.Config{ Routes: upstreams( @@ -232,7 +241,7 @@ func TestManager(t *testing.T) { os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), SearchDomains: strs("tailscale.com", "universe.tf"), - MatchDomains: strs("corp.com", "bigco.net"), + MatchDomains: strs("bigco.net", "corp.com"), }, rs: resolver.Config{ Routes: upstreams( @@ -249,9 +258,13 @@ func TestManager(t *testing.T) { AuthoritativeSuffixes: strs("ts.com"), SearchDomains: strs("tailscale.com", "universe.tf"), }, + bs: OSConfig{ + Nameservers: mustIPs("8.8.8.8"), + SearchDomains: strs("coffee.shop"), + }, os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), - SearchDomains: strs("tailscale.com", "universe.tf"), + SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"), }, rs: resolver.Config{ Routes: upstreams(".", "8.8.8.8:53"), @@ -293,9 +306,13 @@ func TestManager(t *testing.T) { AuthoritativeSuffixes: strs("ts.com"), SearchDomains: strs("tailscale.com", "universe.tf"), }, + bs: OSConfig{ + Nameservers: mustIPs("8.8.8.8"), + SearchDomains: strs("coffee.shop"), + }, os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), - SearchDomains: strs("tailscale.com", "universe.tf"), + SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"), }, rs: resolver.Config{ Routes: upstreams( @@ -321,7 +338,7 @@ func TestManager(t *testing.T) { os: OSConfig{ Nameservers: mustIPs("100.100.100.100"), SearchDomains: strs("tailscale.com", "universe.tf"), - MatchDomains: strs("ts.com", "corp.com"), + MatchDomains: strs("corp.com", "ts.com"), }, rs: resolver.Config{ Routes: upstreams("corp.com.", "2.2.2.2:53"), @@ -335,7 +352,10 @@ func TestManager(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - f := fakeOSConfigurator{SplitDNS: test.split} + f := fakeOSConfigurator{ + SplitDNS: test.split, + BaseConfig: test.bs, + } m := NewManager(t.Logf, &f, nil) m.resolver.TestOnlySetHook(f.SetResolver)