fix(geolocate): always use netxlite functionality (#976)

This change ensures that, in turn, we're able to "remote" all the traffic generated by the `geolocate` package, rather than missing some bits of it that were still using the standard library and caused _some_ geolocations to geolocate as the local host rather than as the remote host.

Extracted from https://github.com/ooni/probe-cli/pull/969, where we tested this functionality.

Closes https://github.com/ooni/probe/issues/1383 (which was long overdue).

Part of https://github.com/ooni/probe/issues/2340, because it allows us to make progress with that.
This commit is contained in:
Simone Basso 2022-10-12 18:07:42 +02:00 committed by GitHub
commit 57a3919d2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 32 deletions

View file

@ -2,43 +2,51 @@ package geolocate
import (
"context"
"net"
"net/http"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/pion/stun"
)
// TODO(bassosimone): we should modify the stun code to use
// the session resolver rather than using its own.
//
// See https://github.com/ooni/probe/issues/1383.
type stunClient interface {
Close() error
Start(m *stun.Message, h stun.Handler) error
}
type stunConfig struct {
Dial func(network string, address string) (stunClient, error)
Endpoint string
Logger model.Logger
Dialer model.Dialer // optional
Endpoint string
Logger model.Logger
NewClient func(conn net.Conn) (stunClient, error) // optional
Resolver model.Resolver
}
func stunDialer(network string, address string) (stunClient, error) {
return stun.Dial(network, address)
func stunNewClient(conn net.Conn) (stunClient, error) {
return stun.NewClient(conn)
}
func stunIPLookup(ctx context.Context, config stunConfig) (string, error) {
config.Logger.Debugf("STUNIPLookup: start using %s", config.Endpoint)
ip, err := func() (string, error) {
dial := config.Dial
if dial == nil {
dial = stunDialer
dialer := config.Dialer
if dialer == nil {
dialer = netxlite.NewDialerWithResolver(config.Logger, config.Resolver)
}
clnt, err := dial("udp", config.Endpoint)
conn, err := dialer.DialContext(ctx, "udp", config.Endpoint)
if err != nil {
return model.DefaultProbeIP, err
}
newClient := config.NewClient
if newClient == nil {
newClient = stunNewClient
}
clnt, err := newClient(conn)
if err != nil {
conn.Close()
return model.DefaultProbeIP, err
}
defer clnt.Close()
message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
errch, ipch := make(chan error, 1), make(chan string, 1)
@ -78,10 +86,12 @@ func stunEkigaIPLookup(
httpClient *http.Client,
logger model.Logger,
userAgent string,
resolver model.Resolver,
) (string, error) {
return stunIPLookup(ctx, stunConfig{
Endpoint: "stun.ekiga.net:3478",
Logger: logger,
Resolver: resolver,
})
}
@ -90,9 +100,11 @@ func stunGoogleIPLookup(
httpClient *http.Client,
logger model.Logger,
userAgent string,
resolver model.Resolver,
) (string, error) {
return stunIPLookup(ctx, stunConfig{
Endpoint: "stun.l.google.com:19302",
Logger: logger,
Resolver: resolver,
})
}