Skip to content

Commit

Permalink
dnsforward: test doain specific upstreams
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Jul 28, 2022
1 parent 9a83ebf commit fd9ee82
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions internal/dnsforward/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,8 @@ func ValidateUpstreamsPrivate(upstreams []string, privateNets netutil.SubnetSet)
var protocols = []string{"udp://", "tcp://", "tls://", "https://", "sdns://", "quic://"}

func validateUpstream(u string, domains []string) (useDefault bool, err error) {
// Check if the user tries to specify upstream for domain.
useDefault = domains == nil

// The special server address '#' means that default server must be used.
if u == "#" && !useDefault {
if useDefault = u == "#" && domains != nil; useDefault {
return useDefault, nil
}

Expand Down Expand Up @@ -535,7 +532,7 @@ func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
RecursionDesired: true,
},
Question: []dns.Question{{
Name: "google-public-dns-a.google.com.",
Name: "test.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
}},
Expand All @@ -545,12 +542,8 @@ func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
reply, err = u.Exchange(req)
if err != nil {
return fmt.Errorf("couldn't communicate with upstream: %w", err)
}

if len(reply.Answer) != 1 {
return fmt.Errorf("wrong response")
} else if a, ok := reply.Answer[0].(*dns.A); !ok || !a.A.Equal(net.IP{8, 8, 8, 8}) {
return fmt.Errorf("wrong response")
} else if len(reply.Answer) != 0 {
return errors.Error("wrong response")
}

return nil
Expand All @@ -565,7 +558,7 @@ func checkPrivateUpstreamExc(u upstream.Upstream) (err error) {
RecursionDesired: true,
},
Question: []dns.Question{{
Name: "1.0.0.127.in-addr.arpa.",
Name: "in-addr.arpa.",
Qtype: dns.TypePTR,
Qclass: dns.ClassINET,
}},
Expand All @@ -578,6 +571,13 @@ func checkPrivateUpstreamExc(u upstream.Upstream) (err error) {
return nil
}

// domainSpecificTestError is a wrapper for errors returned by checkDNS to mark
// the tested upstream domain-specific and therefore consider its errors
// non-critical.
type domainSpecificTestError struct {
error
}

func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFunc) (err error) {
if IsCommentOrEmpty(input) {
return nil
Expand All @@ -592,7 +592,7 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
useDefault, err := validateUpstream(input, domains)
if err != nil {
return fmt.Errorf("wrong upstream format: %w", err)
} else if !useDefault {
} else if useDefault {
return nil
}

Expand All @@ -612,7 +612,12 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
}

if err = ef(u); err != nil {
return fmt.Errorf("upstream %q fails to exchange: %w", input, err)
err = fmt.Errorf("upstream %q fails to exchange: %w", input, err)
if domains != nil {
return domainSpecificTestError{error: err}
}

return err
}

log.Debug("upstream %s is ok", input)
Expand All @@ -638,6 +643,9 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Info("%v", err)
result[host] = err.Error()
if _, ok := err.(domainSpecificTestError); ok {
result[host] = fmt.Sprintf("WARNING: %s", result[host])
}

continue
}
Expand All @@ -653,6 +661,9 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
// above, we rewriting the error for it. These cases should be
// handled properly instead.
result[host] = err.Error()
if _, ok := err.(domainSpecificTestError); ok {
result[host] = fmt.Sprintf("WARNING: %s", result[host])
}

continue
}
Expand Down

0 comments on commit fd9ee82

Please sign in to comment.