mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-23 09:06:24 +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
@@ -35,6 +35,12 @@ type Resolver struct {
|
||||
//
|
||||
// As of 2022-09-08, BootstrapResolution is not yet used.
|
||||
BootstrapResolution []netip.Addr `json:",omitempty"`
|
||||
|
||||
// UseWithExitNode designates that this resolver should continue to be used when an
|
||||
// exit node is in use. Normally, DNS resolution is delegated to the exit node but
|
||||
// there are situations where it is preferable to still use a Split DNS server and/or
|
||||
// global DNS server instead of the exit node.
|
||||
UseWithExitNode bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// IPPort returns r.Addr as an IP address and port if either
|
||||
@@ -64,5 +70,7 @@ func (r *Resolver) Equal(other *Resolver) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
return r.Addr == other.Addr && slices.Equal(r.BootstrapResolution, other.BootstrapResolution)
|
||||
return r.Addr == other.Addr &&
|
||||
slices.Equal(r.BootstrapResolution, other.BootstrapResolution) &&
|
||||
r.UseWithExitNode == other.UseWithExitNode
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ func (src *Resolver) Clone() *Resolver {
|
||||
var _ResolverCloneNeedsRegeneration = Resolver(struct {
|
||||
Addr string
|
||||
BootstrapResolution []netip.Addr
|
||||
UseWithExitNode bool
|
||||
}{})
|
||||
|
||||
// Clone duplicates src into dst and reports whether it succeeded.
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestResolverEqual(t *testing.T) {
|
||||
fieldNames = append(fieldNames, field.Name)
|
||||
}
|
||||
sort.Strings(fieldNames)
|
||||
if !slices.Equal(fieldNames, []string{"Addr", "BootstrapResolution"}) {
|
||||
if !slices.Equal(fieldNames, []string{"Addr", "BootstrapResolution", "UseWithExitNode"}) {
|
||||
t.Errorf("Resolver fields changed; update test")
|
||||
}
|
||||
|
||||
@@ -68,6 +68,18 @@ func TestResolverEqual(t *testing.T) {
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "equal UseWithExitNode",
|
||||
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "not equal UseWithExitNode",
|
||||
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: false},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -88,10 +88,12 @@ func (v ResolverView) Addr() string { return v.ж.Addr }
|
||||
func (v ResolverView) BootstrapResolution() views.Slice[netip.Addr] {
|
||||
return views.SliceOf(v.ж.BootstrapResolution)
|
||||
}
|
||||
func (v ResolverView) UseWithExitNode() bool { return v.ж.UseWithExitNode }
|
||||
func (v ResolverView) Equal(v2 ResolverView) bool { return v.ж.Equal(v2.ж) }
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _ResolverViewNeedsRegeneration = Resolver(struct {
|
||||
Addr string
|
||||
BootstrapResolution []netip.Addr
|
||||
UseWithExitNode bool
|
||||
}{})
|
||||
|
||||
Reference in New Issue
Block a user