2022-07-05 19:10:39 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
//
|
|
|
|
// DNS measurements
|
|
|
|
//
|
2021-02-02 12:05:47 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"sync"
|
2022-08-28 12:02:17 +02:00
|
|
|
"time"
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2022-01-07 18:33:37 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
2021-10-13 16:37:02 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
2022-06-02 00:50:55 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/tracex"
|
2021-02-02 12:05:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// newfailure is a convenience shortcut to save typing
|
2022-05-31 21:53:01 +02:00
|
|
|
var newfailure = tracex.NewFailure
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2022-07-05 19:10:39 +02:00
|
|
|
// ctrlDNSResult is the result of the DNS check performed by
|
2021-02-02 12:05:47 +01:00
|
|
|
// the Web Connectivity test helper.
|
2022-08-28 20:20:12 +02:00
|
|
|
type ctrlDNSResult = model.THDNSResult
|
2022-07-05 19:10:39 +02:00
|
|
|
|
|
|
|
// dnsConfig configures the DNS check.
|
|
|
|
type dnsConfig struct {
|
|
|
|
// Domain is the MANDATORY domain to resolve.
|
|
|
|
Domain string
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2022-07-05 19:10:39 +02:00
|
|
|
// NewResolver is the MANDATORY factory to create a new resolver.
|
2022-07-05 18:41:35 +02:00
|
|
|
NewResolver func() model.Resolver
|
2022-07-05 19:10:39 +02:00
|
|
|
|
|
|
|
// Out is the channel where we publish the results.
|
|
|
|
Out chan ctrlDNSResult
|
|
|
|
|
|
|
|
// Wg allows to synchronize with the parent.
|
|
|
|
Wg *sync.WaitGroup
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:10:39 +02:00
|
|
|
// dnsDo performs the DNS check.
|
|
|
|
func dnsDo(ctx context.Context, config *dnsConfig) {
|
2022-08-28 12:02:17 +02:00
|
|
|
const timeout = 4 * time.Second
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
|
|
|
defer cancel()
|
2021-02-02 12:05:47 +01:00
|
|
|
defer config.Wg.Done()
|
2022-07-05 18:41:35 +02:00
|
|
|
reso := config.NewResolver()
|
|
|
|
defer reso.CloseIdleConnections()
|
|
|
|
addrs, err := reso.LookupHost(ctx, config.Domain)
|
2021-09-27 08:13:30 +02:00
|
|
|
if addrs == nil {
|
|
|
|
addrs = []string{} // fix: the old test helper did that
|
|
|
|
}
|
2021-10-13 16:37:02 +02:00
|
|
|
failure := dnsMapFailure(newfailure(err))
|
2022-08-28 14:34:40 +02:00
|
|
|
config.Out <- ctrlDNSResult{
|
|
|
|
Failure: failure,
|
|
|
|
Addrs: addrs,
|
|
|
|
ASNs: []int64{}, // unused by the TH and not serialized
|
|
|
|
}
|
2021-10-13 16:37:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// dnsMapFailure attempts to map netxlite failures to the strings
|
|
|
|
// used by the original OONI test helper.
|
|
|
|
//
|
|
|
|
// See https://github.com/ooni/backend/blob/6ec4fda5b18/oonib/testhelpers/http_helpers.py#L430
|
|
|
|
func dnsMapFailure(failure *string) *string {
|
|
|
|
switch failure {
|
|
|
|
case nil:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
switch *failure {
|
|
|
|
case netxlite.FailureDNSNXDOMAINError:
|
|
|
|
// We have a name for this string because dnsanalysis.go is
|
|
|
|
// already checking for this specific error string.
|
2022-08-28 20:20:12 +02:00
|
|
|
s := model.THDNSNameError
|
2021-10-13 16:37:02 +02:00
|
|
|
return &s
|
2021-10-15 16:20:07 +02:00
|
|
|
case netxlite.FailureDNSNoAnswer:
|
|
|
|
// In this case the legacy TH would produce an empty
|
|
|
|
// reply that is not attached to any error.
|
|
|
|
//
|
|
|
|
// See https://github.com/ooni/probe/issues/1707#issuecomment-944322725
|
|
|
|
return nil
|
|
|
|
case netxlite.FailureDNSNonRecoverableFailure,
|
2021-10-13 16:37:02 +02:00
|
|
|
netxlite.FailureDNSRefusedError,
|
|
|
|
netxlite.FailureDNSServerMisbehaving,
|
|
|
|
netxlite.FailureDNSTemporaryFailure:
|
|
|
|
s := "dns_server_failure"
|
|
|
|
return &s
|
|
|
|
default:
|
|
|
|
s := "unknown_error"
|
|
|
|
return &s
|
|
|
|
}
|
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|