diff --git a/bitmask_go/bonafide.go b/bitmask_go/bonafide.go
index cc94b2557b7f5262293f36fdb259e18171458723..97d83c948f79efbb5364e960a9aa4e688d535cc6 100644
--- a/bitmask_go/bonafide.go
+++ b/bitmask_go/bonafide.go
@@ -23,6 +23,9 @@ import (
 	"io/ioutil"
 	"log"
 	"net/http"
+	"sort"
+	"strconv"
+	"time"
 )
 
 const (
@@ -66,8 +69,9 @@ UN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp
 )
 
 type bonafide struct {
-	client *http.Client
-	eip    *eipService
+	client         *http.Client
+	eip            *eipService
+	defaultGateway string
 }
 
 type eipService struct {
@@ -102,7 +106,7 @@ func newBonafide() *bonafide {
 		},
 	}
 
-	return &bonafide{client, nil}
+	return &bonafide{client, nil, ""}
 }
 
 func (b *bonafide) getCertPem() ([]byte, error) {
@@ -129,6 +133,11 @@ func (b *bonafide) getGateways() ([]gateway, error) {
 	return b.eip.Gateways, nil
 }
 
+func (b *bonafide) setDefaultGateway(name string) {
+	b.defaultGateway = name
+	b.sortGateways()
+}
+
 func (b *bonafide) getOpenvpnArgs() ([]string, error) {
 	if b.eip == nil {
 		err := b.fetchEipJSON()
@@ -171,5 +180,50 @@ func (b *bonafide) fetchEipJSON() error {
 	}
 
 	b.eip = &eip
+	b.sortGateways()
 	return nil
 }
+
+func (b *bonafide) sortGateways() {
+	type gatewayDistance struct {
+		gateway  gateway
+		distance int
+	}
+
+	gws := []gatewayDistance{}
+	_, tzOffset := time.Now().Zone()
+	for _, gw := range b.eip.Gateways {
+		distance := 13
+		if gw.Location == b.defaultGateway {
+			distance = -1
+		} else {
+			gwOffset, err := strconv.Atoi(b.eip.Locations[gw.Location].Timezone)
+			if err != nil {
+				log.Printf("Error sorting gateways: %v", err)
+			} else {
+				distance = tzDistance(tzOffset, gwOffset)
+			}
+		}
+		gws = append(gws, gatewayDistance{gw, distance})
+	}
+
+	sort.Slice(gws, func(i, j int) bool { return gws[i].distance > gws[j].distance })
+	for i, gw := range gws {
+		b.eip.Gateways[i] = gw.gateway
+	}
+}
+
+func tzDistance(offset1, offset2 int) int {
+	abs := func(x int) int {
+		if x < 0 {
+			return -x
+		} else {
+			return x
+		}
+	}
+	distance := abs(offset1 - offset2)
+	if distance > 12 {
+		distance = 24 - distance
+	}
+	return distance
+}
diff --git a/bitmask_go/vpn.go b/bitmask_go/vpn.go
index 041a8e41d2c5ce9e4f881e8489a109a5bd981cd6..c62e27cfeb543b3867b6a65717b0f68716067488 100644
--- a/bitmask_go/vpn.go
+++ b/bitmask_go/vpn.go
@@ -81,13 +81,20 @@ func (b *Bitmask) VPNCheck() (helpers bool, priviledge bool, err error) {
 
 // ListGateways return the names of the gateways
 func (b *Bitmask) ListGateways(provider string) ([]string, error) {
-	// TODO
-	return []string{}, nil
+	gateways, err := b.bonafide.getGateways()
+	if err != nil {
+		return nil, err
+	}
+	gatewayNames := make([]string, len(gateways))
+	for i, gw := range gateways {
+		gatewayNames[i] = gw.Location
+	}
+	return gatewayNames, nil
 }
 
 // UseGateway selects name as the default gateway
 func (b *Bitmask) UseGateway(name string) error {
-	// TODO
+	b.bonafide.setDefaultGateway(name)
 	return nil
 }
 
diff --git a/config.go b/config.go
index e8b25ab1f46e338264d4d929d49e1857e501fc49..4eb5dd30240e476c8ecdcf7949688ebd4d48e5fb 100644
--- a/config.go
+++ b/config.go
@@ -17,7 +17,6 @@ package main
 
 import (
 	"encoding/json"
-	"flag"
 	"os"
 	"path"
 	"time"
@@ -37,7 +36,7 @@ var (
 type systrayConfig struct {
 	LastNotification time.Time
 	Donated          time.Time
-	SelectWateway    bool
+	SelectGateway    bool
 	UserStoppedVPN   bool
 }
 
@@ -53,7 +52,6 @@ func parseConfig() *systrayConfig {
 
 	dec := json.NewDecoder(f)
 	err = dec.Decode(&conf)
-	conf.parseFlags()
 	return &conf
 }
 
@@ -62,11 +60,6 @@ func (c *systrayConfig) setUserStoppedVPN(vpnStopped bool) error {
 	return c.save()
 }
 
-func (c *systrayConfig) parseFlags() {
-	flag.BoolVar(&c.SelectWateway, "select-gateway", false, "Enable gateway selection")
-	flag.Parse()
-}
-
 func (c *systrayConfig) hasDonated() bool {
 	return c.Donated.Add(oneMonth).After(time.Now())
 }
diff --git a/main.go b/main.go
index 617bdf1028f9f0715be3f86da5bf52da39e0fca5..56198bd9ae018415b2f665a3015060982d4482af 100644
--- a/main.go
+++ b/main.go
@@ -40,6 +40,10 @@ func main() {
 	// locking the main thread into an OS thread fixes the problem
 	runtime.LockOSThread()
 
+	conf := parseConfig()
+	initPrinter()
+
+	flag.BoolVar(&conf.SelectGateway, "select-gateway", false, "Enable gateway selection")
 	versionFlag := flag.Bool("version", false, "Version of the bitmask-systray")
 	flag.Parse()
 	if *versionFlag {
@@ -57,9 +61,6 @@ func main() {
 	}
 	defer releasePID()
 
-	conf := parseConfig()
-	initPrinter()
-
 	notify := newNotificator(conf)
 
 	b, err := initBitmask()
diff --git a/systray.go b/systray.go
index 5b2977ecf18f94c893710f2419fa899e6d96827f..28aeb29dccfa8d36e676d591a2b74f018e9699ec 100644
--- a/systray.go
+++ b/systray.go
@@ -77,7 +77,7 @@ func (bt *bmTray) onReady() {
 	bt.mCancel.Hide()
 	systray.AddSeparator()
 
-	if bt.conf.SelectWateway {
+	if bt.conf.SelectGateway {
 		bt.addGateways()
 	}