diff options
-rw-r--r-- | cmd/bitmask-vpn/main.go | 4 | ||||
-rw-r--r-- | pkg/bitmask/bitmask.go | 1 | ||||
-rw-r--r-- | pkg/bitmaskd/vpn.go | 5 | ||||
-rw-r--r-- | pkg/standalone/bonafide/bonafide.go | 8 | ||||
-rw-r--r-- | pkg/standalone/bonafide/eip_service.go | 7 | ||||
-rw-r--r-- | pkg/standalone/main.go | 5 | ||||
-rw-r--r-- | pkg/standalone/vpn.go | 106 | ||||
-rw-r--r-- | pkg/systray/config.go | 3 | ||||
-rw-r--r-- | pkg/systray/run.go | 6 |
9 files changed, 135 insertions, 10 deletions
diff --git a/cmd/bitmask-vpn/main.go b/cmd/bitmask-vpn/main.go index d7f12df..0f5759e 100644 --- a/cmd/bitmask-vpn/main.go +++ b/cmd/bitmask-vpn/main.go @@ -52,6 +52,7 @@ func main() { conf := systray.ParseConfig() selectGateway := flag.Bool("select-gateway", false, "Enable gateway selection") + obfs4 := flag.Bool("obfs4", false, "Use obfs4 to obfuscate the traffic is available in the provider") disableAutostart := flag.Bool("disable-autostart", false, "Disable the autostart for the next run") startVPN := flag.String("start-vpn", "", "Start the vpn in turned 'on' or 'off'") versionFlag := flag.Bool("version", false, "Version of the bitmask-systray") @@ -70,6 +71,9 @@ func main() { if *selectGateway { conf.SelectGateway = *selectGateway } + if *obfs4 { + conf.Obfs4 = *obfs4 + } if *disableAutostart { conf.DisableAustostart = *disableAutostart } diff --git a/pkg/bitmask/bitmask.go b/pkg/bitmask/bitmask.go index a7aabaa..df26fc0 100644 --- a/pkg/bitmask/bitmask.go +++ b/pkg/bitmask/bitmask.go @@ -27,4 +27,5 @@ type Bitmask interface { VPNCheck() (helpers bool, priviledge bool, err error) ListGateways(provider string) ([]string, error) UseGateway(name string) error + UseTransport(transport string) error } diff --git a/pkg/bitmaskd/vpn.go b/pkg/bitmaskd/vpn.go index 48ce7dd..2747441 100644 --- a/pkg/bitmaskd/vpn.go +++ b/pkg/bitmaskd/vpn.go @@ -96,3 +96,8 @@ func (b *Bitmask) UseGateway(name string) error { _, err := b.send("vpn", "locations", name) return err } + +// UseTransport selects an obfuscation transport to use +func (b *Bitmask) UseTransport(transport string) error { + return errors.New("Transport " + transport + " not implemented") +} diff --git a/pkg/standalone/bonafide/bonafide.go b/pkg/standalone/bonafide/bonafide.go index bdf6fff..fd32f2a 100644 --- a/pkg/standalone/bonafide/bonafide.go +++ b/pkg/standalone/bonafide/bonafide.go @@ -31,6 +31,7 @@ import ( const ( certAPI = config.APIURL + "1/cert" + certAPI3 = config.APIURL + "3/cert" secondsPerHour = 60 * 60 retryFetchJSONSeconds = 15 ) @@ -91,6 +92,13 @@ func (b *Bonafide) GetCertPem() ([]byte, error) { return nil, err } defer resp.Body.Close() + if resp.StatusCode == 404 { + resp, err = b.client.Post(certAPI3, "", nil) + if err != nil { + return nil, err + } + defer resp.Body.Close() + } if resp.StatusCode != 200 { return nil, fmt.Errorf("get vpn cert has failed with status: %s", resp.Status) } diff --git a/pkg/standalone/bonafide/eip_service.go b/pkg/standalone/bonafide/eip_service.go index 94e303d..c097e8a 100644 --- a/pkg/standalone/bonafide/eip_service.go +++ b/pkg/standalone/bonafide/eip_service.go @@ -78,11 +78,17 @@ func (b *Bonafide) fetchEipJSON() error { case 200: b.eip, err = decodeEIP3(resp.Body) case 404: + buf := make([]byte, 128) + resp.Body.Read(buf) + log.Printf("Error fetching eip v3 json: %s", buf) resp, err = b.client.Post(eip1API, "", nil) if err != nil { return err } defer resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("get eip json has failed with status: %s", resp.Status) + } b.eip, err = decodeEIP1(resp.Body) default: @@ -108,6 +114,7 @@ func decodeEIP1(body io.Reader) (*eipService, error) { decoder := json.NewDecoder(body) err := decoder.Decode(&eip1) if err != nil { + log.Printf("Error fetching eip v1 json: %v", err) return nil, err } diff --git a/pkg/standalone/main.go b/pkg/standalone/main.go index e19634c..6c267d6 100644 --- a/pkg/standalone/main.go +++ b/pkg/standalone/main.go @@ -22,6 +22,7 @@ import ( "0xacab.org/leap/bitmask-vpn/pkg/config" "0xacab.org/leap/bitmask-vpn/pkg/standalone/bonafide" + "0xacab.org/leap/shapeshifter" "github.com/apparentlymart/go-openvpn-mgmt/openvpn" ) @@ -32,6 +33,8 @@ type Bitmask struct { managementClient *openvpn.MgmtClient bonafide *bonafide.Bonafide launch *launcher + transport string + shapes *shapeshifter.ShapeShifter } // Init the connection to bitmask @@ -46,7 +49,7 @@ func Init() (*Bitmask, error) { if err != nil { return nil, err } - b := Bitmask{tempdir, statusCh, nil, bonafide, launch} + b := Bitmask{tempdir, statusCh, nil, bonafide, launch, "", nil} err = b.StopVPN() if err != nil { diff --git a/pkg/standalone/vpn.go b/pkg/standalone/vpn.go index 260eec1..e593f59 100644 --- a/pkg/standalone/vpn.go +++ b/pkg/standalone/vpn.go @@ -16,9 +16,15 @@ package standalone import ( + "fmt" "io/ioutil" + "log" "os" "path" + "strconv" + "strings" + + "0xacab.org/leap/shapeshifter" ) const ( @@ -28,26 +34,95 @@ const ( // StartVPN for provider func (b *Bitmask) StartVPN(provider string) error { - gateways, err := b.bonafide.GetGateways("openvpn") - if err != nil { - return err + var proxy string + if b.transport != "" { + var err error + proxy, err = b.startTransport() + if err != nil { + return err + } } - certPemPath, err := b.getCert() + + return b.startOpenVPN(proxy) +} + +func (b *Bitmask) startTransport() (proxy string, err error) { + proxy = "127.0.0.1:4430" + if b.shapes != nil { + return proxy, nil + } + + gateways, err := b.bonafide.GetGateways(b.transport) if err != nil { - return err + return "", err + } + if len(gateways) == 0 { + log.Printf("No gateway for transport %s in provider", b.transport) + return "", nil + } + + for _, gw := range gateways { + if _, ok := gw.Options["cert"]; !ok { + continue + } + b.shapes = &shapeshifter.ShapeShifter{ + Cert: gw.Options["cert"], + Target: gw.IPAddress + ":" + gw.Ports[0], + SocksAddr: proxy, + } + if iatMode, ok := gw.Options["iat-mode"]; ok { + b.shapes.IatMode, err = strconv.Atoi(iatMode) + if err != nil { + b.shapes.IatMode = 0 + } + } + err = b.shapes.Open() + if err != nil { + log.Printf("Can't connect to transport %s: %v", b.transport, err) + continue + } + return proxy, nil } + return "", fmt.Errorf("No working gateway for transport %s: %v", b.transport, err) +} - err = b.launch.firewallStart(gateways) +func (b *Bitmask) startOpenVPN(proxy string) error { + certPemPath, err := b.getCert() if err != nil { return err } - arg, err := b.bonafide.GetOpenvpnArgs() if err != nil { return err } - for _, gw := range gateways { - arg = append(arg, "--remote", gw.IPAddress, "443", "tcp4") + + if proxy == "" { + gateways, err := b.bonafide.GetGateways("openvpn") + if err != nil { + return err + } + err = b.launch.firewallStart(gateways) + if err != nil { + return err + } + + for _, gw := range gateways { + for _, port := range gw.Ports { + arg = append(arg, "--remote", gw.IPAddress, port, "tcp4") + } + } + } else { + gateways, err := b.bonafide.GetGateways(b.transport) + if err != nil { + return err + } + err = b.launch.firewallStart(gateways) + if err != nil { + return err + } + + proxyArgs := strings.Split(proxy, ":") + arg = append(arg, "--remote", proxyArgs[0], proxyArgs[1], "tcp4") } arg = append(arg, "--verb", "1", @@ -79,6 +154,10 @@ func (b *Bitmask) StopVPN() error { if err != nil { return err } + if b.shapes != nil { + b.shapes.Close() + b.shapes = nil + } return b.launch.openvpnStop() } @@ -146,6 +225,15 @@ func (b *Bitmask) UseGateway(name string) error { return nil } +// UseTransport selects an obfuscation transport to use +func (b *Bitmask) UseTransport(transport string) error { + if transport != "obfs4" { + return fmt.Errorf("Transport %s not implemented", transport) + } + b.transport = transport + return nil +} + func (b *Bitmask) getCertPemPath() string { return path.Join(b.tempdir, "openvpn.pem") } diff --git a/pkg/systray/config.go b/pkg/systray/config.go index 2e97456..75a4a98 100644 --- a/pkg/systray/config.go +++ b/pkg/systray/config.go @@ -40,10 +40,12 @@ type Config struct { LastNotification time.Time Donated time.Time SelectGateway bool + Obfs4 bool UserStoppedVPN bool DisableAustostart bool } SelectGateway bool + Obfs4 bool DisableAustostart bool StartVPN bool Version string @@ -64,6 +66,7 @@ func ParseConfig() *Config { } conf.SelectGateway = conf.file.SelectGateway + conf.Obfs4 = conf.file.Obfs4 conf.DisableAustostart = conf.file.DisableAustostart conf.StartVPN = !conf.file.UserStoppedVPN return &conf diff --git a/pkg/systray/run.go b/pkg/systray/run.go index ce4a886..6521da6 100644 --- a/pkg/systray/run.go +++ b/pkg/systray/run.go @@ -68,6 +68,12 @@ func initialize(conf *Config, bt *bmTray, finishedCh chan bool) { } func checkAndStartBitmask(b bitmask.Bitmask, notify *notificator, conf *Config) { + if conf.Obfs4 { + err := b.UseTransport("obfs4") + if err != nil { + log.Printf("Error setting transport: %v", err) + } + } err := checkAndInstallHelpers(b, notify) if err != nil { log.Printf("Is bitmask running? %v", err) |