|
|
|
@ -11,6 +11,7 @@ import (
|
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
|
"inet.af/netaddr"
|
|
|
|
|
"tailscale.com/net/dns/resolver"
|
|
|
|
|
"tailscale.com/util/dnsname"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type fakeOSConfigurator struct {
|
|
|
|
@ -64,78 +65,78 @@ func TestManager(t *testing.T) {
|
|
|
|
|
{
|
|
|
|
|
name: "search-only",
|
|
|
|
|
in: Config{
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "corp",
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("1.1.1.1", "9.9.9.9"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "corp-split",
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("1.1.1.1", "9.9.9.9"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "corp-magic",
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(".", "1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "corp-magic-split",
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(".", "1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@ -143,11 +144,11 @@ func TestManager(t *testing.T) {
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
Routes: upstreams("corp.com", "2.2.2.2:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -160,12 +161,12 @@ func TestManager(t *testing.T) {
|
|
|
|
|
in: Config{
|
|
|
|
|
DefaultResolvers: mustIPPs("1.1.1.1:53", "9.9.9.9:53"),
|
|
|
|
|
Routes: upstreams("corp.com", "2.2.2.2:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -177,15 +178,15 @@ func TestManager(t *testing.T) {
|
|
|
|
|
name: "routes",
|
|
|
|
|
in: Config{
|
|
|
|
|
Routes: upstreams("corp.com", "2.2.2.2:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
bs: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("8.8.8.8"),
|
|
|
|
|
SearchDomains: strs("coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -197,13 +198,13 @@ func TestManager(t *testing.T) {
|
|
|
|
|
name: "routes-split",
|
|
|
|
|
in: Config{
|
|
|
|
|
Routes: upstreams("corp.com", "2.2.2.2:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("2.2.2.2"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: strs("corp.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: fqdns("corp.com"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@ -212,15 +213,15 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Routes: upstreams(
|
|
|
|
|
"corp.com", "2.2.2.2:53",
|
|
|
|
|
"bigco.net", "3.3.3.3:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
bs: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("8.8.8.8"),
|
|
|
|
|
SearchDomains: strs("coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -235,13 +236,13 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Routes: upstreams(
|
|
|
|
|
"corp.com", "2.2.2.2:53",
|
|
|
|
|
"bigco.net", "3.3.3.3:53"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: strs("bigco.net", "corp.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: fqdns("bigco.net", "corp.com"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -255,23 +256,23 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
bs: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("8.8.8.8"),
|
|
|
|
|
SearchDomains: strs("coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(".", "8.8.8.8:53"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@ -280,20 +281,20 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: strs("ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: fqdns("ts.com"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@ -303,16 +304,16 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
bs: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("8.8.8.8"),
|
|
|
|
|
SearchDomains: strs("coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf", "coffee.shop"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams(
|
|
|
|
@ -321,7 +322,7 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@ -331,21 +332,21 @@ func TestManager(t *testing.T) {
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
AuthoritativeSuffixes: strs("ts.com"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
AuthoritativeSuffixes: fqdns("ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
},
|
|
|
|
|
split: true,
|
|
|
|
|
os: OSConfig{
|
|
|
|
|
Nameservers: mustIPs("100.100.100.100"),
|
|
|
|
|
SearchDomains: strs("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: strs("corp.com", "ts.com"),
|
|
|
|
|
SearchDomains: fqdns("tailscale.com", "universe.tf"),
|
|
|
|
|
MatchDomains: fqdns("corp.com", "ts.com"),
|
|
|
|
|
},
|
|
|
|
|
rs: resolver.Config{
|
|
|
|
|
Routes: upstreams("corp.com.", "2.2.2.2:53"),
|
|
|
|
|
Hosts: hosts(
|
|
|
|
|
"dave.ts.com.", "1.2.3.4",
|
|
|
|
|
"bradfitz.ts.com.", "2.3.4.5"),
|
|
|
|
|
LocalDomains: strs("ts.com."),
|
|
|
|
|
LocalDomains: fqdns("ts.com."),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
@ -387,11 +388,20 @@ func mustIPPs(strs ...string) (ret []netaddr.IPPort) {
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func strs(strs ...string) []string { return strs }
|
|
|
|
|
func fqdns(strs ...string) (ret []dnsname.FQDN) {
|
|
|
|
|
for _, s := range strs {
|
|
|
|
|
fqdn, err := dnsname.ToFQDN(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
ret = append(ret, fqdn)
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func hosts(strs ...string) (ret map[string][]netaddr.IP) {
|
|
|
|
|
var key string
|
|
|
|
|
ret = map[string][]netaddr.IP{}
|
|
|
|
|
func hosts(strs ...string) (ret map[dnsname.FQDN][]netaddr.IP) {
|
|
|
|
|
var key dnsname.FQDN
|
|
|
|
|
ret = map[dnsname.FQDN][]netaddr.IP{}
|
|
|
|
|
for _, s := range strs {
|
|
|
|
|
if ip, err := netaddr.ParseIP(s); err == nil {
|
|
|
|
|
if key == "" {
|
|
|
|
@ -399,15 +409,19 @@ func hosts(strs ...string) (ret map[string][]netaddr.IP) {
|
|
|
|
|
}
|
|
|
|
|
ret[key] = append(ret[key], ip)
|
|
|
|
|
} else {
|
|
|
|
|
key = s
|
|
|
|
|
fqdn, err := dnsname.ToFQDN(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
key = fqdn
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func upstreams(strs ...string) (ret map[string][]netaddr.IPPort) {
|
|
|
|
|
var key string
|
|
|
|
|
ret = map[string][]netaddr.IPPort{}
|
|
|
|
|
func upstreams(strs ...string) (ret map[dnsname.FQDN][]netaddr.IPPort) {
|
|
|
|
|
var key dnsname.FQDN
|
|
|
|
|
ret = map[dnsname.FQDN][]netaddr.IPPort{}
|
|
|
|
|
for _, s := range strs {
|
|
|
|
|
if ipp, err := netaddr.ParseIPPort(s); err == nil {
|
|
|
|
|
if key == "" {
|
|
|
|
@ -415,7 +429,11 @@ func upstreams(strs ...string) (ret map[string][]netaddr.IPPort) {
|
|
|
|
|
}
|
|
|
|
|
ret[key] = append(ret[key], ipp)
|
|
|
|
|
} else {
|
|
|
|
|
key = s
|
|
|
|
|
fqdn, err := dnsname.ToFQDN(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
key = fqdn
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|