diff --git a/pkg/vpn/bitmask.go b/pkg/vpn/bitmask.go index 701379ebb64fdd29046efbd8b5f1ac81e45564fa..d40a601346e4732e60d502cbbd2263c847d9a546 100644 --- a/pkg/vpn/bitmask.go +++ b/pkg/vpn/bitmask.go @@ -33,44 +33,59 @@ import ( ) type Bitmask struct { - tempdir string - onGateway bonafide.Gateway - ptGateway bonafide.Gateway - statusCh chan string - managementClient *management.MgmtClient - bonafide *bonafide.Bonafide - launch *launcher.Launcher - transport string - obfsvpnProxy *obfsvpn.Client - certPemPath string - openvpnArgs []string - useUDP bool - useSnowflake bool - canUpgrade bool - motd []motd.Message - provider string + api apiInterface // handles backend API communication, implemented in bonafide (v3) or menshen (v5) + onGateway bonafide.Gateway // gateway we are connected + ptGateway bonafide.Gateway // public transport gateway we are connected with + launch *launcher.Launcher // launcher manages the firewall and starts/stops openvpn + canUpgrade bool // is there an update available? + motd []motd.Message // cached message of the day (ony fetched once during startup) + statusCh chan string // channel used to get current OpenVPN state (remote ip, connection state, ...) + managementClient *management.MgmtClient // used to speak with our own management backend (OpenVPN process connects to it) + transport string // used transport, e.g. OpenVPN (plain) or obfuscated protocols (obfs4) + openvpnArgs []string // arguments used for invoking the OpenVPN process + useUDP bool // should we use UDP? + obfsvpnProxy *obfsvpn.Client // handles OpenVPN obfuscation, e.g. starts/stops obfs4 bridge + useSnowflake bool // should we use Snowflake? + provider string // currently not used, get fixed if we get to the provider agnostic client + tempdir string // random base temp dir. Used for OpenVPN CA (cacert.pem), + // client certificate (openvpn.pem, holds key and certificate) and management communication + // authentication (key file prefixed with leap-vpn-...). Directory gets deleted during teardown + certPemPath string // path of OpenVPN client certificate. Normally this is $tempdir/openvpn.pem, + // but it also can be $config/$provider.pem (if snowflake is used or supplied out-of-band in a censored network) } // Init the connection to bitmask func Init() (*Bitmask, error) { - statusCh := make(chan string, 10) tempdir, err := ioutil.TempDir("", "leap-") if err != nil { return nil, err } - bf := bonafide.New() + + api := bonafide.New() launch, err := launcher.NewLauncher() if err != nil { return nil, err } b := Bitmask{ - tempdir, - bonafide.Gateway{}, - bonafide.Gateway{}, statusCh, nil, bf, launch, - "", nil, "", []string{}, - false, false, isUpgradeAvailable(), - []motd.Message{}, ""} + tempdir: tempdir, + onGateway: bonafide.Gateway{}, + ptGateway: bonafide.Gateway{}, + statusCh: make(chan string, 10), + managementClient: nil, + api: api, + launch: launch, + transport: "", + obfsvpnProxy: nil, + certPemPath: "", + openvpnArgs: []string{}, + useUDP: false, + useSnowflake: false, + canUpgrade: isUpgradeAvailable(), + motd: motd.FetchLatest(), + provider: "", + } + // FIXME multiprovider: need to pass provider name early on // XXX we want to block on these, but they can timeout if we're blocked. b.checkForMOTD() @@ -111,7 +126,7 @@ func (b *Bitmask) GetStatusCh() <-chan string { } func (b *Bitmask) GetSnowflakeCh() <-chan *snowflake.StatusEvent { - return b.bonafide.GetSnowflakeCh() + return b.api.GetSnowflakeCh() } // Close the connection to bitmask, and does cleanup of temporal files @@ -145,11 +160,11 @@ func (b *Bitmask) Version() (string, error) { } func (b *Bitmask) NeedsCredentials() bool { - return b.bonafide.NeedsCredentials() + return b.api.NeedsCredentials() } func (b *Bitmask) DoLogin(username, password string) (bool, error) { - return b.bonafide.DoLogin(username, password) + return b.api.DoLogin(username, password) } func (b *Bitmask) UseUDP(udp bool) { @@ -162,7 +177,7 @@ func (b *Bitmask) UseSnowflake(s bool) error { } func (b *Bitmask) OffersUDP() bool { - return b.bonafide.IsUDPAvailable() + return b.api.IsUDPAvailable() } func (b *Bitmask) GetMotd() string { diff --git a/pkg/vpn/interface.go b/pkg/vpn/interface.go new file mode 100644 index 0000000000000000000000000000000000000000..91575e6fcbd64f5b4c9a4114abb2093fbf7901dc --- /dev/null +++ b/pkg/vpn/interface.go @@ -0,0 +1,24 @@ +package vpn + +import ( + "0xacab.org/leap/bitmask-vpn/pkg/snowflake" + "0xacab.org/leap/bitmask-vpn/pkg/vpn/bonafide" +) + +type apiInterface interface { + NeedsCredentials() bool + DoLogin(username, password string) (bool, error) + GetLocationQualityMap(transport string) map[string]float64 + GetLocationLabels(transport string) map[string][]string + SetManualGateway(label string) + SetAutomaticGateway() + IsManualLocation() bool + IsUDPAvailable() bool + GetBestLocation(transport string) (string, error) + GetPemCertificate() ([]byte, error) + GetOpenvpnArgs() ([]string, error) + GetGatewayByIP(ip string) (bonafide.Gateway, error) + GetBestGateways(transport string) ([]bonafide.Gateway, error) + GetAllGateways(transport string) ([]bonafide.Gateway, error) + GetSnowflakeCh() chan *snowflake.StatusEvent +} diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go index 47b3933abde78dff77feb4c406f7ad3bd996fabb..0f90770e87020fb2b0a54d37481f5ba2a19b98dc 100644 --- a/pkg/vpn/openvpn.go +++ b/pkg/vpn/openvpn.go @@ -49,7 +49,7 @@ func (b *Bitmask) StartVPN(provider string) error { if err != nil { return err } - b.openvpnArgs, err = b.bonafide.GetOpenvpnArgs() + b.openvpnArgs, err = b.api.GetOpenvpnArgs() if err != nil { return err } @@ -62,7 +62,7 @@ func (b *Bitmask) CanStartVPN() bool { /* FIXME this is not enough. We should check, if provider needs * credentials, if we have a valid token, otherwise remove it and make sure that we're asking for the credentials input */ - return !b.bonafide.NeedsCredentials() + return !b.api.NeedsCredentials() } func (b *Bitmask) startTransportForPrivateBridge(ctx context.Context, gw bonafide.Gateway) (proxy string, err error) { @@ -98,7 +98,7 @@ func (b *Bitmask) startTransport(ctx context.Context, host string) (proxy string return proxyAddr, nil } - gateways, err := b.bonafide.GetBestGateways(b.transport) + gateways, err := b.api.GetBestGateways(b.transport) if err != nil { return "", err } @@ -226,7 +226,7 @@ func (b *Bitmask) startOpenVPN(ctx context.Context) error { log.Debug().Msg("Getting a gateway with obfs4 transport...") - gateways, err := b.bonafide.GetBestGateways("obfs4") + gateways, err := b.api.GetBestGateways("obfs4") if err != nil { return err } @@ -261,7 +261,7 @@ func (b *Bitmask) startOpenVPN(ctx context.Context) error { log.Info(). Str("args", strings.Join(arg, " ")). Msg("args passed to bitmask-root") - gateways, err := b.bonafide.GetBestGateways("openvpn") + gateways, err := b.api.GetBestGateways("openvpn") if err != nil { return err } @@ -349,7 +349,7 @@ func (b *Bitmask) getCert() (certPath string, err error) { log.Info(). Str("certPath", certPath). Msg("Fetching certificate") - cert, err := b.bonafide.GetPemCertificate() + cert, err := b.api.GetPemCertificate() if err != nil { log.Warn(). Err(err). @@ -373,7 +373,7 @@ func (b *Bitmask) getCert() (certPath string, err error) { // Explicit call to GetGateways, to be able to fetch them all before starting the vpn func (b *Bitmask) fetchGateways() { log.Info().Msg("Fetching gateways...") - _, err := b.bonafide.GetAllGateways(b.transport) + _, err := b.api.GetAllGateways(b.transport) if err != nil { log.Warn(). Err(err). @@ -447,7 +447,7 @@ func (b *Bitmask) ReloadFirewall() error { } if status != Off { - gateways, err := b.bonafide.GetAllGateways("any") + gateways, err := b.api.GetAllGateways("any") if err != nil { return err } @@ -479,22 +479,22 @@ func (b *Bitmask) VPNCheck() (helpers bool, privilege bool, err error) { } func (b *Bitmask) GetLocationQualityMap(transport string) map[string]float64 { - return b.bonafide.GetLocationQualityMap(transport) + return b.api.GetLocationQualityMap(transport) } func (b *Bitmask) GetLocationLabels(transport string) map[string][]string { - return b.bonafide.GetLocationLabels(transport) + return b.api.GetLocationLabels(transport) } // UseGateway selects a gateway, by label, as the default gateway func (b *Bitmask) UseGateway(label string) { - b.bonafide.SetManualGateway(label) + b.api.SetManualGateway(label) } // UseAutomaticGateway sets the gateway to be selected automatically // best gateway will be used func (b *Bitmask) UseAutomaticGateway() { - b.bonafide.SetAutomaticGateway() + b.api.SetAutomaticGateway() } // SetTransport selects an obfuscation transport to use diff --git a/pkg/vpn/status.go b/pkg/vpn/status.go index aa12437508435b01900d66e7743bfd47e88b8552..ef81b8c9ddc199000edbbc8ff773d7448a57491b 100644 --- a/pkg/vpn/status.go +++ b/pkg/vpn/status.go @@ -88,7 +88,7 @@ func (b *Bitmask) eventHandler(eventCh <-chan management.Event) { // we're using pluggable transports b.onGateway = b.ptGateway } else { - gw, err := b.bonafide.GetGatewayByIP(ip) + gw, err := b.api.GetGatewayByIP(ip) if err == nil { b.onGateway = gw log.Info(). @@ -118,7 +118,7 @@ func (b *Bitmask) GetCurrentCountry() string { } func (b *Bitmask) GetBestLocation(transport string) string { - location, err := b.bonafide.GetBestLocation(transport) + location, err := b.api.GetBestLocation(transport) if err != nil { log.Warn(). Err(err). @@ -129,7 +129,7 @@ func (b *Bitmask) GetBestLocation(transport string) string { } func (b *Bitmask) IsManualLocation() bool { - return b.bonafide.IsManualLocation() + return b.api.IsManualLocation() } func (b *Bitmask) getOpenvpnState() (string, error) {