From e129a67b1967eaa58277efd93a3258105c918b57 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Sun, 2 Jan 2022 16:02:57 +1100 Subject: [PATCH] Add control of recursion desired flag for DNS probes This defaults recursion desired to on to preserve existing behaviour, but allows it to be configured. Signed-off-by: David Leadbeater --- CONFIGURATION.md | 2 ++ config/config.go | 6 ++++-- prober/dns.go | 2 +- prober/dns_test.go | 45 ++++++++++++++++++++++++++++++++++---------- prober/utils_test.go | 2 +- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 5a8608e0..bd2b4161 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -189,6 +189,8 @@ query_name: [ query_type: | default = "ANY" ] [ query_class: | default = "IN" ] +[ recursion_desired: | default = true ] + # List of valid response codes. valid_rcodes: [ - ... | default = "NOERROR" ] diff --git a/config/config.go b/config/config.go index e36b47c9..46dbfb4b 100644 --- a/config/config.go +++ b/config/config.go @@ -82,6 +82,7 @@ var ( // DefaultDNSProbe set default value for DNSProbe DefaultDNSProbe = DNSProbe{ IPProtocolFallback: true, + RecursionDesired: true, } ) @@ -264,8 +265,9 @@ type DNSProbe struct { TransportProtocol string `yaml:"transport_protocol,omitempty"` QueryClass string `yaml:"query_class,omitempty"` // Defaults to IN. QueryName string `yaml:"query_name,omitempty"` - QueryType string `yaml:"query_type,omitempty"` // Defaults to ANY. - ValidRcodes []string `yaml:"valid_rcodes,omitempty"` // Defaults to NOERROR. + QueryType string `yaml:"query_type,omitempty"` // Defaults to ANY. + RecursionDesired bool `yaml:"recursion_desired,omitempty"` // Defaults to true. + ValidRcodes []string `yaml:"valid_rcodes,omitempty"` // Defaults to NOERROR. ValidateAnswer DNSRRValidator `yaml:"validate_answer_rrs,omitempty"` ValidateAuthority DNSRRValidator `yaml:"validate_authority_rrs,omitempty"` ValidateAdditional DNSRRValidator `yaml:"validate_additional_rrs,omitempty"` diff --git a/prober/dns.go b/prober/dns.go index d3463e2e..130a9cb5 100644 --- a/prober/dns.go +++ b/prober/dns.go @@ -250,7 +250,7 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry msg := new(dns.Msg) msg.Id = dns.Id() - msg.RecursionDesired = true + msg.RecursionDesired = module.DNS.RecursionDesired msg.Question = make([]dns.Question, 1) msg.Question[0] = dns.Question{dns.Fqdn(module.DNS.QueryName), qt, qc} diff --git a/prober/dns_test.go b/prober/dns_test.go index 1d313d66..38ee38ac 100644 --- a/prober/dns_test.go +++ b/prober/dns_test.go @@ -69,16 +69,20 @@ func startDNSServer(protocol string, handler func(dns.ResponseWriter, *dns.Msg)) func recursiveDNSHandler(w dns.ResponseWriter, r *dns.Msg) { m := new(dns.Msg) m.SetReply(r) - answers := []string{ - "example.com. 3600 IN A 127.0.0.1", - "example.com. 3600 IN A 127.0.0.2", - } - for _, rr := range answers { - a, err := dns.NewRR(rr) - if err != nil { - panic(err) + if !r.RecursionDesired { + m.Rcode = dns.RcodeRefused + } else { + answers := []string{ + "example.com. 3600 IN A 127.0.0.1", + "example.com. 3600 IN A 127.0.0.2", + } + for _, rr := range answers { + a, err := dns.NewRR(rr) + if err != nil { + panic(err) + } + m.Answer = append(m.Answer, a) } - m.Answer = append(m.Answer, a) } if err := w.WriteMsg(m); err != nil { panic(err) @@ -99,6 +103,7 @@ func TestRecursiveDNSResponse(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, }, true, }, { @@ -106,6 +111,7 @@ func TestRecursiveDNSResponse(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, ValidRcodes: []string{"SERVFAIL", "NXDOMAIN"}, }, false, }, @@ -114,6 +120,7 @@ func TestRecursiveDNSResponse(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, ValidateAnswer: config.DNSRRValidator{ FailIfMatchesRegexp: []string{".*7200.*"}, FailIfNotMatchesRegexp: []string{".*3600.*"}, @@ -125,6 +132,7 @@ func TestRecursiveDNSResponse(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, ValidateAuthority: config.DNSRRValidator{ FailIfMatchesRegexp: []string{".*7200.*"}, }, @@ -135,11 +143,20 @@ func TestRecursiveDNSResponse(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, ValidateAdditional: config.DNSRRValidator{ FailIfNotMatchesRegexp: []string{".*3600.*"}, }, }, false, }, + { + config.DNSProbe{ + IPProtocol: "ip4", + IPProtocolFallback: true, + QueryName: "example.com", + RecursionDesired: false, + }, false, + }, } for _, protocol := range PROTOCOLS { @@ -166,6 +183,9 @@ func TestRecursiveDNSResponse(t *testing.T) { "probe_dns_authority_rrs": 0, "probe_dns_additional_rrs": 0, } + if !test.Probe.RecursionDesired { + expectedResults["probe_dns_answer_rrs"] = 0 + } checkRegistryResults(expectedResults, mfs, t) } } @@ -474,6 +494,7 @@ func TestDNSProtocol(t *testing.T) { QueryName: "example.com", TransportProtocol: protocol, IPProtocol: "ip6", + RecursionDesired: true, }, } registry := prometheus.NewRegistry() @@ -497,6 +518,7 @@ func TestDNSProtocol(t *testing.T) { Timeout: time.Second, DNS: config.DNSProbe{ QueryName: "example.com", + RecursionDesired: true, TransportProtocol: protocol, IPProtocol: "ip4", }, @@ -523,6 +545,7 @@ func TestDNSProtocol(t *testing.T) { Timeout: time.Second, DNS: config.DNSProbe{ QueryName: "example.com", + RecursionDesired: true, TransportProtocol: protocol, }, } @@ -547,7 +570,8 @@ func TestDNSProtocol(t *testing.T) { module = config.Module{ Timeout: time.Second, DNS: config.DNSProbe{ - QueryName: "example.com", + QueryName: "example.com", + RecursionDesired: true, }, } registry = prometheus.NewRegistry() @@ -590,6 +614,7 @@ func TestDNSMetrics(t *testing.T) { IPProtocol: "ip4", IPProtocolFallback: true, QueryName: "example.com", + RecursionDesired: true, }, } registry := prometheus.NewRegistry() diff --git a/prober/utils_test.go b/prober/utils_test.go index ed56baf4..0f51906d 100644 --- a/prober/utils_test.go +++ b/prober/utils_test.go @@ -162,7 +162,7 @@ func TestChooseProtocol(t *testing.T) { registry = prometheus.NewPedanticRegistry() ip, _, err = chooseProtocol(ctx, "ip4", false, "ipv6.google.com", registry, logger) - if err != nil && err.Error() != "address ipv6.google.com: no suitable address found" { + if err != nil && err.Error() != "address ipv6.google.com: no suitable address found" && err.Error() != "lookup ipv6.google.com: no such host" { t.Error(err) } else if err == nil { t.Error("should set error")