feat(netxlite): implement DNSTransport wrapping (#776)

Acknowledge that transports MAY be used in isolation (i.e., outside
of a Resolver) and add support for wrapping.

Ensure that every factory that creates an unwrapped type is named
accordingly to hopefully ensure there are no surprises.

Implement DNSTransport wrapping and use a technique similar to the
one used by Dialer to customize the DNSTransport while constructing
more complex data types (e.g., a specific resolver).

Ensure that the stdlib resolver's own "getaddrinfo" transport (1)
is wrapped and (2) could be extended during construction.

This work is part of my ongoing effort to bring to this repository
websteps-illustrated changes relative to netxlite.

Ref issue: https://github.com/ooni/probe/issues/2096
This commit is contained in:
Simone Basso 2022-06-01 11:10:08 +02:00 committed by GitHub
commit 8f7e3803eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 369 additions and 91 deletions

View file

@ -264,20 +264,20 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
case "https":
config.TLSConfig.NextProtos = []string{"h2", "http/1.1"}
httpClient := &http.Client{Transport: NewHTTPTransport(config)}
var txp model.DNSTransport = netxlite.NewDNSOverHTTPSTransportWithHostOverride(
var txp model.DNSTransport = netxlite.NewUnwrappedDNSOverHTTPSTransportWithHostOverride(
httpClient, URL, hostOverride)
txp = config.ResolveSaver.WrapDNSTransport(txp) // safe when config.ResolveSaver == nil
return netxlite.NewSerialResolver(txp), nil
return netxlite.NewUnwrappedSerialResolver(txp), nil
case "udp":
dialer := NewDialer(config)
endpoint, err := makeValidEndpoint(resolverURL)
if err != nil {
return nil, err
}
var txp model.DNSTransport = netxlite.NewDNSOverUDPTransport(
var txp model.DNSTransport = netxlite.NewUnwrappedDNSOverUDPTransport(
dialer, endpoint)
txp = config.ResolveSaver.WrapDNSTransport(txp) // safe when config.ResolveSaver == nil
return netxlite.NewSerialResolver(txp), nil
return netxlite.NewUnwrappedSerialResolver(txp), nil
case "dot":
config.TLSConfig.NextProtos = []string{"dot"}
tlsDialer := NewTLSDialer(config)
@ -285,20 +285,20 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
if err != nil {
return nil, err
}
var txp model.DNSTransport = netxlite.NewDNSOverTLSTransport(
var txp model.DNSTransport = netxlite.NewUnwrappedDNSOverTLSTransport(
tlsDialer.DialTLSContext, endpoint)
txp = config.ResolveSaver.WrapDNSTransport(txp) // safe when config.ResolveSaver == nil
return netxlite.NewSerialResolver(txp), nil
return netxlite.NewUnwrappedSerialResolver(txp), nil
case "tcp":
dialer := NewDialer(config)
endpoint, err := makeValidEndpoint(resolverURL)
if err != nil {
return nil, err
}
var txp model.DNSTransport = netxlite.NewDNSOverTCPTransport(
var txp model.DNSTransport = netxlite.NewUnwrappedDNSOverTCPTransport(
dialer.DialContext, endpoint)
txp = config.ResolveSaver.WrapDNSTransport(txp) // safe when config.ResolveSaver == nil
return netxlite.NewSerialResolver(txp), nil
return netxlite.NewUnwrappedSerialResolver(txp), nil
default:
return nil, errors.New("unsupported resolver scheme")
}

View file

@ -70,50 +70,50 @@ func TestNewResolverSystem(t *testing.T) {
}
func TestNewResolverUDPAddress(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverUDPTransport(netxlite.DefaultDialer, "8.8.8.8:53"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverUDPTransport(netxlite.DefaultDialer, "8.8.8.8:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverUDPDomain(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverUDPTransport(netxlite.DefaultDialer, "dns.google.com:53"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverUDPTransport(netxlite.DefaultDialer, "dns.google.com:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverTCPAddress(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverTCPTransport(new(net.Dialer).DialContext, "8.8.8.8:53"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTCPTransport(new(net.Dialer).DialContext, "8.8.8.8:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverTCPDomain(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverTCPTransport(new(net.Dialer).DialContext, "dns.google.com:53"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTCPTransport(new(net.Dialer).DialContext, "dns.google.com:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoTAddress(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverTLSTransport(new(tls.Dialer).DialContext, "8.8.8.8:853"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTLSTransport(new(tls.Dialer).DialContext, "8.8.8.8:853"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoTDomain(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverTLSTransport(new(tls.Dialer).DialContext, "dns.google.com:853"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTLSTransport(new(tls.Dialer).DialContext, "dns.google.com:853"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoH(t *testing.T) {
reso := netxlite.NewSerialResolver(
netxlite.NewDNSOverHTTPSTransport(http.DefaultClient, "https://cloudflare-dns.com/dns-query"))
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverHTTPSTransport(http.DefaultClient, "https://cloudflare-dns.com/dns-query"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}