feat: add support for search domains in dns config

This commit is contained in:
Johan Siebens
2024-02-07 07:59:19 +01:00
parent 5d1ac326ea
commit 128ed22bde
6 changed files with 91 additions and 91 deletions
+45 -58
View File
@@ -26,35 +26,7 @@ func getDNSConfigCommand() *cobra.Command {
} }
config := resp.Msg.Config config := resp.Msg.Config
w := new(tabwriter.Writer) printDnsConfig(config)
w.Init(os.Stdout, 8, 8, 1, '\t', 0)
defer w.Flush()
fmt.Fprintf(w, "%s\t\t%v\n", "MagicDNS", config.MagicDns)
fmt.Fprintf(w, "%s\t\t%v\n", "HTTPS Certs", config.HttpsCerts)
fmt.Fprintf(w, "%s\t\t%v\n", "Override Local DNS", config.OverrideLocalDns)
if config.MagicDns {
fmt.Fprintf(w, "MagicDNS\t%s\t%s\n", config.MagicDnsSuffix, "100.100.100.100")
}
for k, r := range config.Routes {
for i, t := range r.Routes {
if i == 0 {
fmt.Fprintf(w, "SplitDNS\t%s\t%s\n", k, t)
} else {
fmt.Fprintf(w, "%s\t%s\n", "", t)
}
}
}
for i, t := range config.Nameservers {
if i == 0 {
fmt.Fprintf(w, "%s\t%s\t%s\n", "Global", "", t)
} else {
fmt.Fprintf(w, "%s\t%s\t%s\n", "", "", t)
}
}
return nil return nil
} }
@@ -73,11 +45,13 @@ func setDNSConfigCommand() *cobra.Command {
var magicDNS bool var magicDNS bool
var httpsCerts bool var httpsCerts bool
var overrideLocalDNS bool var overrideLocalDNS bool
var searchDomains []string
command.Flags().StringSliceVarP(&nameservers, "nameserver", "", []string{}, "Machines on your network will use these nameservers to resolve DNS queries.") command.Flags().StringSliceVarP(&nameservers, "nameserver", "", []string{}, "Machines on your network will use these nameservers to resolve DNS queries.")
command.Flags().BoolVarP(&magicDNS, "magic-dns", "", false, "Enable MagicDNS for the specified Tailnet") command.Flags().BoolVarP(&magicDNS, "magic-dns", "", false, "Enable MagicDNS for the specified Tailnet")
command.Flags().BoolVarP(&httpsCerts, "https-certs", "", false, "Enable HTTPS Certificates for the specified Tailnet") command.Flags().BoolVarP(&httpsCerts, "https-certs", "", false, "Enable HTTPS Certificates for the specified Tailnet")
command.Flags().BoolVarP(&overrideLocalDNS, "override-local-dns", "", false, "When enabled, connected clients ignore local DNS settings and always use the nameservers specified for this Tailnet") command.Flags().BoolVarP(&overrideLocalDNS, "override-local-dns", "", false, "When enabled, connected clients ignore local DNS settings and always use the nameservers specified for this Tailnet")
command.Flags().StringSliceVarP(&searchDomains, "search-domain", "", []string{}, "Custom DNS search domains.")
command.RunE = func(cmd *cobra.Command, args []string) error { command.RunE = func(cmd *cobra.Command, args []string) error {
var globalNameservers []string var globalNameservers []string
@@ -105,6 +79,7 @@ func setDNSConfigCommand() *cobra.Command {
Nameservers: globalNameservers, Nameservers: globalNameservers,
Routes: routes, Routes: routes,
HttpsCerts: httpsCerts, HttpsCerts: httpsCerts,
SearchDomains: searchDomains,
}, },
} }
resp, err := tc.Client().SetDNSConfig(cmd.Context(), connect.NewRequest(&req)) resp, err := tc.Client().SetDNSConfig(cmd.Context(), connect.NewRequest(&req))
@@ -120,38 +95,50 @@ func setDNSConfigCommand() *cobra.Command {
fmt.Println() fmt.Println()
} }
w := new(tabwriter.Writer) printDnsConfig(config)
w.Init(os.Stdout, 8, 8, 1, '\t', 0)
defer w.Flush()
fmt.Fprintf(w, "%s\t\t%v\n", "MagicDNS", config.MagicDns)
fmt.Fprintf(w, "%s\t\t%v\n", "HTTPS Certs", config.HttpsCerts)
fmt.Fprintf(w, "%s\t\t%v\n", "Override Local DNS", config.OverrideLocalDns)
if config.MagicDns {
fmt.Fprintf(w, "MagicDNS\t%s\t%s\n", config.MagicDnsSuffix, "100.100.100.100")
}
for k, r := range config.Routes {
for i, t := range r.Routes {
if i == 0 {
fmt.Fprintf(w, "SplitDNS\t%s\t%s\n", k, t)
} else {
fmt.Fprintf(w, "%s\t%s\n", "", t)
}
}
}
for i, t := range config.Nameservers {
if i == 0 {
fmt.Fprintf(w, "%s\t%s\t%s\n", "Global", "", t)
} else {
fmt.Fprintf(w, "%s\t%s\t%s\n", "", "", t)
}
}
return nil return nil
} }
return command return command
} }
func printDnsConfig(config *api.DNSConfig) {
w := new(tabwriter.Writer)
w.Init(os.Stdout, 8, 8, 1, '\t', 0)
defer w.Flush()
fmt.Fprintf(w, "%s\t\t%v\n", "MagicDNS", config.MagicDns)
fmt.Fprintf(w, "%s\t\t%v\n", "HTTPS Certs", config.HttpsCerts)
fmt.Fprintf(w, "%s\t\t%v\n", "Override Local DNS", config.OverrideLocalDns)
if config.MagicDns {
fmt.Fprintf(w, "MagicDNS\t%s\t%s\n", config.MagicDnsSuffix, "100.100.100.100")
}
for k, r := range config.Routes {
for i, t := range r.Routes {
if i == 0 {
fmt.Fprintf(w, "SplitDNS\t%s\t%s\n", k, t)
} else {
fmt.Fprintf(w, "%s\t%s\n", "", t)
}
}
}
for i, t := range config.Nameservers {
if i == 0 {
fmt.Fprintf(w, "%s\t%s\t%s\n", "Global", "", t)
} else {
fmt.Fprintf(w, "%s\t%s\t%s\n", "", "", t)
}
}
for i, t := range config.SearchDomains {
if i == 0 {
fmt.Fprintf(w, "%s\t%s\t%s\n", "Search Domains", t, "")
} else {
fmt.Fprintf(w, "%s\t%s\t%s\n", "", t, "")
}
}
}
+1
View File
@@ -14,6 +14,7 @@ type DNSConfig struct {
OverrideLocalDNS bool `json:"override_local_dns"` OverrideLocalDNS bool `json:"override_local_dns"`
Nameservers []string `json:"nameservers"` Nameservers []string `json:"nameservers"`
Routes map[string][]string `json:"routes"` Routes map[string][]string `json:"routes"`
SearchDomains []string `json:"search_domains"`
} }
func (i *DNSConfig) Scan(destination interface{}) error { func (i *DNSConfig) Scan(destination interface{}) error {
+13 -12
View File
@@ -34,20 +34,20 @@ func ToDNSConfig(m *domain.Machine, tailnet *domain.Tailnet, c *domain.DNSConfig
sanitizeTailnetName := domain.SanitizeTailnetName(tailnet.Name) sanitizeTailnetName := domain.SanitizeTailnetName(tailnet.Name)
tailnetDomain := fmt.Sprintf("%s.%s", sanitizeTailnetName, config.MagicDNSSuffix()) tailnetDomain := fmt.Sprintf("%s.%s", sanitizeTailnetName, config.MagicDNSSuffix())
resolvers := []*dnstype.Resolver{} resolvers := make([]*dnstype.Resolver, 0)
for _, r := range c.Nameservers { for _, r := range c.Nameservers {
resolver := &dnstype.Resolver{ resolvers = append(resolvers, &dnstype.Resolver{Addr: r})
Addr: r,
}
resolvers = append(resolvers, resolver)
} }
dnsConfig := &tailcfg.DNSConfig{} dnsConfig := &tailcfg.DNSConfig{}
var routes = make(map[string][]*dnstype.Resolver)
var domains []string var domains []string
var certDomains []string var certDomains []string
if c.MagicDNS { if c.MagicDNS {
routes[tailnetDomain] = nil
domains = append(domains, tailnetDomain) domains = append(domains, tailnetDomain)
dnsConfig.Proxied = true dnsConfig.Proxied = true
@@ -63,23 +63,24 @@ func ToDNSConfig(m *domain.Machine, tailnet *domain.Tailnet, c *domain.DNSConfig
} }
if len(c.Routes) != 0 || certsEnabled { if len(c.Routes) != 0 || certsEnabled {
routes := make(map[string][]*dnstype.Resolver)
for r, s := range c.Routes { for r, s := range c.Routes {
routeResolver := []*dnstype.Resolver{} routeResolver := make([]*dnstype.Resolver, 0)
for _, addr := range s { for _, addr := range s {
resolver := &dnstype.Resolver{Addr: addr} routeResolver = append(routeResolver, &dnstype.Resolver{Addr: addr})
routeResolver = append(routeResolver, resolver)
} }
routes[r] = routeResolver routes[r] = routeResolver
domains = append(domains, r)
} }
dnsConfig.Routes = routes dnsConfig.Routes = routes
} }
dnsConfig.Domains = domains dnsConfig.Domains = append(domains, c.SearchDomains...)
dnsConfig.CertDomains = certDomains dnsConfig.CertDomains = certDomains
dnsConfig.ExitNodeFilteredSet = []string{
fmt.Sprintf(".%s", config.MagicDNSSuffix()),
}
return dnsConfig return dnsConfig
} }
+7 -7
View File
@@ -42,6 +42,10 @@ func (s *Service) SetDNSConfig(ctx context.Context, req *connect.Request[api.Set
return nil, connect.NewError(connect.CodeFailedPrecondition, fmt.Errorf("MagicDNS must be enabled when enabling HTTPS Certs")) return nil, connect.NewError(connect.CodeFailedPrecondition, fmt.Errorf("MagicDNS must be enabled when enabling HTTPS Certs"))
} }
if dnsConfig.HttpsCerts && s.dnsProvider != nil {
return nil, connect.NewError(connect.CodeFailedPrecondition, fmt.Errorf("A DNS provider must be configured when enabling HTTPS Certs"))
}
tailnet, err := s.repository.GetTailnet(ctx, req.Msg.TailnetId) tailnet, err := s.repository.GetTailnet(ctx, req.Msg.TailnetId)
if err != nil { if err != nil {
return nil, logError(err) return nil, logError(err)
@@ -50,13 +54,7 @@ func (s *Service) SetDNSConfig(ctx context.Context, req *connect.Request[api.Set
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("tailnet not found")) return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("tailnet not found"))
} }
tailnet.DNSConfig = domain.DNSConfig{ tailnet.DNSConfig = apiDNSConfigToDomainDNSConfig(req.Msg.Config)
MagicDNS: dnsConfig.MagicDns,
HttpsCertsEnabled: s.dnsProvider != nil && dnsConfig.HttpsCerts,
OverrideLocalDNS: dnsConfig.OverrideLocalDns,
Nameservers: dnsConfig.Nameservers,
Routes: apiRoutesToDomainRoutes(dnsConfig.Routes),
}
if err := s.repository.SaveTailnet(ctx, tailnet); err != nil { if err := s.repository.SaveTailnet(ctx, tailnet); err != nil {
return nil, logError(err) return nil, logError(err)
@@ -102,6 +100,7 @@ func apiDNSConfigToDomainDNSConfig(dnsConfig *api.DNSConfig) domain.DNSConfig {
OverrideLocalDNS: dnsConfig.OverrideLocalDns, OverrideLocalDNS: dnsConfig.OverrideLocalDns,
Nameservers: dnsConfig.Nameservers, Nameservers: dnsConfig.Nameservers,
Routes: apiRoutesToDomainRoutes(dnsConfig.Routes), Routes: apiRoutesToDomainRoutes(dnsConfig.Routes),
SearchDomains: dnsConfig.SearchDomains,
} }
} }
@@ -115,5 +114,6 @@ func domainDNSConfigToApiDNSConfig(tailnet *domain.Tailnet) *api.DNSConfig {
OverrideLocalDns: dnsConfig.OverrideLocalDNS, OverrideLocalDns: dnsConfig.OverrideLocalDNS,
Nameservers: dnsConfig.Nameservers, Nameservers: dnsConfig.Nameservers,
Routes: domainRoutesToApiRoutes(dnsConfig.Routes), Routes: domainRoutesToApiRoutes(dnsConfig.Routes),
SearchDomains: dnsConfig.SearchDomains,
} }
} }
+24 -14
View File
@@ -235,6 +235,7 @@ type DNSConfig struct {
Routes map[string]*Routes `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Routes map[string]*Routes `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
MagicDnsSuffix string `protobuf:"bytes,5,opt,name=magic_dns_suffix,json=magicDnsSuffix,proto3" json:"magic_dns_suffix,omitempty"` MagicDnsSuffix string `protobuf:"bytes,5,opt,name=magic_dns_suffix,json=magicDnsSuffix,proto3" json:"magic_dns_suffix,omitempty"`
HttpsCerts bool `protobuf:"varint,6,opt,name=https_certs,json=httpsCerts,proto3" json:"https_certs,omitempty"` HttpsCerts bool `protobuf:"varint,6,opt,name=https_certs,json=httpsCerts,proto3" json:"https_certs,omitempty"`
SearchDomains []string `protobuf:"bytes,7,rep,name=search_domains,json=searchDomains,proto3" json:"search_domains,omitempty"`
} }
func (x *DNSConfig) Reset() { func (x *DNSConfig) Reset() {
@@ -311,6 +312,13 @@ func (x *DNSConfig) GetHttpsCerts() bool {
return false return false
} }
func (x *DNSConfig) GetSearchDomains() []string {
if x != nil {
return x.SearchDomains
}
return nil
}
type Routes struct { type Routes struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -383,7 +391,7 @@ var file_ionscale_v1_dns_proto_rawDesc = []byte{
0x32, 0x16, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x32, 0x16, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xcf, 0x02, 0x0a, 0x09, 0x44, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xf6, 0x02, 0x0a, 0x09, 0x44,
0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x67, 0x69, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x67, 0x69,
0x63, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x67, 0x63, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x67,
0x69, 0x63, 0x44, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x69, 0x63, 0x44, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
@@ -399,19 +407,21 @@ var file_ionscale_v1_dns_proto_rawDesc = []byte{
0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x67, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x67,
0x69, 0x63, 0x44, 0x6e, 0x73, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x69, 0x63, 0x44, 0x6e, 0x73, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x68,
0x74, 0x74, 0x70, 0x73, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x74, 0x74, 0x70, 0x73, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x43, 0x65, 0x72, 0x74, 0x73, 0x1a, 0x4e, 0x0a, 0x0b, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x43, 0x65, 0x72, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x6d, 0x61,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x69, 0x69, 0x6e, 0x73, 0x1a, 0x4e, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x20, 0x0a, 0x06, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x3d, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x02, 0x38, 0x01, 0x22, 0x20, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a,
0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72,
0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e,
0x72, 0x6f, 0x74, 0x6f, 0x33, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
+1
View File
@@ -29,6 +29,7 @@ message DNSConfig {
map<string, Routes> routes = 4; map<string, Routes> routes = 4;
string magic_dns_suffix = 5; string magic_dns_suffix = 5;
bool https_certs = 6; bool https_certs = 6;
repeated string search_domains = 7;
} }
message Routes { message Routes {