From 8bf6e12b8371d783d125cc0bd03cc476b1aa440b Mon Sep 17 00:00:00 2001 From: Artem Glazychev Date: Fri, 22 Jul 2022 17:21:55 +0700 Subject: [PATCH] dns: fix dnsutils (#1330) * dns: use upd instead of tcp Signed-off-by: Artem Glazychev * Add tcp Signed-off-by: Artem Glazychev * Fix cache chain element Signed-off-by: Artem Glazychev Signed-off-by: anastasia.malysheva --- pkg/tools/dnsutils/cache/gen.go | 4 ++-- pkg/tools/dnsutils/cache/handler.go | 16 +++++++++++----- .../dnsutils/cache/response_writer_wrapper.go | 2 +- pkg/tools/dnsutils/cache/sync_map.gen.go | 16 ++++++++-------- pkg/tools/dnsutils/connect/handler.go | 4 ++-- pkg/tools/dnsutils/dnsconfigs/handler.go | 9 ++++----- pkg/tools/dnsutils/dnsconfigs/handler_test.go | 5 ++++- pkg/tools/dnsutils/fanout/handler.go | 6 +++--- pkg/tools/dnsutils/noloop/handler.go | 2 +- pkg/tools/dnsutils/searches/handler.go | 2 +- 10 files changed, 37 insertions(+), 29 deletions(-) diff --git a/pkg/tools/dnsutils/cache/gen.go b/pkg/tools/dnsutils/cache/gen.go index 8cca2f3a5..19e4d40e0 100644 --- a/pkg/tools/dnsutils/cache/gen.go +++ b/pkg/tools/dnsutils/cache/gen.go @@ -18,8 +18,8 @@ package cache import "sync" -//go:generate go-syncmap -output sync_map.gen.go -type msgMap +//go:generate go-syncmap -output sync_map.gen.go -type msgMap -// msgMap is like a Go map[string]*dns.Msg but is safe for concurrent use +// msgMap is like a Go map[dns.Question]*dns.Msg but is safe for concurrent use // by multiple goroutines without additional locking or coordination type msgMap sync.Map diff --git a/pkg/tools/dnsutils/cache/handler.go b/pkg/tools/dnsutils/cache/handler.go index 644fb6607..da1032b7b 100644 --- a/pkg/tools/dnsutils/cache/handler.go +++ b/pkg/tools/dnsutils/cache/handler.go @@ -19,6 +19,7 @@ package cache import ( "context" + "sync" "time" "github.com/miekg/dns" @@ -29,24 +30,27 @@ import ( ) type dnsCacheHandler struct { - cache *msgMap + cache *msgMap + lastTTLUpdate time.Time + m sync.Mutex } func (h *dnsCacheHandler) ServeDNS(ctx context.Context, rw dns.ResponseWriter, m *dns.Msg) { h.updateTTL() - if v, ok := h.cache.Load(m.Question[0].Name); ok { + if val, ok := h.cache.Load(m.Question[0]); ok { + v := val.Copy() if validateMsg(v) { v.Id = m.Id if err := rw.WriteMsg(v); err != nil { - log.FromContext(ctx).Warnf("got an error during write the message: %v", err.Error()) + log.FromContext(ctx).WithField("dnsCacheHandler", "ServeDNS").Warnf("got an error during write the message: %v", err.Error()) dns.HandleFailed(rw, v) return } return } - h.cache.Delete(m.Question[0].Name) + h.cache.Delete(m.Question[0]) } wrapper := responseWriterWrapper{ @@ -59,13 +63,15 @@ func (h *dnsCacheHandler) ServeDNS(ctx context.Context, rw dns.ResponseWriter, m func (h *dnsCacheHandler) updateTTL() { now := time.Now() + h.m.Lock() + defer h.m.Unlock() diff := uint32(now.Sub(h.lastTTLUpdate).Seconds()) if diff == 0 { return } - h.cache.Range(func(key string, value *dns.Msg) bool { + h.cache.Range(func(key dns.Question, value *dns.Msg) bool { for i := range value.Answer { if value.Answer[i].Header().Ttl < diff { value.Answer[i].Header().Ttl = 0 diff --git a/pkg/tools/dnsutils/cache/response_writer_wrapper.go b/pkg/tools/dnsutils/cache/response_writer_wrapper.go index 9646ab7aa..d731e4b65 100644 --- a/pkg/tools/dnsutils/cache/response_writer_wrapper.go +++ b/pkg/tools/dnsutils/cache/response_writer_wrapper.go @@ -27,7 +27,7 @@ type responseWriterWrapper struct { func (r *responseWriterWrapper) WriteMsg(m *dns.Msg) error { if m != nil && m.Rcode == dns.RcodeSuccess { - r.cache.Store(m.Question[0].Name, m) + r.cache.Store(m.Question[0], m) } return r.ResponseWriter.WriteMsg(m) } diff --git a/pkg/tools/dnsutils/cache/sync_map.gen.go b/pkg/tools/dnsutils/cache/sync_map.gen.go index 01a69d1d1..34a919e36 100644 --- a/pkg/tools/dnsutils/cache/sync_map.gen.go +++ b/pkg/tools/dnsutils/cache/sync_map.gen.go @@ -1,4 +1,4 @@ -// Code generated by "-output sync_map.gen.go -type msgMap -output sync_map.gen.go -type msgMap"; DO NOT EDIT. +// Code generated by "-output sync_map.gen.go -type msgMap -output sync_map.gen.go -type msgMap"; DO NOT EDIT. package cache import ( @@ -19,7 +19,7 @@ var _nil_msgMap_dns_Msg_value = func() (val *dns.Msg) { return }() // Load returns the value stored in the map for a key, or nil if no // value is present. // The ok result indicates whether value was found in the map. -func (m *msgMap) Load(key string) (*dns.Msg, bool) { +func (m *msgMap) Load(key dns.Question) (*dns.Msg, bool) { value, ok := (*sync.Map)(m).Load(key) if value == nil { return _nil_msgMap_dns_Msg_value, ok @@ -28,14 +28,14 @@ func (m *msgMap) Load(key string) (*dns.Msg, bool) { } // Store sets the value for a key. -func (m *msgMap) Store(key string, value *dns.Msg) { +func (m *msgMap) Store(key dns.Question, value *dns.Msg) { (*sync.Map)(m).Store(key, value) } // LoadOrStore returns the existing value for the key if present. // Otherwise, it stores and returns the given value. // The loaded result is true if the value was loaded, false if stored. -func (m *msgMap) LoadOrStore(key string, value *dns.Msg) (*dns.Msg, bool) { +func (m *msgMap) LoadOrStore(key dns.Question, value *dns.Msg) (*dns.Msg, bool) { actual, loaded := (*sync.Map)(m).LoadOrStore(key, value) if actual == nil { return _nil_msgMap_dns_Msg_value, loaded @@ -45,7 +45,7 @@ func (m *msgMap) LoadOrStore(key string, value *dns.Msg) (*dns.Msg, bool) { // LoadAndDelete deletes the value for a key, returning the previous value if any. // The loaded result reports whether the key was present. -func (m *msgMap) LoadAndDelete(key string) (value *dns.Msg, loaded bool) { +func (m *msgMap) LoadAndDelete(key dns.Question) (value *dns.Msg, loaded bool) { actual, loaded := (*sync.Map)(m).LoadAndDelete(key) if actual == nil { return _nil_msgMap_dns_Msg_value, loaded @@ -54,7 +54,7 @@ func (m *msgMap) LoadAndDelete(key string) (value *dns.Msg, loaded bool) { } // Delete deletes the value for a key. -func (m *msgMap) Delete(key string) { +func (m *msgMap) Delete(key dns.Question) { (*sync.Map)(m).Delete(key) } @@ -68,8 +68,8 @@ func (m *msgMap) Delete(key string) { // // Range may be O(N) with the number of elements in the map even if f returns // false after a constant number of calls. -func (m *msgMap) Range(f func(key string, value *dns.Msg) bool) { +func (m *msgMap) Range(f func(key dns.Question, value *dns.Msg) bool) { (*sync.Map)(m).Range(func(key, value interface{}) bool { - return f(key.(string), value.(*dns.Msg)) + return f(key.(dns.Question), value.(*dns.Msg)) }) } diff --git a/pkg/tools/dnsutils/connect/handler.go b/pkg/tools/dnsutils/connect/handler.go index beaad4a68..907e815fd 100644 --- a/pkg/tools/dnsutils/connect/handler.go +++ b/pkg/tools/dnsutils/connect/handler.go @@ -44,13 +44,13 @@ func (c *connectDNSHandler) ServeDNS(ctx context.Context, rp dns.ResponseWriter, var resp, _, err = client.Exchange(msg, c.connectTO.Host) if err != nil { - log.FromContext(ctx).Warnf("got an error during exchanging: %v", err.Error()) + log.FromContext(ctx).WithField("connectDNSHandler", "ServeDNS").Warnf("got an error during exchanging: %v", err.Error()) dns.HandleFailed(rp, msg) return } if err = rp.WriteMsg(resp); err != nil { - log.FromContext(ctx).Warnf("got an error during write the message: %v", err.Error()) + log.FromContext(ctx).WithField("connectDNSHandler", "ServeDNS").Warnf("got an error during write the message: %v", err.Error()) dns.HandleFailed(rp, msg) return } diff --git a/pkg/tools/dnsutils/dnsconfigs/handler.go b/pkg/tools/dnsutils/dnsconfigs/handler.go index 275a01b8b..05c05d3fe 100644 --- a/pkg/tools/dnsutils/dnsconfigs/handler.go +++ b/pkg/tools/dnsutils/dnsconfigs/handler.go @@ -42,12 +42,11 @@ func (h *dnsConfigsHandler) ServeDNS(ctx context.Context, rp dns.ResponseWriter, h.configs.Range(func(key string, value []*networkservice.DNSConfig) bool { for _, conf := range value { - ips := make([]url.URL, len(conf.DnsServerIps)) - for i, ip := range conf.DnsServerIps { - ips[i] = url.URL{Scheme: "tcp", Host: ip} + for _, ip := range conf.DnsServerIps { + dnsIPs = append(dnsIPs, + url.URL{Scheme: "udp", Host: ip}, + url.URL{Scheme: "tcp", Host: ip}) } - - dnsIPs = append(dnsIPs, ips...) searchDomains = append(searchDomains, conf.SearchDomains...) } diff --git a/pkg/tools/dnsutils/dnsconfigs/handler_test.go b/pkg/tools/dnsutils/dnsconfigs/handler_test.go index da3eb0c07..8abd74fc8 100644 --- a/pkg/tools/dnsutils/dnsconfigs/handler_test.go +++ b/pkg/tools/dnsutils/dnsconfigs/handler_test.go @@ -86,8 +86,11 @@ func TestDNSConfigs(t *testing.T) { require.Contains(t, domains, "net") urls := check.URLs - require.Equal(t, len(urls), 3) + require.Equal(t, len(urls), 6) + require.Contains(t, urls, "udp://7.7.7.7") require.Contains(t, urls, "tcp://7.7.7.7") + require.Contains(t, urls, "udp://1.1.1.1") require.Contains(t, urls, "tcp://1.1.1.1") + require.Contains(t, urls, "udp://9.9.9.9") require.Contains(t, urls, "tcp://9.9.9.9") } diff --git a/pkg/tools/dnsutils/fanout/handler.go b/pkg/tools/dnsutils/fanout/handler.go index a598e7c30..4a01be8e6 100644 --- a/pkg/tools/dnsutils/fanout/handler.go +++ b/pkg/tools/dnsutils/fanout/handler.go @@ -43,7 +43,7 @@ func (h *fanoutHandler) ServeDNS(ctx context.Context, rw dns.ResponseWriter, msg timeout := time.Until(deadline) if len(connectTO) == 0 { - log.FromContext(ctx).Error("no urls to fanout") + log.FromContext(ctx).WithField("fanoutHandler", "ServeDNS").Error("no urls to fanout") dns.HandleFailed(rw, msg) return } @@ -62,7 +62,7 @@ func (h *fanoutHandler) ServeDNS(ctx context.Context, rw dns.ResponseWriter, msg var resp, _, err = client.Exchange(msg, address) if err != nil { - log.FromContext(ctx).Warnf("got an error during exchanging: %v", err.Error()) + log.FromContext(ctx).WithField("fanoutHandler", "ServeDNS").Warnf("got an error during exchanging with address %v: %v", address, err.Error()) responseCh <- nil return } @@ -79,7 +79,7 @@ func (h *fanoutHandler) ServeDNS(ctx context.Context, rw dns.ResponseWriter, msg } if err := rw.WriteMsg(resp); err != nil { - log.FromContext(ctx).Warnf("got an error during write the message: %v", err.Error()) + log.FromContext(ctx).WithField("fanoutHandler", "ServeDNS").Warnf("got an error during write the message: %v", err.Error()) dns.HandleFailed(rw, msg) return } diff --git a/pkg/tools/dnsutils/noloop/handler.go b/pkg/tools/dnsutils/noloop/handler.go index ceff25bb4..061831ab0 100644 --- a/pkg/tools/dnsutils/noloop/handler.go +++ b/pkg/tools/dnsutils/noloop/handler.go @@ -33,7 +33,7 @@ type noloopDNSHandler struct{ ids sync.Map } func (n *noloopDNSHandler) ServeDNS(ctx context.Context, rp dns.ResponseWriter, m *dns.Msg) { if _, loaded := n.ids.LoadOrStore(m.Id, struct{}{}); loaded { - log.FromContext(ctx).Errorf("loop is not allowed: query: %v", m.String()) + log.FromContext(ctx).WithField("noloopDNSHandler", "ServeDNS").Errorf("loop is not allowed: query: %v", m.String()) dns.HandleFailed(rp, m) return } diff --git a/pkg/tools/dnsutils/searches/handler.go b/pkg/tools/dnsutils/searches/handler.go index d61056be0..2ae7dcdff 100644 --- a/pkg/tools/dnsutils/searches/handler.go +++ b/pkg/tools/dnsutils/searches/handler.go @@ -59,7 +59,7 @@ func (h *searchDomainsHandler) ServeDNS(ctx context.Context, rw dns.ResponseWrit if resp != nil && resp.Rcode == dns.RcodeSuccess { resp.Question = m.Question if err := rw.WriteMsg(resp); err != nil { - log.FromContext(ctx).Warnf("got an error during write the message: %v", err.Error()) + log.FromContext(ctx).WithField("searchDomainsHandler", "ServeDNS").Warnf("got an error during write the message: %v", err.Error()) dns.HandleFailed(rw, resp) return }