feat(netxlite): implement LookupHTTPS (#514)
This new API call performs DNS lookups for HTTPS records. 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:
parent
c6b69cbee8
commit
8b9fe1a160
13 changed files with 621 additions and 24 deletions
|
|
@ -7,10 +7,14 @@ import (
|
|||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/dnsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/errorsx"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
// HTTPSSvc is the type returned for HTTPSSvc queries.
|
||||
type HTTPSSvc = dnsx.HTTPSSvc
|
||||
|
||||
// Resolver performs domain name resolutions.
|
||||
type Resolver interface {
|
||||
// LookupHost behaves like net.Resolver.LookupHost.
|
||||
|
|
@ -24,8 +28,17 @@ type Resolver interface {
|
|||
|
||||
// CloseIdleConnections closes idle connections, if any.
|
||||
CloseIdleConnections()
|
||||
|
||||
// LookupHTTPS issues a single HTTPS query for
|
||||
// a domain without any retry mechanism whatsoever.
|
||||
LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error)
|
||||
}
|
||||
|
||||
// ErrNoDNSTransport indicates that the requested Resolver operation
|
||||
// cannot be performed because we're using the "system" resolver.
|
||||
var ErrNoDNSTransport = errors.New("operation requires a DNS transport")
|
||||
|
||||
// NewResolverStdlib creates a new Resolver by combining
|
||||
// WrapResolver with an internal "system" resolver type that
|
||||
// adds extra functionality to net.Resolver.
|
||||
|
|
@ -120,6 +133,11 @@ func (r *resolverSystem) CloseIdleConnections() {
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
func (r *resolverSystem) LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error) {
|
||||
return nil, ErrNoDNSTransport
|
||||
}
|
||||
|
||||
// resolverLogger is a resolver that emits events
|
||||
type resolverLogger struct {
|
||||
Resolver
|
||||
|
|
@ -142,6 +160,24 @@ func (r *resolverLogger) LookupHost(ctx context.Context, hostname string) ([]str
|
|||
return addrs, nil
|
||||
}
|
||||
|
||||
func (r *resolverLogger) LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error) {
|
||||
prefix := fmt.Sprintf("resolve[HTTPS] %s with %s (%s)", domain, r.Network(), r.Address())
|
||||
r.Logger.Debugf("%s...", prefix)
|
||||
start := time.Now()
|
||||
https, err := r.Resolver.LookupHTTPS(ctx, domain)
|
||||
elapsed := time.Since(start)
|
||||
if err != nil {
|
||||
r.Logger.Debugf("%s... %s in %s", prefix, err, elapsed)
|
||||
return nil, err
|
||||
}
|
||||
alpn := https.ALPN
|
||||
a := https.IPv4
|
||||
aaaa := https.IPv6
|
||||
r.Logger.Debugf("%s... %+v %+v %+v in %s", prefix, alpn, a, aaaa, elapsed)
|
||||
return https, nil
|
||||
}
|
||||
|
||||
// resolverIDNA supports resolving Internationalized Domain Names.
|
||||
//
|
||||
// See RFC3492 for more information.
|
||||
|
|
@ -157,6 +193,15 @@ func (r *resolverIDNA) LookupHost(ctx context.Context, hostname string) ([]strin
|
|||
return r.Resolver.LookupHost(ctx, host)
|
||||
}
|
||||
|
||||
func (r *resolverIDNA) LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error) {
|
||||
host, err := idna.ToASCII(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.Resolver.LookupHTTPS(ctx, host)
|
||||
}
|
||||
|
||||
// resolverShortCircuitIPAddr recognizes when the input hostname is an
|
||||
// IP address and returns it immediately to the caller.
|
||||
type resolverShortCircuitIPAddr struct {
|
||||
|
|
@ -193,6 +238,11 @@ func (r *nullResolver) CloseIdleConnections() {
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
func (r *nullResolver) LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error) {
|
||||
return nil, ErrNoResolver
|
||||
}
|
||||
|
||||
// resolverErrWrapper is a Resolver that knows about wrapping errors.
|
||||
type resolverErrWrapper struct {
|
||||
Resolver
|
||||
|
|
@ -208,3 +258,13 @@ func (r *resolverErrWrapper) LookupHost(ctx context.Context, hostname string) ([
|
|||
}
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
func (r *resolverErrWrapper) LookupHTTPS(
|
||||
ctx context.Context, domain string) (*HTTPSSvc, error) {
|
||||
out, err := r.Resolver.LookupHTTPS(ctx, domain)
|
||||
if err != nil {
|
||||
return nil, errorsx.NewErrWrapper(
|
||||
errorsx.ClassifyResolverError, errorsx.ResolveOperation, err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue