fix(netxlite/dns): more stricly mirror stdlib error strings (#513)

This diff attempts to modify the errors reported by our custom
resolver by matching more strings from the stdlib.

Part of https://github.com/ooni/probe/issues/1733 and diff has been
extracted from https://github.com/ooni/probe-cli/pull/506.
This commit is contained in:
Simone Basso 2021-09-27 16:48:46 +02:00 committed by GitHub
commit 24b230fd38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 177 additions and 52 deletions

View file

@ -84,12 +84,18 @@ func classifyWithStringSuffix(err error) string {
if strings.HasSuffix(s, "TLS handshake timeout") {
return FailureGenericTimeoutError
}
if strings.HasSuffix(s, "no such host") {
if strings.HasSuffix(s, DNSNoSuchHostSuffix) {
// This is dns_lookup_error in MK but such error is used as a
// generic "hey, the lookup failed" error. Instead, this error
// that we return here is significantly more specific.
return FailureDNSNXDOMAINError
}
if strings.HasSuffix(s, DNSServerMisbehavingSuffix) {
return FailureDNSServerMisbehaving
}
if strings.HasSuffix(s, DNSNoAnswerSuffix) {
return FailureDNSNoAnswer
}
if strings.HasSuffix(s, "use of closed network connection") {
return FailureConnectionAlreadyClosed
}
@ -223,6 +229,21 @@ func quicIsCertificateError(alert uint8) bool {
// filters for DNS bogons MUST use this error.
var ErrDNSBogon = errors.New("dns: detected bogon address")
// These strings are same as the standard library.
const (
DNSNoSuchHostSuffix = "no such host"
DNSServerMisbehavingSuffix = "server misbehaving"
DNSNoAnswerSuffix = "no answer from DNS server"
)
// These errors are returned by the decoder and/or the serial resolver.
var (
ErrOODNSNoSuchHost = fmt.Errorf("ooniresolver: %s", DNSNoSuchHostSuffix)
ErrOODNSRefused = errors.New("ooniresolver: refused")
ErrOODNSMisbehaving = fmt.Errorf("ooniresolver: %s", DNSServerMisbehavingSuffix)
ErrOODNSNoAnswer = fmt.Errorf("ooniresolver: %s", DNSNoAnswerSuffix)
)
// ClassifyResolverError maps an error occurred during a domain name
// resolution to the corresponding OONI failure string.
//
@ -239,6 +260,11 @@ func ClassifyResolverError(err error) string {
if errors.Is(err, ErrDNSBogon) {
return FailureDNSBogonError // not in MK
}
// Implementation note: we match errors that share the same
// string of the stdlib in the generic classifier.
if errors.Is(err, ErrOODNSRefused) {
return FailureDNSRefusedError // not in MK
}
return ClassifyGenericError(err)
}

View file

@ -77,6 +77,18 @@ func TestClassifyGenericError(t *testing.T) {
}
})
t.Run("for dns server misbehaving", func(t *testing.T) {
if ClassifyGenericError(errors.New("dns server misbehaving")) != FailureDNSServerMisbehaving {
t.Fatal("unexpected results")
}
})
t.Run("for no answer from DNS server", func(t *testing.T) {
if ClassifyGenericError(errors.New("no answer from DNS server")) != FailureDNSNoAnswer {
t.Fatal("unexpected results")
}
})
t.Run("for use of closed network connection", func(t *testing.T) {
err := errors.New("read tcp 10.0.2.15:56948->93.184.216.34:443: use of closed network connection")
if ClassifyGenericError(err) != FailureConnectionAlreadyClosed {
@ -251,6 +263,12 @@ func TestClassifyResolverError(t *testing.T) {
}
})
t.Run("for refused", func(t *testing.T) {
if ClassifyResolverError(ErrOODNSRefused) != FailureDNSRefusedError {
t.Fatal("unexpected result")
}
})
t.Run("for another kind of error", func(t *testing.T) {
if ClassifyResolverError(io.EOF) != FailureEOFError {
t.Fatal("unexpected result")

View file

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// Generated: 2021-09-27 14:20:26.411929 +0200 CEST m=+0.233208042
// Generated: 2021-09-27 15:57:58.500515 +0200 CEST m=+0.304199251
package errorsx
@ -50,6 +50,9 @@ const (
//
FailureDNSBogonError = "dns_bogon_error"
FailureDNSNXDOMAINError = "dns_nxdomain_error"
FailureDNSRefusedError = "dns_refused_error"
FailureDNSServerMisbehaving = "dns_server_misbehaving"
FailureDNSNoAnswer = "dns_no_answer"
FailureEOFError = "eof_error"
FailureGenericTimeoutError = "generic_timeout_error"
FailureQUICIncompatibleVersion = "quic_incompatible_version"
@ -94,6 +97,9 @@ var failuresMap = map[string]string{
"wrong_protocol_type": "wrong_protocol_type",
"dns_bogon_error": "dns_bogon_error",
"dns_nxdomain_error": "dns_nxdomain_error",
"dns_refused_error": "dns_refused_error",
"dns_server_misbehaving": "dns_server_misbehaving",
"dns_no_answer": "dns_no_answer",
"eof_error": "eof_error",
"generic_timeout_error": "generic_timeout_error",
"quic_incompatible_version": "quic_incompatible_version",

View file

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// Generated: 2021-09-27 14:20:26.459041 +0200 CEST m=+0.280321626
// Generated: 2021-09-27 15:57:58.553101 +0200 CEST m=+0.356786917
package errorsx

View file

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// Generated: 2021-09-27 14:20:26.179327 +0200 CEST m=+0.000601459
// Generated: 2021-09-27 15:57:58.197535 +0200 CEST m=+0.001212709
package errorsx

View file

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// Generated: 2021-09-27 14:20:26.380511 +0200 CEST m=+0.201789292
// Generated: 2021-09-27 15:57:58.455744 +0200 CEST m=+0.259427834
package errorsx

View file

@ -93,6 +93,9 @@ var Specs = []*ErrorSpec{
// we must write "DNS" rather than writing "dns".
NewLibraryError("DNS_bogon_error"),
NewLibraryError("DNS_NXDOMAIN_error"),
NewLibraryError("DNS_refused_error"),
NewLibraryError("DNS_server_misbehaving"),
NewLibraryError("DNS_no_answer"),
NewLibraryError("EOF_error"),
NewLibraryError("generic_timeout_error"),
NewLibraryError("QUIC_incompatible_version"),