Skip to content

Commit

Permalink
Merge remote-tracking branch 'ooni/main' into chore/update-tree-2
Browse files Browse the repository at this point in the history
  • Loading branch information
ainghazal committed Mar 6, 2024
2 parents c6fa599 + 41e4e0b commit 48bebdd
Show file tree
Hide file tree
Showing 40 changed files with 251 additions and 217 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ TARGET ?= "1.1.1.1"
COUNT ?= 5
TIMEOUT ?= 10
LOCAL_TARGET := $(shell ip -4 addr show docker0 | grep 'inet ' | awk '{print $$2}' | cut -f 1 -d /)
COVERAGE_THRESHOLD := 75
COVERAGE_THRESHOLD := 70
FLAGS=-ldflags="-w -s -buildid=none -linkmode=external" -buildmode=pie -buildvcs=false

build:
Expand Down
59 changes: 23 additions & 36 deletions cmd/minivpn/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ import (
"github.com/jackpal/gateway"

"github.com/ooni/minivpn/extras/ping"
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/networkio"
"github.com/ooni/minivpn/internal/runtimex"
"github.com/ooni/minivpn/internal/tun"
"github.com/ooni/minivpn/pkg/config"
"github.com/ooni/minivpn/pkg/tracex"
"github.com/ooni/minivpn/pkg/tunnel"
)

func runCmd(binaryPath string, args ...string) {
Expand All @@ -41,7 +40,7 @@ func runRoute(args ...string) {
runCmd("/sbin/route", args...)
}

type config struct {
type cmdConfig struct {
configPath string
doPing bool
doTrace bool
Expand All @@ -52,7 +51,7 @@ type config struct {
func main() {
log.SetLevel(log.DebugLevel)

cfg := &config{}
cfg := &cmdConfig{}
flag.StringVar(&cfg.configPath, "config", "", "config file to load")
flag.BoolVar(&cfg.doPing, "ping", false, "if true, do ping and exit (for testing)")
flag.BoolVar(&cfg.doTrace, "trace", false, "if true, do a trace of the handshake and exit (for testing)")
Expand All @@ -68,17 +67,17 @@ func main() {
log.SetHandler(NewHandler(os.Stderr))
log.SetLevel(log.DebugLevel)

opts := []model.Option{
model.WithConfigFile(cfg.configPath),
model.WithLogger(log.Log),
opts := []config.Option{
config.WithConfigFile(cfg.configPath),
config.WithLogger(log.Log),
}

start := time.Now()

var tracer *tracex.Tracer
if cfg.doTrace {
tracer = tracex.NewTracer(start)
opts = append(opts, model.WithHandshakeTracer(tracer))
opts = append(opts, config.WithHandshakeTracer(tracer))
defer func() {
trace := tracer.Trace()
jsonData, err := json.MarshalIndent(trace, "", " ")
Expand All @@ -89,34 +88,22 @@ func main() {
}()
}

config := model.NewConfig(opts...)

// connect to the server
dialer := networkio.NewDialer(log.Log, &net.Dialer{})
ctx := context.Background()

proto := config.Remote().Protocol
addr := config.Remote().Endpoint

conn, err := dialer.DialContext(ctx, proto, addr)
if err != nil {
log.WithError(err).Error("dialer.DialContext")
return
}

// The TLS will expire in 60 seconds by default, but we can pass
// a shorter timeout.
ctx, cancel := context.WithTimeout(ctx, time.Duration(cfg.timeout)*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.timeout)*time.Second)
defer cancel()

// create config from the passed options
vpncfg := config.NewConfig(opts...)

// create a vpn tun Device
tunnel, err := tun.StartTUN(ctx, conn, config)
tun, err := tunnel.Start(ctx, &net.Dialer{}, vpncfg)
if err != nil {
log.WithError(err).Error("init error")
return
}
log.Infof("Local IP: %s\n", tunnel.LocalAddr())
log.Infof("Gateway: %s\n", tunnel.RemoteAddr())
log.Infof("Local IP: %s\n", tun.LocalAddr())
log.Infof("Gateway: %s\n", tun.RemoteAddr())

fmt.Println("initialization-sequence-completed")
fmt.Printf("elapsed: %v\n", time.Since(start))
Expand All @@ -126,7 +113,7 @@ func main() {
}

if cfg.doPing {
pinger := ping.New("8.8.8.8", tunnel)
pinger := ping.New("8.8.8.8", tun)
count := 5
pinger.Count = count

Expand All @@ -151,9 +138,9 @@ func main() {
MTU := 1420
iface.SetMTU(MTU)

localAddr := tunnel.LocalAddr().String()
remoteAddr := tunnel.RemoteAddr().String()
netMask := tunnel.NetMask()
localAddr := tun.LocalAddr().String()
remoteAddr := tun.RemoteAddr().String()
netMask := tun.NetMask()

// discover local gateway IP, we need it to add a route to our remote via our network gw
defaultGatewayIP, err := gateway.DiscoverGateway()
Expand All @@ -170,8 +157,8 @@ func main() {
}

if defaultGatewayIP != nil && defaultInterface != nil {
log.Infof("route add %s gw %v dev %s", config.Remote().IPAddr, defaultGatewayIP, defaultInterface.Name)
runRoute("add", config.Remote().IPAddr, "gw", defaultGatewayIP.String(), defaultInterface.Name)
log.Infof("route add %s gw %v dev %s", vpncfg.Remote().IPAddr, defaultGatewayIP, defaultInterface.Name)
runRoute("add", vpncfg.Remote().IPAddr, "gw", defaultGatewayIP.String(), defaultInterface.Name)
}

// we want the network CIDR for setting up the routes
Expand All @@ -194,13 +181,13 @@ func main() {
if err != nil {
log.WithError(err).Fatal("error reading from tun")
}
tunnel.Write(packet[:n])
tun.Write(packet[:n])
}
}()
go func() {
for {
packet := make([]byte, 2000)
n, err := tunnel.Read(packet)
n, err := tun.Read(packet)
if err != nil {
log.WithError(err).Fatal("error reading from tun")
}
Expand Down
3 changes: 2 additions & 1 deletion internal/controlchannel/controlchannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/internal/workers"
"github.com/ooni/minivpn/pkg/config"
)

var (
Expand Down Expand Up @@ -38,7 +39,7 @@ type Service struct {
//
// [ARCHITECTURE]: https://github.com/ooni/minivpn/blob/main/ARCHITECTURE.md
func (svc *Service) StartWorkers(
config *model.Config,
config *config.Config,
workersManager *workers.Manager,
sessionManager *session.Manager,
) {
Expand Down
7 changes: 4 additions & 3 deletions internal/datachannel/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ import (
"github.com/ooni/minivpn/internal/runtimex"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/internal/vpntest"
"github.com/ooni/minivpn/pkg/config"
)

func makeTestingSession() *session.Manager {
manager, err := session.NewManager(model.NewConfig())
manager, err := session.NewManager(config.NewConfig())
runtimex.PanicOnError(err, "could not get session manager")
manager.SetRemoteSessionID(model.SessionID{0x01})
return manager
}

func makeTestingOptions(t *testing.T, cipher, auth string) *model.OpenVPNOptions {
func makeTestingOptions(t *testing.T, cipher, auth string) *config.OpenVPNOptions {
crt, _ := vpntest.WriteTestingCerts(t.TempDir())
opt := &model.OpenVPNOptions{
opt := &config.OpenVPNOptions{
Cipher: cipher,
Auth: auth,
CertPath: crt.Cert,
Expand Down
5 changes: 3 additions & 2 deletions internal/datachannel/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/runtimex"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/pkg/config"
)

// dataChannelHandler manages the data "channel".
Expand All @@ -25,7 +26,7 @@ type dataChannelHandler interface {
// DataChannel represents the data "channel", that will encrypt and decrypt the tunnel payloads.
// data implements the dataHandler interface.
type DataChannel struct {
options *model.OpenVPNOptions
options *config.OpenVPNOptions
sessionManager *session.Manager
state *dataChannelState
decodeFn func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error)
Expand All @@ -39,7 +40,7 @@ var _ dataChannelHandler = &DataChannel{} // Ensure that we implement dataChanne
// NewDataChannelFromOptions returns a new data object, initialized with the
// options given. it also returns any error raised.
func NewDataChannelFromOptions(logger model.Logger,
opt *model.OpenVPNOptions,
opt *config.OpenVPNOptions,
sessionManager *session.Manager) (*DataChannel, error) {
runtimex.Assert(opt != nil, "openvpn datachannel: opts cannot be nil")
runtimex.Assert(opt != nil, "openvpn datachannel: opts cannot be nil")
Expand Down
23 changes: 12 additions & 11 deletions internal/datachannel/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/pkg/config"
)

func TestNewDataChannelFromOptions(t *testing.T) {
t.Run("check we can create a data channel", func(t *testing.T) {
opt := &model.OpenVPNOptions{
opt := &config.OpenVPNOptions{
Auth: "SHA256",
Cipher: "AES-128-GCM",
Compress: model.CompressionEmpty,
Compress: config.CompressionEmpty,
}
_, err := NewDataChannelFromOptions(log.Log, opt, makeTestingSession())
if err != nil {
Expand Down Expand Up @@ -77,7 +78,7 @@ func Test_DataChannel_setupKeys(t *testing.T) {

func Test_DataChannel_writePacket(t *testing.T) {
type fields struct {
options *model.OpenVPNOptions
options *config.OpenVPNOptions
// session is only used for NonAEAD encryption
session *session.Manager
state *dataChannelState
Expand All @@ -96,7 +97,7 @@ func Test_DataChannel_writePacket(t *testing.T) {
{
name: "good write with aead encryption should not fail",
fields: fields{
options: &model.OpenVPNOptions{Compress: model.CompressionEmpty},
options: &config.OpenVPNOptions{Compress: config.CompressionEmpty},
session: makeTestingSession(),
state: makeTestingStateAEAD(),
encryptEncodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) ([]byte, error) {
Expand All @@ -117,7 +118,7 @@ func Test_DataChannel_writePacket(t *testing.T) {
{
name: "good write with non-aead encryption should not fail",
fields: fields{
options: &model.OpenVPNOptions{Compress: model.CompressionEmpty},
options: &config.OpenVPNOptions{Compress: config.CompressionEmpty},
session: makeTestingSession(),
state: makeTestingStateNonAEAD(),
encryptEncodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) ([]byte, error) {
Expand Down Expand Up @@ -172,7 +173,7 @@ func Test_DataChannel_deadPacket(t *testing.T) {
}

type fields struct {
options *model.OpenVPNOptions
options *config.OpenVPNOptions
state *dataChannelState
decodeFn func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error)
decryptFn func([]byte, *encryptedData) ([]byte, error)
Expand Down Expand Up @@ -238,7 +239,7 @@ func Test_Data_decrypt(t *testing.T) {
}

type fields struct {
options *model.OpenVPNOptions
options *config.OpenVPNOptions
session *session.Manager
state *dataChannelState
decryptFn func([]byte, *encryptedData) ([]byte, error)
Expand All @@ -258,7 +259,7 @@ func Test_Data_decrypt(t *testing.T) {
{
name: "empty output in decode does fail",
fields: fields{
options: &model.OpenVPNOptions{},
options: &config.OpenVPNOptions{},
session: makeTestingSession(),
state: makeTestingStateAEAD(),
decodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error) {
Expand All @@ -275,7 +276,7 @@ func Test_Data_decrypt(t *testing.T) {
{
name: "empty encrypted input does fail",
fields: fields{
options: &model.OpenVPNOptions{},
options: &config.OpenVPNOptions{},
session: makeTestingSession(),
state: makeTestingStateAEAD(),
decodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error) {
Expand All @@ -292,7 +293,7 @@ func Test_Data_decrypt(t *testing.T) {
{
name: "error in decrypt propagates",
fields: fields{
options: &model.OpenVPNOptions{},
options: &config.OpenVPNOptions{},
session: makeTestingSession(),
state: makeTestingStateAEAD(),
decodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error) {
Expand All @@ -310,7 +311,7 @@ func Test_Data_decrypt(t *testing.T) {
{
name: "good decrypt returns expected output",
fields: fields{
options: &model.OpenVPNOptions{},
options: &config.OpenVPNOptions{},
session: makeTestingSession(),
state: makeTestingStateAEAD(),
decodeFn: func(model.Logger, []byte, *session.Manager, *dataChannelState) (*encryptedData, error) {
Expand Down
7 changes: 4 additions & 3 deletions internal/datachannel/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/runtimex"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/pkg/config"
)

var (
Expand Down Expand Up @@ -104,7 +105,7 @@ func decodeEncryptedPayloadNonAEAD(log model.Logger, buf []byte, session *sessio
// modes are supported at the moment, so no real decompression is done. It
// returns a byte array, and an error if the operation could not be completed
// successfully.
func maybeDecompress(b []byte, st *dataChannelState, opt *model.OpenVPNOptions) ([]byte, error) {
func maybeDecompress(b []byte, st *dataChannelState, opt *config.OpenVPNOptions) ([]byte, error) {
if st == nil || st.dataCipher == nil {
return []byte{}, fmt.Errorf("%w:%s", ErrBadInput, "bad state")
}
Expand All @@ -121,7 +122,7 @@ func maybeDecompress(b []byte, st *dataChannelState, opt *model.OpenVPNOptions)
switch st.dataCipher.isAEAD() {
case true:
switch opt.Compress {
case model.CompressionStub, model.CompressionLZONo:
case config.CompressionStub, config.CompressionLZONo:
// these are deprecated in openvpn 2.5.x
compr = b[0]
payload = b[1:]
Expand All @@ -141,7 +142,7 @@ func maybeDecompress(b []byte, st *dataChannelState, opt *model.OpenVPNOptions)
st.SetRemotePacketID(remotePacketID)

switch opt.Compress {
case model.CompressionStub, model.CompressionLZONo:
case config.CompressionStub, config.CompressionLZONo:
compr = b[4]
payload = b[5:]
default:
Expand Down
3 changes: 2 additions & 1 deletion internal/datachannel/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/internal/workers"
"github.com/ooni/minivpn/pkg/config"
)

var (
Expand Down Expand Up @@ -50,7 +51,7 @@ type Service struct {
// 3. keyWorker BLOCKS on keyUp to read a dataChannelKey and
// initializes the internal state with the resulting key;
func (s *Service) StartWorkers(
config *model.Config,
config *config.Config,
workersManager *workers.Manager,
sessionManager *session.Manager,
) {
Expand Down
3 changes: 2 additions & 1 deletion internal/datachannel/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ooni/minivpn/internal/model"
"github.com/ooni/minivpn/internal/session"
"github.com/ooni/minivpn/internal/workers"
"github.com/ooni/minivpn/pkg/config"
)

// test that we can start and stop the workers
Expand All @@ -26,7 +27,7 @@ func TestService_StartWorkers(t *testing.T) {
session := makeTestingSession()

opts := makeTestingOptions(t, "AES-128-GCM", "sha512")
s.StartWorkers(model.NewConfig(model.WithOpenVPNOptions(opts)), workers, session)
s.StartWorkers(config.NewConfig(config.WithOpenVPNOptions(opts)), workers, session)

keyReady <- makeTestingDataChannelKey()
<-session.Ready
Expand Down
Loading

0 comments on commit 48bebdd

Please sign in to comment.