diff --git a/client/internal/dns/host.go b/client/internal/dns/host.go index fa474afde92..2cd4b1d92d5 100644 --- a/client/internal/dns/host.go +++ b/client/internal/dns/host.go @@ -25,7 +25,7 @@ type hostManager interface { type SystemDNSSettings struct { Domains []string - ServerIP netip.Addr + ServerIPs []netip.Addr ServerPort int } diff --git a/client/internal/dns/host_darwin.go b/client/internal/dns/host_darwin.go index 820cf902921..0fb9f0deb79 100644 --- a/client/internal/dns/host_darwin.go +++ b/client/internal/dns/host_darwin.go @@ -85,9 +85,10 @@ func (s *systemConfigurator) applyDNSConfig(config HostDNSConfig, stateManager * searchDomains = append(searchDomains, strings.TrimSuffix(""+dConf.Domain, ".")) } + configServerIPs := []netip.Addr { config.ServerIP } matchKey := getKeyWithInput(netbirdDNSStateKeyFormat, matchSuffix) if len(matchDomains) != 0 { - err = s.addMatchDomains(matchKey, strings.Join(matchDomains, " "), config.ServerIP, config.ServerPort) + err = s.addMatchDomains(matchKey, strings.Join(matchDomains, " "), configServerIPs, config.ServerPort) } else { log.Infof("removing match domains from the system") err = s.removeKeyFromSystemConfig(matchKey) @@ -98,7 +99,7 @@ func (s *systemConfigurator) applyDNSConfig(config HostDNSConfig, stateManager * searchKey := getKeyWithInput(netbirdDNSStateKeyFormat, searchSuffix) if len(searchDomains) != 0 { - err = s.addSearchDomains(searchKey, strings.Join(searchDomains, " "), config.ServerIP, config.ServerPort) + err = s.addSearchDomains(searchKey, strings.Join(searchDomains, " "), configServerIPs, config.ServerPort) } else { log.Infof("removing search domains from the system") err = s.removeKeyFromSystemConfig(searchKey) @@ -165,14 +166,14 @@ func (s *systemConfigurator) removeKeyFromSystemConfig(key string) error { } func (s *systemConfigurator) addLocalDNS() error { - if !s.systemDNSSettings.ServerIP.IsValid() || len(s.systemDNSSettings.Domains) == 0 { + if len(s.systemDNSSettings.ServerIPs) == 0 || len(s.systemDNSSettings.Domains) == 0 { err := s.recordSystemDNSSettings(true) log.Errorf("Unable to get system DNS configuration") return err } localKey := getKeyWithInput(netbirdDNSStateKeyFormat, localSuffix) - if s.systemDNSSettings.ServerIP.IsValid() && len(s.systemDNSSettings.Domains) != 0 { - err := s.addSearchDomains(localKey, strings.Join(s.systemDNSSettings.Domains, " "), s.systemDNSSettings.ServerIP, s.systemDNSSettings.ServerPort) + if len(s.systemDNSSettings.Domains) != 0 { + err := s.addSearchDomains(localKey, strings.Join(s.systemDNSSettings.Domains, " "), s.systemDNSSettings.ServerIPs, s.systemDNSSettings.ServerPort) if err != nil { return fmt.Errorf("couldn't add local network DNS conf: %w", err) } @@ -184,7 +185,7 @@ func (s *systemConfigurator) addLocalDNS() error { } func (s *systemConfigurator) recordSystemDNSSettings(force bool) error { - if s.systemDNSSettings.ServerIP.IsValid() && len(s.systemDNSSettings.Domains) != 0 && !force { + if len(s.systemDNSSettings.ServerIPs) >= 1 && len(s.systemDNSSettings.Domains) != 0 && !force { return nil } @@ -212,6 +213,7 @@ func (s *systemConfigurator) getSystemDNSSettings() (SystemDNSSettings, error) { } var dnsSettings SystemDNSSettings + localDomains := make(map[string]struct{}) inSearchDomainsArray := false inServerAddressesArray := false @@ -221,7 +223,8 @@ func (s *systemConfigurator) getSystemDNSSettings() (SystemDNSSettings, error) { switch { case strings.HasPrefix(line, "DomainName :"): domainName := strings.TrimSpace(strings.Split(line, ":")[1]) - dnsSettings.Domains = append(dnsSettings.Domains, domainName) + localDomains[domainName] = struct{}{} + case line == "SearchDomains : {": inSearchDomainsArray = true continue @@ -235,11 +238,13 @@ func (s *systemConfigurator) getSystemDNSSettings() (SystemDNSSettings, error) { if inSearchDomainsArray { searchDomain := strings.Split(line, " : ")[1] - dnsSettings.Domains = append(dnsSettings.Domains, searchDomain) + localDomains[string(searchDomain)] = struct{}{} } else if inServerAddressesArray { address := strings.Split(line, " : ")[1] if ip, err := netip.ParseAddr(address); err == nil && ip.Is4() { - dnsSettings.ServerIP = ip + if ip.IsValid() { + dnsSettings.ServerIPs = append(dnsSettings.ServerIPs, ip) + } inServerAddressesArray = false // Stop reading after finding the first IPv4 address } } @@ -249,14 +254,19 @@ func (s *systemConfigurator) getSystemDNSSettings() (SystemDNSSettings, error) { return dnsSettings, err } + dnsSettings.Domains = make([]string, 0, len(localDomains)) + for k := range localDomains { + dnsSettings.Domains = append(dnsSettings.Domains, k) + } + // default to 53 port dnsSettings.ServerPort = defaultPort return dnsSettings, nil } -func (s *systemConfigurator) addSearchDomains(key, domains string, ip netip.Addr, port int) error { - err := s.addDNSState(key, domains, ip, port, true) +func (s *systemConfigurator) addSearchDomains(key, domains string, ips []netip.Addr, port int) error { + err := s.addDNSState(key, domains, ips, port, true) if err != nil { return fmt.Errorf("add dns state: %w", err) } @@ -268,8 +278,8 @@ func (s *systemConfigurator) addSearchDomains(key, domains string, ip netip.Addr return nil } -func (s *systemConfigurator) addMatchDomains(key, domains string, dnsServer netip.Addr, port int) error { - err := s.addDNSState(key, domains, dnsServer, port, false) +func (s *systemConfigurator) addMatchDomains(key, domains string, dnsServers []netip.Addr, port int) error { + err := s.addDNSState(key, domains, dnsServers, port, false) if err != nil { return fmt.Errorf("add dns state: %w", err) } @@ -281,14 +291,19 @@ func (s *systemConfigurator) addMatchDomains(key, domains string, dnsServer neti return nil } -func (s *systemConfigurator) addDNSState(state, domains string, dnsServer netip.Addr, port int, enableSearch bool) error { +func (s *systemConfigurator) addDNSState(state, domains string, dnsServers []netip.Addr, port int, enableSearch bool) error { noSearch := "1" if enableSearch { noSearch = "0" } + + serversStr := "" + for _, serverIP := range dnsServers { + serversStr = serversStr + serverIP.String() + " " + } lines := buildAddCommandLine(keySupplementalMatchDomains, arraySymbol+domains) lines += buildAddCommandLine(keySupplementalMatchDomainsNoSearch, digitSymbol+noSearch) - lines += buildAddCommandLine(keyServerAddresses, arraySymbol+dnsServer.String()) + lines += buildAddCommandLine(keyServerAddresses, arraySymbol+serversStr) lines += buildAddCommandLine(keyServerPort, digitSymbol+strconv.Itoa(port)) addDomainCommand := buildCreateStateWithOperation(state, lines)