Add control of recursion desired flag for DNS probes
authorDavid Leadbeater <dgl@dgl.cx>
Sun, 2 Jan 2022 05:02:57 +0000 (16:02 +1100)
committerDavid Leadbeater <dgl@dgl.cx>
Sun, 2 Jan 2022 05:41:40 +0000 (16:41 +1100)
This defaults recursion desired to on to preserve existing behaviour,
but allows it to be configured.

Signed-off-by: David Leadbeater <dgl@dgl.cx>
CONFIGURATION.md
config/config.go
prober/dns.go
prober/dns_test.go
prober/utils_test.go

index 5a8608e06dffece0a90125fc7d8bfb17e17fce5d..bd2b4161c94ed18778440f8f37d0e057072c27e6 100644 (file)
@@ -189,6 +189,8 @@ query_name: <string>
 [ query_type: <string> | default = "ANY" ]
 [ query_class: <string> | default = "IN" ]
 
+[ recursion_desired: <boolean> | default = true ]
+
 # List of valid response codes.
 valid_rcodes:
   [ - <string> ... | default = "NOERROR" ]
index e36b47c9f86e45c436924c469b6937a57b13cb8c..46dbfb4bd98c46526b8bf495b270a706a1dc1b4c 100644 (file)
@@ -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"`
index d3463e2e168da225243cb3eb83faeda2e568e3fc..130a9cb53ad83c329b74982d6ff0549a17c97bcf 100644 (file)
@@ -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}
 
index 1d313d6643731104ee8b18f014fb0335471ddcd1..38ee38ac904ce2690b1aeac9a057209f1354c24d 100644 (file)
@@ -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()
index ed56baf41eb24649072ce591f705e44b17eba55e..0f51906dbb5274ef1c4b518ed0fbbd69f81f275d 100644 (file)
@@ -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")