From e8a6a8b00cf0509efe54985f03d3840dbd0f10e9 Mon Sep 17 00:00:00 2001 From: Ganesh Vernekar Date: Sat, 26 Jan 2019 17:11:59 +0530 Subject: [PATCH 1/3] Use miekg/dns for SRV lookup Signed-off-by: Ganesh Vernekar --- pkg/alertmanager/peers.go | 10 ++--- pkg/chunk/cache/memcached_client.go | 3 +- pkg/util/dns.go | 57 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 pkg/util/dns.go diff --git a/pkg/alertmanager/peers.go b/pkg/alertmanager/peers.go index 03a849d240..5005b5d3e2 100644 --- a/pkg/alertmanager/peers.go +++ b/pkg/alertmanager/peers.go @@ -1,11 +1,11 @@ package alertmanager import ( - "net" "time" "github.com/cortexproject/cortex/pkg/util" "github.com/go-kit/kit/log/level" + "github.com/miekg/dns" "github.com/prometheus/client_golang/prometheus" ) @@ -34,7 +34,7 @@ type srvDiscovery struct { service string hostname string pollInterval time.Duration - addresses chan []*net.SRV + addresses chan []*dns.SRV stop chan struct{} done chan struct{} @@ -46,7 +46,7 @@ func newSRVDiscovery(service, hostname string, pollInterval time.Duration) *srvD service: service, hostname: hostname, pollInterval: pollInterval, - addresses: make(chan []*net.SRV), + addresses: make(chan []*dns.SRV), stop: make(chan struct{}), done: make(chan struct{}), } @@ -61,8 +61,8 @@ func (s *srvDiscovery) Stop() { } func (s *srvDiscovery) updatePeers() { - var addrs []*net.SRV - _, addrs, err := net.LookupSRV(s.service, "tcp", s.hostname) + var addrs []*dns.SRV + addrs, err := util.LookupSRV(s.service, "tcp", s.hostname) srvRequests.Inc() if err != nil { srvRequestFailures.Inc() diff --git a/pkg/chunk/cache/memcached_client.go b/pkg/chunk/cache/memcached_client.go index d43fa93713..c670e46a7d 100644 --- a/pkg/chunk/cache/memcached_client.go +++ b/pkg/chunk/cache/memcached_client.go @@ -3,7 +3,6 @@ package cache import ( "flag" "fmt" - "net" "sort" "sync" "time" @@ -100,7 +99,7 @@ func (c *memcachedClient) updateLoop(updateInterval time.Duration) error { // updateMemcacheServers sets a memcache server list from SRV records. SRV // priority & weight are ignored. func (c *memcachedClient) updateMemcacheServers() error { - _, addrs, err := net.LookupSRV(c.service, "tcp", c.hostname) + addrs, err := util.LookupSRV(c.service, "tcp", c.hostname) if err != nil { return err } diff --git a/pkg/util/dns.go b/pkg/util/dns.go new file mode 100644 index 0000000000..021a46bfc3 --- /dev/null +++ b/pkg/util/dns.go @@ -0,0 +1,57 @@ +package util + +import ( + "fmt" + + "github.com/miekg/dns" +) + +const defaultResolvConf = "/etc/resolv.conf" + +// GetDefaultDNSServers returns the DNS servers from the default +// resolver configuration. +func GetDefaultDNSServers() ([]string, error) { + conf, err := dns.ClientConfigFromFile(defaultResolvConf) + if err != nil { + return nil, err + } + return conf.Servers, nil +} + +// LookupSRV tries to resolve an SRV query of the given service, proto and domain name. +// proto can be 'tcp' or udp'. +// The query will be of the form _service._proto.name. +func LookupSRV(service, proto, name string) ([]*dns.SRV, error) { + dnsServers, err := GetDefaultDNSServers() + if err != nil { + return nil, err + } + + msg := &dns.Msg{} + name = "_" + service + "._" + proto + "." + name + msg.SetQuestion(dns.Fqdn(name), dns.TypeSRV) + + var result []*dns.SRV + dnsResolved := false + for _, serverAddr := range dnsServers { + resMsg, err := dns.Exchange(msg, serverAddr) + if err != nil { + continue + } + dnsResolved = true + for _, ans := range resMsg.Ns { + if srvRecord, ok := ans.(*dns.SRV); ok { + result = append(result, srvRecord) + } + } + if len(result) > 0 { + return result, nil + } + } + + if !dnsResolved { + return result, fmt.Errorf("Couldn't resolve %s: No server responded", name) + } + + return result, nil +} From 93fc1279149848013fc2a1f5c2843621f29143c9 Mon Sep 17 00:00:00 2001 From: Ganesh Vernekar Date: Tue, 19 Feb 2019 14:42:53 +0530 Subject: [PATCH 2/3] Take SRV records from Msg.Answer instead of Msg.Ns Also use TCP for the DNS lookup Signed-off-by: Ganesh Vernekar --- Gopkg.lock | 1 + pkg/util/dns.go | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 833451eb67..107bbae2c6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1432,6 +1432,7 @@ "github.com/mattes/migrate/driver/postgres", "github.com/mattes/migrate/migrate", "github.com/mgutz/ansi", + "github.com/miekg/dns", "github.com/opentracing-contrib/go-grpc", "github.com/opentracing-contrib/go-stdlib/nethttp", "github.com/opentracing/opentracing-go", diff --git a/pkg/util/dns.go b/pkg/util/dns.go index 021a46bfc3..55a60a3c40 100644 --- a/pkg/util/dns.go +++ b/pkg/util/dns.go @@ -3,6 +3,7 @@ package util import ( "fmt" + "github.com/go-kit/kit/log/level" "github.com/miekg/dns" ) @@ -31,15 +32,19 @@ func LookupSRV(service, proto, name string) ([]*dns.SRV, error) { name = "_" + service + "._" + proto + "." + name msg.SetQuestion(dns.Fqdn(name), dns.TypeSRV) + client := dns.Client{ + Net: "tcp", + } var result []*dns.SRV dnsResolved := false for _, serverAddr := range dnsServers { - resMsg, err := dns.Exchange(msg, serverAddr) + resMsg, _, err := client.Exchange(msg, serverAddr) if err != nil { + level.Warn(Logger).Log("msg", "DNS exchange failed", "err", err) continue } dnsResolved = true - for _, ans := range resMsg.Ns { + for _, ans := range resMsg.Answer { if srvRecord, ok := ans.(*dns.SRV); ok { result = append(result, srvRecord) } From 64e3a6f4e4d0cf5695a4e5efbdb5cb03a730de46 Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Wed, 6 Mar 2019 13:37:53 +0530 Subject: [PATCH 3/3] Make sure server has port attached Also make sure that we check for search domains Revert the TCP lookup change and fallback to UDP Signed-off-by: Goutham Veeramachaneni --- pkg/util/dns.go | 63 ++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/pkg/util/dns.go b/pkg/util/dns.go index 55a60a3c40..04f8ef77e7 100644 --- a/pkg/util/dns.go +++ b/pkg/util/dns.go @@ -2,6 +2,7 @@ package util import ( "fmt" + "net" "github.com/go-kit/kit/log/level" "github.com/miekg/dns" @@ -9,54 +10,58 @@ import ( const defaultResolvConf = "/etc/resolv.conf" -// GetDefaultDNSServers returns the DNS servers from the default -// resolver configuration. -func GetDefaultDNSServers() ([]string, error) { - conf, err := dns.ClientConfigFromFile(defaultResolvConf) - if err != nil { - return nil, err +func getDefaultDNSServers(conf *dns.ClientConfig) []string { + servers := make([]string, 0, len(conf.Servers)) + for _, server := range conf.Servers { + servers = append(servers, net.JoinHostPort(server, conf.Port)) } - return conf.Servers, nil + + return servers } // LookupSRV tries to resolve an SRV query of the given service, proto and domain name. // proto can be 'tcp' or udp'. // The query will be of the form _service._proto.name. func LookupSRV(service, proto, name string) ([]*dns.SRV, error) { - dnsServers, err := GetDefaultDNSServers() + conf, err := dns.ClientConfigFromFile(defaultResolvConf) if err != nil { return nil, err } - msg := &dns.Msg{} + dnsServers := getDefaultDNSServers(conf) + name = "_" + service + "._" + proto + "." + name - msg.SetQuestion(dns.Fqdn(name), dns.TypeSRV) + names := conf.NameList(name) - client := dns.Client{ - Net: "tcp", - } - var result []*dns.SRV dnsResolved := false - for _, serverAddr := range dnsServers { - resMsg, _, err := client.Exchange(msg, serverAddr) - if err != nil { - level.Warn(Logger).Log("msg", "DNS exchange failed", "err", err) - continue - } - dnsResolved = true - for _, ans := range resMsg.Answer { - if srvRecord, ok := ans.(*dns.SRV); ok { - result = append(result, srvRecord) + client := dns.Client{} + + for _, name := range names { + msg := &dns.Msg{} + msg.SetQuestion(dns.Fqdn(name), dns.TypeSRV) + + var result []*dns.SRV + for _, serverAddr := range dnsServers { + resMsg, _, err := client.Exchange(msg, serverAddr) + if err != nil { + level.Warn(Logger).Log("msg", "DNS exchange failed", "err", err) + continue + } + dnsResolved = true + for _, ans := range resMsg.Answer { + if srvRecord, ok := ans.(*dns.SRV); ok { + result = append(result, srvRecord) + } + } + if len(result) > 0 { + return result, nil } - } - if len(result) > 0 { - return result, nil } } if !dnsResolved { - return result, fmt.Errorf("Couldn't resolve %s: No server responded", name) + return nil, fmt.Errorf("Couldn't resolve %s: No server responded", name) } - return result, nil + return nil, nil }