2021-04-03 19:57:21 +02:00
|
|
|
// Package tunnel allows to create tunnels to speak
|
|
|
|
// with OONI backends and other services.
|
2021-04-05 16:08:16 +02:00
|
|
|
//
|
|
|
|
// You need to fill a Config object and call Start to
|
|
|
|
// obtain an instance of Tunnel. The tunnel will expose
|
|
|
|
// a SOCKS5 proxy. You need to configure your HTTP
|
|
|
|
// code to use such a proxy. Remember to call the Stop
|
|
|
|
// method of a tunnel when you are done.
|
|
|
|
//
|
|
|
|
// There are two use cases for this package. The first
|
|
|
|
// use case is to enable urlgetter to perform measurements
|
|
|
|
// over tunnels (mainly psiphon).
|
|
|
|
//
|
|
|
|
// The second use case is to use tunnels to reach to the
|
|
|
|
// OONI backend when it's blocked. For the latter case
|
|
|
|
// we currently mainly use psiphon. In such a case, we'll
|
|
|
|
// use a psiphon configuration embedded into the OONI
|
|
|
|
// binary itself. When you are running a version of OONI
|
|
|
|
// that does not embed such a configuration, it won't
|
|
|
|
// be possible to address this use case.
|
|
|
|
//
|
|
|
|
// See session.go in the engine package for more details
|
|
|
|
// concerning this second use case.
|
2021-02-02 12:05:47 +01:00
|
|
|
package tunnel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
2021-04-05 11:27:41 +02:00
|
|
|
"fmt"
|
2021-02-02 12:05:47 +01:00
|
|
|
"net/url"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2021-04-05 16:08:16 +02:00
|
|
|
// Session is a measurement session. We filter for the only
|
|
|
|
// functionality we're interested to use. That is, fetching the
|
|
|
|
// psiphon configuration from the OONI backend (if possible).
|
2021-02-02 12:05:47 +01:00
|
|
|
type Session interface {
|
2021-04-05 16:08:16 +02:00
|
|
|
// FetchPsiphonConfig should fetch and return the psiphon config
|
|
|
|
// as a serialized JSON, or fail with an error.
|
2021-04-03 19:57:21 +02:00
|
|
|
FetchPsiphonConfig(ctx context.Context) ([]byte, error)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
2021-04-05 16:08:16 +02:00
|
|
|
// Tunnel is a tunnel for communicating with OONI backends
|
|
|
|
// (and other services) to circumvent blocking.
|
2021-02-02 12:05:47 +01:00
|
|
|
type Tunnel interface {
|
2021-04-05 11:27:41 +02:00
|
|
|
// BootstrapTime returns the time it required to
|
2021-04-05 16:08:16 +02:00
|
|
|
// create a new tunnel instance.
|
2021-02-02 12:05:47 +01:00
|
|
|
BootstrapTime() time.Duration
|
2021-04-05 11:27:41 +02:00
|
|
|
|
2021-04-05 16:08:16 +02:00
|
|
|
// SOCKS5ProxyURL returns the SOCSK5 proxy URL.
|
2021-02-02 12:05:47 +01:00
|
|
|
SOCKS5ProxyURL() *url.URL
|
2021-04-05 11:27:41 +02:00
|
|
|
|
2021-04-05 16:08:16 +02:00
|
|
|
// Stop stops the tunnel. You should not attempt to
|
|
|
|
// use any other tunnel method after Stop.
|
2021-02-02 12:05:47 +01:00
|
|
|
Stop()
|
|
|
|
}
|
|
|
|
|
2021-04-05 11:27:41 +02:00
|
|
|
// ErrEmptyTunnelDir indicates that config.TunnelDir is empty.
|
|
|
|
var ErrEmptyTunnelDir = errors.New("TunnelDir is empty")
|
|
|
|
|
|
|
|
// ErrUnsupportedTunnelName indicates that the given tunnel name
|
|
|
|
// is not supported by this package.
|
|
|
|
var ErrUnsupportedTunnelName = errors.New("unsupported tunnel name")
|
|
|
|
|
2021-04-05 16:08:16 +02:00
|
|
|
// Start starts a new tunnel by name or returns an error. We currently
|
|
|
|
// support the following tunnels:
|
|
|
|
//
|
|
|
|
// The "tor" tunnel requires the "tor" binary to be installed on
|
|
|
|
// your system. You can use config.TorArgs and config.TorBinary to
|
|
|
|
// select what binary to execute and with which arguments.
|
|
|
|
//
|
|
|
|
// The "psiphon" tunnel requires a configuration. Some builds of
|
|
|
|
// ooniprobe embed a configuration into the binary. When this
|
|
|
|
// is the case, the config.Session is a mocked object that just
|
|
|
|
// retuns such configuration.
|
|
|
|
//
|
|
|
|
// Otherwise, If there is no embedded psiphon configuration, the
|
|
|
|
// config.Session will must be an ordinary session. In such a
|
|
|
|
// case, fetching the Psiphon configuration from the backend may
|
|
|
|
// fail when the backend is not reachable.
|
2021-04-03 20:12:56 +02:00
|
|
|
func Start(ctx context.Context, config *Config) (Tunnel, error) {
|
2021-02-02 12:05:47 +01:00
|
|
|
switch config.Name {
|
|
|
|
case "psiphon":
|
2021-04-05 16:08:16 +02:00
|
|
|
return psiphonStart(ctx, config)
|
2021-02-02 12:05:47 +01:00
|
|
|
case "tor":
|
2021-04-05 16:08:16 +02:00
|
|
|
return torStart(ctx, config)
|
2021-02-02 12:05:47 +01:00
|
|
|
default:
|
2021-04-05 11:27:41 +02:00
|
|
|
return nil, fmt.Errorf("%w: %s", ErrUnsupportedTunnelName, config.Name)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
}
|