diff --git a/pkg/services/dns/dns.go b/pkg/services/dns/dns.go index aa9b862d..821ab30f 100644 --- a/pkg/services/dns/dns.go +++ b/pkg/services/dns/dns.go @@ -16,17 +16,17 @@ import ( ) type dnsHandler struct { - zones []types.Zone - zonesLock sync.RWMutex - udpClient *dns.Client - tcpClient *dns.Client - hostsFile *HostsFile - nameserver string + zones []types.Zone + zonesLock sync.RWMutex + udpClient *dns.Client + tcpClient *dns.Client + hostsFile *HostsFile + nameservers []string } func newDNSHandler(zones []types.Zone) (*dnsHandler, error) { - nameserver, port, err := getDNSHostAndPort() + nameservers, err := getDNSHostAndPort() if err != nil { return nil, err } @@ -37,11 +37,11 @@ func newDNSHandler(zones []types.Zone) (*dnsHandler, error) { } return &dnsHandler{ - zones: zones, - tcpClient: &dns.Client{Net: "tcp"}, - udpClient: &dns.Client{Net: "udp"}, - nameserver: net.JoinHostPort(nameserver, port), - hostsFile: hostsFile, + zones: zones, + tcpClient: &dns.Client{Net: "tcp"}, + udpClient: &dns.Client{Net: "udp"}, + nameservers: nameservers, + hostsFile: hostsFile, }, nil } @@ -145,15 +145,20 @@ func (h *dnsHandler) addAnswers(dnsClient *dns.Client, r *dns.Msg) *dns.Msg { return m } } - - r, _, err := dnsClient.Exchange(r, h.nameserver) - if err != nil { - log.Errorf("Error during DNS Exchange: %s", err) - m.Rcode = dns.RcodeNameError - return m + for _, nameserver := range h.nameservers { + msg := r.Copy() + r, _, err := dnsClient.Exchange(msg, nameserver) + // return first good answer + if err == nil { + return r + } else { + log.Debugf("Error during DNS Exchange: %s", err) + } } - return r + // return the error if none of configured nameservers has right answer + m.Rcode = dns.RcodeNameError + return m } type Server struct { diff --git a/pkg/services/dns/dns_config_unix.go b/pkg/services/dns/dns_config_unix.go index 32716240..bdb2ad87 100644 --- a/pkg/services/dns/dns_config_unix.go +++ b/pkg/services/dns/dns_config_unix.go @@ -3,16 +3,23 @@ package dns import ( + "net" + "github.com/miekg/dns" ) -func getDNSHostAndPort() (string, string, error) { +func getDNSHostAndPort() ([]string, error) { conf, err := dns.ClientConfigFromFile("/etc/resolv.conf") if err != nil { - return "", "", err + return []string{}, err } - // TODO: use all configured nameservers, instead just first one - nameserver := conf.Servers[0] - - return nameserver, conf.Port, nil + var hosts = make([]string, len(conf.Servers)) + for _, server := range conf.Servers { + dnsIp := net.ParseIP(server) + //add only ipv4 dns addresses + if dnsIp != nil && dnsIp.To4() != nil { + hosts = append(hosts, net.JoinHostPort(server, conf.Port)) + } + } + return hosts, nil } diff --git a/pkg/services/dns/dns_config_windows.go b/pkg/services/dns/dns_config_windows.go index 2644e065..ba4eea62 100644 --- a/pkg/services/dns/dns_config_windows.go +++ b/pkg/services/dns/dns_config_windows.go @@ -3,24 +3,22 @@ package dns import ( - "net/netip" - "strconv" + "net" qdmDns "github.com/qdm12/dns/v2/pkg/nameserver" ) -func getDNSHostAndPort() (string, string, error) { +func getDNSHostAndPort() ([]string, error) { nameservers := qdmDns.GetDNSServers() - var nameserver netip.AddrPort + var dnsServers = make([]string, 5) for _, n := range nameservers { - // return first non ipv6 nameserver + // return only ipv4 nameservers if n.Addr().Is4() { - nameserver = n - break + dnsServers = append(dnsServers, net.JoinHostPort(n.Addr().String(), n.Port())) } } - return nameserver.Addr().String(), strconv.Itoa(int(nameserver.Port())), nil + return dnsServers, nil }