mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-24 01:26:39 +00:00
types/dnstype, ipn/ipnlocal: allow other DNS resolvers with exit nodes
dnstype.Resolver adds a boolean UseWithExitNode that controls whether the resolver should be used in tailscale exit node contexts (not wireguard exit nodes). If UseWithExitNode resolvers are found, they are installed as the global resolvers. If no UseWithExitNode resolvers are found, the exit node resolver continues to be installed as the global resolver. Split DNS Routes referencing UseWithExitNode resolvers are also installed. Updates #8237 Fixes tailscale/corp#30906 Fixes tailscale/corp#30907 Signed-off-by: Michael Ben-Ami <mzb@tailscale.com>
This commit is contained in:
committed by
mzbenami
parent
b8c45a6a8f
commit
3f1851a6d9
@@ -2080,7 +2080,14 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
|
||||
wantRoutes map[dnsname.FQDN][]*dnstype.Resolver
|
||||
}
|
||||
|
||||
defaultResolvers := []*dnstype.Resolver{{Addr: "default.example.com"}}
|
||||
const tsUseWithExitNodeResolverAddr = "usewithexitnode.example.com"
|
||||
defaultResolvers := []*dnstype.Resolver{
|
||||
{Addr: "default.example.com"},
|
||||
}
|
||||
containsFlaggedResolvers := append([]*dnstype.Resolver{
|
||||
{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true},
|
||||
}, defaultResolvers...)
|
||||
|
||||
wgResolvers := []*dnstype.Resolver{{Addr: "wg.example.com"}}
|
||||
peers := []tailcfg.NodeView{
|
||||
(&tailcfg.Node{
|
||||
@@ -2099,9 +2106,33 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
|
||||
}).View(),
|
||||
}
|
||||
exitDOH := peerAPIBase(&netmap.NetworkMap{Peers: peers}, peers[0]) + "/dns-query"
|
||||
routes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
baseRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"route.example.com.": {{Addr: "route.example.com"}},
|
||||
}
|
||||
containsEmptyRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"route.example.com.": {{Addr: "route.example.com"}},
|
||||
"empty.example.com.": {},
|
||||
}
|
||||
containsFlaggedRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"route.example.com.": {{Addr: "route.example.com"}},
|
||||
"withexit.example.com.": {{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
}
|
||||
containsFlaggedAndEmptyRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"empty.example.com.": {},
|
||||
"route.example.com.": {{Addr: "route.example.com"}},
|
||||
"withexit.example.com.": {{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
}
|
||||
flaggedRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"withexit.example.com.": {{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
}
|
||||
emptyRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"empty.example.com.": {},
|
||||
}
|
||||
flaggedAndEmptyRoutes := map[dnsname.FQDN][]*dnstype.Resolver{
|
||||
"empty.example.com.": {},
|
||||
"withexit.example.com.": {{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
}
|
||||
|
||||
stringifyRoutes := func(routes map[dnsname.FQDN][]*dnstype.Resolver) map[string][]*dnstype.Resolver {
|
||||
if routes == nil {
|
||||
return nil
|
||||
@@ -2138,19 +2169,23 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: nil,
|
||||
},
|
||||
{
|
||||
name: "tsExit/noRoutes/flaggedResolverOnly",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Resolvers: containsFlaggedResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
wantRoutes: nil,
|
||||
},
|
||||
|
||||
// The following two cases may need to be revisited. For a shared-in
|
||||
// exit node split-DNS may effectively break, furthermore in the future
|
||||
// if different nodes observe different DNS configurations, even a
|
||||
// tailnet local exit node may present a different DNS configuration,
|
||||
// which may not meet expectations in some use cases.
|
||||
// In the case where a default resolver is set, the default resolver
|
||||
// should also perhaps take precedence also.
|
||||
// When at tailscale exit node is in use,
|
||||
// only routes that reference resolvers with the UseWithExitNode should be installed,
|
||||
// as well as routes with 0-length resolver lists, which should be installed in all cases.
|
||||
{
|
||||
name: "tsExit/routes/noResolver",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(routes)},
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(baseRoutes)},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: nil,
|
||||
},
|
||||
@@ -2158,10 +2193,58 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
|
||||
name: "tsExit/routes/defaultResolver",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(routes), Resolvers: defaultResolvers},
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(baseRoutes), Resolvers: defaultResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: nil,
|
||||
},
|
||||
{
|
||||
name: "tsExit/routes/flaggedResolverOnly",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(baseRoutes), Resolvers: containsFlaggedResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
wantRoutes: nil,
|
||||
},
|
||||
{
|
||||
name: "tsExit/flaggedRoutesOnly/defaultResolver",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(containsFlaggedRoutes), Resolvers: defaultResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: flaggedRoutes,
|
||||
},
|
||||
{
|
||||
name: "tsExit/flaggedRoutesOnly/flaggedResolverOnly",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(containsFlaggedRoutes), Resolvers: containsFlaggedResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
wantRoutes: flaggedRoutes,
|
||||
},
|
||||
{
|
||||
name: "tsExit/emptyRoutesOnly/defaultResolver",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(containsEmptyRoutes), Resolvers: defaultResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: emptyRoutes,
|
||||
},
|
||||
{
|
||||
name: "tsExit/flaggedAndEmptyRoutesOnly/defaultResolver",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(containsFlaggedAndEmptyRoutes), Resolvers: defaultResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: exitDOH}},
|
||||
wantRoutes: flaggedAndEmptyRoutes,
|
||||
},
|
||||
{
|
||||
name: "tsExit/flaggedAndEmptyRoutesOnly/flaggedResolverOnly",
|
||||
exitNode: "ts",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(containsFlaggedAndEmptyRoutes), Resolvers: containsFlaggedResolvers},
|
||||
wantDefaultResolvers: []*dnstype.Resolver{{Addr: tsUseWithExitNodeResolverAddr, UseWithExitNode: true}},
|
||||
wantRoutes: flaggedAndEmptyRoutes,
|
||||
},
|
||||
|
||||
// WireGuard exit nodes with DNS capabilities provide a "fallback" type
|
||||
// behavior, they have a lower precedence than a default resolver, but
|
||||
@@ -2187,17 +2270,17 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
|
||||
name: "wgExit/routes/defaultResolver",
|
||||
exitNode: "wg",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(routes), Resolvers: defaultResolvers},
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(baseRoutes), Resolvers: defaultResolvers},
|
||||
wantDefaultResolvers: defaultResolvers,
|
||||
wantRoutes: routes,
|
||||
wantRoutes: baseRoutes,
|
||||
},
|
||||
{
|
||||
name: "wgExit/routes/noResolver",
|
||||
exitNode: "wg",
|
||||
peers: peers,
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(routes)},
|
||||
dnsConfig: &tailcfg.DNSConfig{Routes: stringifyRoutes(baseRoutes)},
|
||||
wantDefaultResolvers: wgResolvers,
|
||||
wantRoutes: routes,
|
||||
wantRoutes: baseRoutes,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user