80 lines
2.5 KiB
Go
80 lines
2.5 KiB
Go
package webconnectivity
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
)
|
|
|
|
// TODO(bassosimone): this code needs refining before we can merge it inside
|
|
// master. For one, we already have systemv4 info. Additionally, it would
|
|
// be neat to avoid additional AAAA queries. Furthermore, we should also see
|
|
// to implement support for IPv6 only clients as well.
|
|
|
|
// DNSWhoamiService is a service that performs DNS whoami lookups.
|
|
type DNSWhoamiService struct {
|
|
// mu provides mutual exclusion
|
|
mu *sync.Mutex
|
|
|
|
// systemv4 contains systemv4 results
|
|
systemv4 []DNSWhoamiInfoEntry
|
|
|
|
// udpv4 contains udpv4 results
|
|
udpv4 map[string][]DNSWhoamiInfoEntry
|
|
}
|
|
|
|
// SystemV4 returns the results of querying using the system resolver and IPv4.
|
|
func (svc *DNSWhoamiService) SystemV4(ctx context.Context) ([]DNSWhoamiInfoEntry, bool) {
|
|
svc.mu.Lock()
|
|
defer svc.mu.Unlock()
|
|
if len(svc.systemv4) <= 0 {
|
|
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
|
defer cancel()
|
|
reso := netxlite.NewStdlibResolver(model.DiscardLogger)
|
|
addrs, err := reso.LookupHost(ctx, "whoami.v4.powerdns.org")
|
|
if err != nil || len(addrs) < 1 {
|
|
return nil, false
|
|
}
|
|
svc.systemv4 = []DNSWhoamiInfoEntry{{
|
|
Address: addrs[0],
|
|
}}
|
|
}
|
|
return svc.systemv4, len(svc.systemv4) > 0
|
|
}
|
|
|
|
// UDPv4 returns the results of querying a given UDP resolver and IPv4.
|
|
func (svc *DNSWhoamiService) UDPv4(ctx context.Context, address string) ([]DNSWhoamiInfoEntry, bool) {
|
|
svc.mu.Lock()
|
|
defer svc.mu.Unlock()
|
|
if len(svc.udpv4[address]) <= 0 {
|
|
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
|
defer cancel()
|
|
dialer := netxlite.NewDialerWithStdlibResolver(model.DiscardLogger)
|
|
reso := netxlite.NewParallelUDPResolver(model.DiscardLogger, dialer, address)
|
|
// TODO(bassosimone): this should actually only send an A query. Sending an AAAA
|
|
// query is _way_ unnecessary since we know that only A is going to work.
|
|
addrs, err := reso.LookupHost(ctx, "whoami.v4.powerdns.org")
|
|
if err != nil || len(addrs) < 1 {
|
|
return nil, false
|
|
}
|
|
svc.udpv4[address] = []DNSWhoamiInfoEntry{{
|
|
Address: addrs[0],
|
|
}}
|
|
}
|
|
value := svc.udpv4[address]
|
|
return value, len(value) > 0
|
|
}
|
|
|
|
// TODO(bassosimone): consider factoring this code and keeping state
|
|
// on disk rather than on memory.
|
|
|
|
// DNSWhoamiSingleton is the DNSWhoamiService singleton.
|
|
var DNSWhoamiSingleton = &DNSWhoamiService{
|
|
mu: &sync.Mutex{},
|
|
systemv4: []DNSWhoamiInfoEntry{},
|
|
udpv4: map[string][]DNSWhoamiInfoEntry{},
|
|
}
|