mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 04:34:07 +09:00
mapper: send base_domain as the exit node filtered set
SaaS sends its own domains, which name nothing here. Otherwise an exit node proxies tailnet names, and where its OS resolver reaches MagicDNS a client reads its view of the tailnet. MagicDNS only: without it, base_domain can be public, and clients ask the exit node for its names. Reverse lookups stay open, as on SaaS. Updates #3626
This commit is contained in:
1 parent
ef6d033d19
commit
a7f2c85cfd
3 files changed
+38
-2
No files matched your search
@@ -135,6 +135,16 @@ func generateDNSConfig(
|
||||
dnsConfig.CertDomains = []string{domain}
|
||||
}
|
||||
|
||||
// An exit node refuses to proxy these names. Without this, where its OS
|
||||
// resolver reaches MagicDNS, a client allowed only to use the exit node can
|
||||
// read its view of the tailnet through it. Two gaps are deliberate. Without
|
||||
// MagicDNS, base_domain can be a public domain whose names clients ask the
|
||||
// exit node for, so node names stay readable. Reverse lookups stay open, as
|
||||
// on Tailscale SaaS.
|
||||
if dnsConfig.Proxied && cfg.BaseDomain != "" {
|
||||
dnsConfig.ExitNodeFilteredSet = []string{"." + strings.ToLower(cfg.BaseDomain)}
|
||||
}
|
||||
|
||||
return dnsConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,34 @@ var iap = func(ipStr string) *netip.Addr {
|
||||
return &ip
|
||||
}
|
||||
|
||||
func TestExitNodeFilteredSet(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
magicDNS bool
|
||||
baseDomain string
|
||||
want []string
|
||||
}{
|
||||
{name: "magicdns", magicDNS: true, baseDomain: "Tail.Example.com", want: []string{".tail.example.com"}},
|
||||
{name: "no magicdns", magicDNS: false, baseDomain: "tail.example.com"},
|
||||
{name: "no base domain", magicDNS: true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := generateDNSConfig(
|
||||
&types.Config{
|
||||
BaseDomain: tt.baseDomain,
|
||||
TailcfgDNSConfig: &tailcfg.DNSConfig{Proxied: tt.magicDNS},
|
||||
},
|
||||
(&types.Node{}).View(),
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.Equal(t, tt.want, got.ExitNodeFilteredSet)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSConfigMapResponse(t *testing.T) {
|
||||
tests := []struct {
|
||||
magicDNS bool
|
||||
|
||||
@@ -144,8 +144,6 @@ var aclMapCompatTests = []string{
|
||||
var viaCompatSkipReasons = map[string]string{
|
||||
"tagged-self": "TAGGED_SELF_PROFILE: SaaS gives a tagged node a profile of its own, headscale the shared tagged-devices one",
|
||||
|
||||
"exit-node-filtered-set": "EXIT_NODE_FILTER_UNSET: headscale sends no ExitNodeFilteredSet, so an exit node proxies queries for the tailnet's own names; SaaS sends the suffixes those names sit under",
|
||||
|
||||
"routes-m1-wildcard-src-multi-range/m-odin1/peers": sameUserPeers,
|
||||
"routes-m1-wildcard-src-multi-range/m-odin2/peers": sameUserPeers,
|
||||
"routes-m2-member-partial-subnet/m-odin1/peers": sameUserPeers,
|
||||
|
||||
Reference in new issue
Block a user