diff --git a/cmd/bitmask-vpn/main.go b/cmd/bitmask-vpn/main.go
index d7f12df5687ac108a38f83a60e8c590f83c9834b..0f5759eefac96fa101e21ecd1bf1b7364f12c261 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 a7aabaaaf0c64759f49812db64519dbce00fd9cf..df26fc0efe5ffd600cb506efcc0f11ea2ade0277 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 48ce7dd8d95b34f8dc5e12566d74b6f51dbaa9b9..2747441f6c8b929948dc1037b5377506718c3d16 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 bdf6ffff6b082b8ce2bf6104315ece417eaaa812..fd32f2a8befb15cd68e4f08ad41d6e0929d5cd1a 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 94e303d96d2ba19ffd324bafbedb9fe24cb52c79..c097e8a730d07a0bcfb901e262fac1bc9d549759 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 e19634ceaed88fa48e739933042fcacda946f58e..6c267d6b5113e39c74d224aeb9d2ae8089e56196 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 260eec17cbc7288937004c1c14e9d2de0353cc8f..e593f59b2108570af98977008bfac728ef8ff895 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 2e974563192360cfcf039531e2cb050ee6072844..75a4a984fb43975226a97bfd0c6a9625cdf6febd 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 ce4a8861daf841fd6782fbf16a801d7f40c89202..6521da618811ce2d910fd4094fafee6b687a99c9 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)