From 0ff759e7564f4c0076b93e8451a87fafad1a078f Mon Sep 17 00:00:00 2001
From: jkito <belter@riseup.net>
Date: Fri, 5 Jul 2024 00:06:52 +0530
Subject: [PATCH] update obfsvpn to latest commit on main branch

this updates the helpers starting the obfsvpn bridge
to use the new client interface that was  introduced
in obfsvpn 1.0.0
---
 go.mod                                        |   5 +-
 go.sum                                        |   9 +-
 pkg/vpn/openvpn.go                            |  69 +-
 .../0xacab.org/leap/obfsvpn/client/client.go  | 472 +++++++++++--
 .../leap/obfsvpn/client/hopclient.go          | 444 ------------
 .../leap/obfsvpn/client/interfaces.go         |   7 -
 vendor/0xacab.org/leap/obfsvpn/obfsvpn/kcp.go |  56 ++
 .../leap/obfsvpn/obfsvpn/listener.go          |  45 +-
 .../github.com/kalikaneko/socks5/.gitignore   |   3 -
 vendor/github.com/kalikaneko/socks5/LICENSE   |  22 -
 vendor/github.com/kalikaneko/socks5/README.md | 316 ---------
 .../github.com/kalikaneko/socks5/address.go   | 263 -------
 vendor/github.com/kalikaneko/socks5/auth.go   | 165 -----
 vendor/github.com/kalikaneko/socks5/client.go | 542 ---------------
 vendor/github.com/kalikaneko/socks5/common.go |  47 --
 vendor/github.com/kalikaneko/socks5/conn.go   | 116 ----
 vendor/github.com/kalikaneko/socks5/port.go   | 101 ---
 .../github.com/kalikaneko/socks5/protocol.go  | 155 -----
 vendor/github.com/kalikaneko/socks5/reply.go  |  14 -
 .../github.com/kalikaneko/socks5/request.go   |  70 --
 vendor/github.com/kalikaneko/socks5/server.go | 653 ------------------
 .../github.com/kalikaneko/socks5/transport.go | 122 ----
 vendor/github.com/xtaci/kcp-go/v5/.travis.yml |   4 +
 vendor/github.com/xtaci/kcp-go/v5/README.md   |   6 -
 vendor/github.com/xtaci/kcp-go/v5/donate.png  | Bin 4420 -> 0 bytes
 vendor/github.com/xtaci/kcp-go/v5/fec.go      |  12 +-
 vendor/github.com/xtaci/kcp-go/v5/sess.go     |  49 +-
 .../xtaci/kcp-go/v5/wechat_donate.jpg         | Bin 35307 -> 0 bytes
 vendor/modules.txt                            |  11 +-
 29 files changed, 581 insertions(+), 3197 deletions(-)
 delete mode 100644 vendor/0xacab.org/leap/obfsvpn/client/hopclient.go
 delete mode 100644 vendor/0xacab.org/leap/obfsvpn/client/interfaces.go
 create mode 100644 vendor/0xacab.org/leap/obfsvpn/obfsvpn/kcp.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/.gitignore
 delete mode 100644 vendor/github.com/kalikaneko/socks5/LICENSE
 delete mode 100644 vendor/github.com/kalikaneko/socks5/README.md
 delete mode 100644 vendor/github.com/kalikaneko/socks5/address.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/auth.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/client.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/common.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/conn.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/port.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/protocol.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/reply.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/request.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/server.go
 delete mode 100644 vendor/github.com/kalikaneko/socks5/transport.go
 delete mode 100644 vendor/github.com/xtaci/kcp-go/v5/donate.png
 delete mode 100644 vendor/github.com/xtaci/kcp-go/v5/wechat_donate.jpg

diff --git a/go.mod b/go.mod
index a3c7bd75..4d44b63a 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.22
 toolchain go1.22.2
 
 require (
-	0xacab.org/leap/obfsvpn v0.0.0-20240422180703-83037b24d5cc
+	0xacab.org/leap/obfsvpn v1.0.1-0.20240625123757-59f234eea051
 	git.torproject.org/pluggable-transports/goptlib.git v1.3.0
 	git.torproject.org/pluggable-transports/snowflake.git v1.1.0
 	github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
@@ -16,7 +16,7 @@ require (
 	github.com/pion/webrtc/v3 v3.2.24
 	github.com/sevlyar/go-daemon v0.1.6
 	github.com/smartystreets/goconvey v1.6.4
-	github.com/xtaci/kcp-go/v5 v5.6.1
+	github.com/xtaci/kcp-go/v5 v5.6.3
 	github.com/xtaci/smux v1.5.24
 	// Do not update obfs4 past e330d1b7024b, a backwards incompatible change was
 	// made that will break negotiation!! riseup should move to the newest asap.
@@ -56,7 +56,6 @@ require (
 	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/jtolds/gls v4.20.0+incompatible // indirect
-	github.com/kalikaneko/socks5 v1.0.1 // indirect
 	github.com/klauspost/compress v1.16.6 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.6 // indirect
 	github.com/klauspost/reedsolomon v1.12.1 // indirect
diff --git a/go.sum b/go.sum
index 9a9a8a31..56ee9356 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,7 @@
 0xacab.org/leap/bitmask-core v0.0.0-20240529192952-8ea2f4de269e h1:dg8K5g8gpWYh8GfJPJKlSF6twnjFa4Ui9FMEahAf3jw=
 0xacab.org/leap/bitmask-core v0.0.0-20240529192952-8ea2f4de269e/go.mod h1:kuAy05ISfgrZJIPj2i7lXRxRlFF8gtRy3KvYYOgMYvI=
-0xacab.org/leap/obfsvpn v0.0.0-20240422180703-83037b24d5cc h1:QyADySTHZtWA81k58D/eD5aLFG2n8QaeKjIB/aMI3OU=
-0xacab.org/leap/obfsvpn v0.0.0-20240422180703-83037b24d5cc/go.mod h1:cOGeSmVkgxW5qYIOSvkBeFxwBnoOYsjuQWFYB5YYlm4=
+0xacab.org/leap/obfsvpn v1.0.1-0.20240625123757-59f234eea051 h1:z9sIIud8NbKW5+Qp0k6BnogK3O8CPWCN3Rx5Jbzq7bQ=
+0xacab.org/leap/obfsvpn v1.0.1-0.20240625123757-59f234eea051/go.mod h1:uesfK5XkHYSgHRpE9/Bb2yKkKTE6VFViyjbU/z4ST60=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
@@ -262,8 +262,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
-github.com/kalikaneko/socks5 v1.0.1 h1:j60X3e1sAmy/LK/WtHyU3xH6uMmwlRJyc9TE3AqYDpU=
-github.com/kalikaneko/socks5 v1.0.1/go.mod h1:XAMwFixakJUP0wv6pEVp6v2wx3SwhQEdL8TGDYKFAGU=
 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
 github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
@@ -563,8 +561,9 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg=
 github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
-github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI=
 github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo=
+github.com/xtaci/kcp-go/v5 v5.6.3 h1:yd59SKXdJ0PBxeMBy3apalxFCEmBLGgQmL6nP46tU0g=
+github.com/xtaci/kcp-go/v5 v5.6.3/go.mod h1:uIuw2KEg3FcmEdS4PeXHaGty9Ui7NYb1WKIrSDwpMg4=
 github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
 github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
 github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go
index 1ece141f..416774f8 100644
--- a/pkg/vpn/openvpn.go
+++ b/pkg/vpn/openvpn.go
@@ -30,7 +30,8 @@ import (
 
 	"0xacab.org/leap/bitmask-vpn/pkg/config"
 	"0xacab.org/leap/bitmask-vpn/pkg/vpn/bonafide"
-	obfsvpn "0xacab.org/leap/obfsvpn/client"
+	obfsvpnClient "0xacab.org/leap/obfsvpn/client"
+	"0xacab.org/leap/obfsvpn/obfsvpn"
 )
 
 const (
@@ -68,11 +69,32 @@ func (b *Bitmask) CanStartVPN() bool {
 
 func (b *Bitmask) startTransportForPrivateBridge(ctx context.Context, gw bonafide.Gateway) (proxy string, err error) {
 	proxyAddr := "127.0.0.1:8080"
-	kcpMode := false
+	kcpConfig := obfsvpn.KCPConfig{
+		Enabled: false,
+	}
 	if os.Getenv("LEAP_KCP") == "1" {
-		kcpMode = true
+		kcpConfig = *obfsvpn.DefaultKCPConfig()
+	}
+
+	obfsvpnCfg := obfsvpnClient.Config{
+		ProxyAddr: proxyAddr,
+		HoppingConfig: obfsvpnClient.HoppingConfig{
+			Enabled: false,
+		},
+		KCPConfig:  kcpConfig,
+		Obfs4Cert:  gw.Options["cert"],
+		RemoteIP:   gw.IPAddress,
+		RemotePort: gw.Ports[0],
 	}
-	b.obfsvpnProxy = obfsvpn.NewClient(ctx, kcpMode, proxyAddr, gw.Options["cert"]).(*obfsvpn.Client)
+	log.Info().Str("OBFS4 local proxy address:", obfsvpnCfg.ProxyAddr).
+		Str("OBFS4 Cert:", obfsvpnCfg.Obfs4Cert).
+		Bool("OBFS4+KCP:", kcpConfig.Enabled).
+		Str("OBFS4 Hostname", gw.Host).
+		Str("OBFS4 IP", gw.IPAddress).
+		Str("OBFS4 Port:", obfsvpnCfg.RemotePort).
+		Msg("OBFS4 bridge connection parameters")
+	ctx, cancelFunc := context.WithCancel(ctx)
+	b.obfsvpnProxy = obfsvpnClient.NewClient(ctx, cancelFunc, obfsvpnCfg)
 	go func() {
 		_, err = b.obfsvpnProxy.Start()
 		if err != nil {
@@ -126,21 +148,25 @@ func (b *Bitmask) startTransport(ctx context.Context, host string) (proxy string
 			Str("ip", gw.IPAddress).
 			Msg("Selected Gateway")
 
-		kcpMode := false
+		kcpConfig := obfsvpn.KCPConfig{
+			Enabled: false,
+		}
 		if os.Getenv("LEAP_KCP") == "1" {
-			kcpMode = true
+			kcpConfig = *obfsvpn.DefaultKCPConfig()
 		}
 
-		log.Debug().
-			Str("host", gw.Host).
-			Str("ip", gw.IPAddress).
-			Bool("kcp", kcpMode).
-			Str("cert", gw.Options["cert"]).
-			Str("proxyAddr", proxyAddr).
-			Str("transport", b.transport).
-			Msg("Using gateway")
-
-		b.obfsvpnProxy = obfsvpn.NewClient(ctx, kcpMode, proxyAddr, gw.Options["cert"]).(*obfsvpn.Client)
+		obfsvpnCfg := obfsvpnClient.Config{
+			ProxyAddr: proxyAddr,
+			HoppingConfig: obfsvpnClient.HoppingConfig{
+				Enabled: false,
+			},
+			KCPConfig:  kcpConfig,
+			Obfs4Cert:  gw.Options["cert"],
+			RemoteIP:   gw.IPAddress,
+			RemotePort: gw.Ports[0],
+		}
+		ctx, cancelFunc := context.WithCancel(ctx)
+		b.obfsvpnProxy = obfsvpnClient.NewClient(ctx, cancelFunc, obfsvpnCfg)
 		go func() {
 			_, err = b.obfsvpnProxy.Start()
 			if err != nil {
@@ -154,6 +180,14 @@ func (b *Bitmask) startTransport(ctx context.Context, host string) (proxy string
 				Str("host", gw.Host).
 				Msg("Connected via obfs4")
 		}()
+		log.Debug().
+			Str("host", gw.Host).
+			Str("ip", gw.IPAddress).
+			Bool("kcp", kcpConfig.Enabled).
+			Str("cert", gw.Options["cert"]).
+			Str("proxyAddr", proxyAddr).
+			Str("transport", b.transport).
+			Msg("Using gateway")
 
 		return proxyAddr, nil
 	}
@@ -278,8 +312,7 @@ func (b *Bitmask) startOpenVPN(ctx context.Context) error {
 		}
 
 		proxyArgs := strings.Split(proxy, ":")
-		arg = append(arg, "--socks-proxy", proxyArgs[0], proxyArgs[1])
-		arg = append(arg, "--remote", gw.IPAddress, gw.Ports[0], "tcp4")
+		arg = append(arg, "--remote", proxyArgs[0], proxyArgs[1], "udp")
 		arg = append(arg, "--route", gw.IPAddress, "255.255.255.255", "net_gateway")
 	} else {
 
diff --git a/vendor/0xacab.org/leap/obfsvpn/client/client.go b/vendor/0xacab.org/leap/obfsvpn/client/client.go
index 193b88e3..ad9745fb 100644
--- a/vendor/0xacab.org/leap/obfsvpn/client/client.go
+++ b/vendor/0xacab.org/leap/obfsvpn/client/client.go
@@ -1,18 +1,28 @@
-// Package client exposes a socks5 proxy that uses obfs4 to communicate with the server,
-// with an optional kcp wire transport.
+// Package client exposes a proxy that uses obfs4 to communicate with the server,
+// with an optional KCP wire transport.
 package client
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"log"
+	"math/rand"
 	"net"
 	"sync"
+	"time"
 
 	"0xacab.org/leap/obfsvpn/obfsvpn"
-	"github.com/kalikaneko/socks5"
-	"github.com/xtaci/kcp-go"
+)
+
+type clientState string
+
+const (
+	starting clientState = "STARTING"
+	running  clientState = "RUNNING"
+	stopping clientState = "STOPPING"
+	stopped  clientState = "STOPPED"
 )
 
 var (
@@ -21,113 +31,453 @@ var (
 	ErrBadConfig      = errors.New("configuration error")
 )
 
-type Client struct {
-	ctx         context.Context
-	kcp         bool
-	SocksAddr   string
-	obfs4Cert   string
-	server      *socks5.Server
-	EventLogger EventLogger
-	mux         sync.Mutex
-}
-
 type EventLogger interface {
 	Log(state string, message string)
 	Error(message string)
 }
 
-func NewClient(ctx context.Context, kcp bool, socksAddr, obfs4Cert string) ObfsClient {
+const (
+	dialGiveUpTime = 15 * time.Second
+)
+
+type Obfs4Config struct {
+	Remote string
+	Cert   string
+}
+
+func (oc *Obfs4Config) String() string {
+	return oc.Remote
+}
+
+type Config struct {
+	ProxyAddr     string            `json:"proxy_addr"`
+	HoppingConfig HoppingConfig     `json:"hopping_config"`
+	KCPConfig     obfsvpn.KCPConfig `json:"kcp_config"`
+	RemoteIP      string            `json:"remote_ip"`
+	RemotePort    string            `json:"remote_port"`
+	Obfs4Cert     string            `json:"obfs4_cert"`
+}
+
+type HoppingConfig struct {
+	Enabled       bool     `json:"enabled"`
+	Remotes       []string `json:"remotes"`
+	Obfs4Certs    []string `json:"obfs4_certs"`
+	PortSeed      int64    `json:"port_seed"`
+	PortCount     uint     `json:"port_count"`
+	MinHopSeconds uint     `json:"min_hop_seconds"`
+	HopJitter     uint     `json:"hop_jitter"`
+}
+
+type Client struct {
+	kcpConfig       obfsvpn.KCPConfig
+	ProxyAddr       string
+	newObfs4Conn    chan net.Conn
+	obfs4Conns      []net.Conn
+	obfs4Endpoints  []*Obfs4Config
+	obfs4Dialer     *obfsvpn.Dialer
+	obfs4Failures   map[string]int32
+	EventLogger     EventLogger
+	state           clientState
+	ctx             context.Context
+	mux             sync.Mutex
+	stop            context.CancelFunc
+	openvpnConn     *net.UDPConn
+	openvpnAddr     *net.UDPAddr
+	openvpnAddrLock sync.RWMutex
+	outLock         sync.Mutex
+	hopEnabled      bool
+	minHopSeconds   uint
+	hopJitter       uint
+}
+
+func NewClient(ctx context.Context, stop context.CancelFunc, config Config) *Client {
+	obfs4Endpoints := generateObfs4Config(config)
 	return &Client{
-		ctx:       ctx,
-		kcp:       kcp,
-		obfs4Cert: obfs4Cert,
-		SocksAddr: socksAddr,
+		ProxyAddr:      config.ProxyAddr,
+		hopEnabled:     config.HoppingConfig.Enabled,
+		ctx:            ctx,
+		hopJitter:      config.HoppingConfig.HopJitter,
+		kcpConfig:      config.KCPConfig,
+		obfs4Failures:  map[string]int32{},
+		minHopSeconds:  config.HoppingConfig.MinHopSeconds,
+		newObfs4Conn:   make(chan net.Conn),
+		obfs4Endpoints: obfs4Endpoints,
+		stop:           stop,
+		state:          stopped,
+	}
+}
+
+// NewFFIClient creates a new client
+// This function is exposed to the JNI and since it's not allowed to pass objects that contain slices (other than byte slices) over the JNI
+// we have to pass a json formatted string and convert it to a Config struct for further processing
+func NewFFIClient(jsonConfig string) (*Client, error) {
+	config := Config{}
+	err := json.Unmarshal([]byte(jsonConfig), &config)
+	if err != nil {
+		return nil, err
 	}
+	ctx, stop := context.WithCancel(context.Background())
+	return NewClient(ctx, stop, config), nil
+}
+
+func generateObfs4Config(config Config) []*Obfs4Config {
+	obfsEndpoints := []*Obfs4Config{}
+
+	if config.HoppingConfig.Enabled {
+		for i, obfs4Remote := range config.HoppingConfig.Remotes {
+			// We want a non-crypto RNG so that we can share a seed
+			// #nosec G404
+			r := rand.New(rand.NewSource(config.HoppingConfig.PortSeed))
+			for pi := 0; pi < int(config.HoppingConfig.PortCount); pi++ {
+				portOffset := r.Intn(obfsvpn.PortHopRange)
+				addr := net.JoinHostPort(obfs4Remote, fmt.Sprint(portOffset+obfsvpn.MinHopPort))
+				obfsEndpoints = append(obfsEndpoints, &Obfs4Config{
+					Cert:   config.HoppingConfig.Obfs4Certs[i],
+					Remote: addr,
+				})
+			}
+		}
+	} else {
+		addr := net.JoinHostPort(config.RemoteIP, config.RemotePort)
+		obfsEndpoints = append(obfsEndpoints, &Obfs4Config{
+			Cert:   config.Obfs4Cert,
+			Remote: addr,
+		})
+	}
+
+	log.Printf("obfs4 endpoints: %+v", obfsEndpoints)
+	return obfsEndpoints
 }
 
 func (c *Client) Start() (bool, error) {
+	var err error
+
 	c.mux.Lock()
 
 	defer func() {
-		c.log("STOPPED", "")
+		c.updateState(stopped)
+
+		if err != nil {
+			c.mux.Unlock()
+		}
 	}()
 
 	if c.IsStarted() {
 		c.error("Cannot start proxy server, already running")
-		return false, ErrAlreadyRunning
+		err = ErrAlreadyRunning
+		return false, err
 	}
 
-	c.server = &socks5.Server{
-		Addr:   c.SocksAddr,
-		BindIP: "127.0.0.1",
+	if len(c.obfs4Endpoints) == 0 {
+		c.error("Cannot start proxy server, no valid endpoints")
+		err = ErrBadConfig
+		return false, err
 	}
 
-	dialer, err := obfsvpn.NewDialerFromCert(c.obfs4Cert)
+	c.updateState(starting)
+
+	obfs4Endpoint := c.obfs4Endpoints[0]
+
+	c.obfs4Dialer, err = obfsvpn.NewDialerFromCert(obfs4Endpoint.Cert)
 	if err != nil {
-		c.error("Error getting dialer: %v\n", err)
-		return false, err
+		return false, fmt.Errorf("could not dial obfs4 remote: %w", err)
 	}
 
-	switch {
-	case c.kcp:
-		dialer.DialFunc = func(network, address string) (net.Conn, error) {
-			c.log("RUNNING", "client.Start(): dialing kcp://%s\n", address)
-			return kcp.Dial(address)
-		}
+	if c.kcpConfig.Enabled {
+		c.obfs4Dialer.DialFunc = obfsvpn.GetKCPDialer(c.kcpConfig, c.log)
+	}
+
+	obfs4Conn, err := c.obfs4Dialer.Dial("tcp", obfs4Endpoint.Remote)
+	if err != nil {
+		c.error("Could not dial obfs4 remote: %v", err)
+		return false, fmt.Errorf("could not dial remote: %w", err)
+	}
+
+	c.obfs4Conns = []net.Conn{obfs4Conn}
+
+	c.updateState(running)
+
+	proxyAddr, err := net.ResolveUDPAddr("udp", c.ProxyAddr)
+	if err != nil {
+		return false, fmt.Errorf("cannot resolve UDP addr: %w", err)
 	}
 
-	c.server.Dial = dialer.Dial
+	c.openvpnConn, err = net.ListenUDP("udp", proxyAddr)
+	if err != nil {
+		return false, fmt.Errorf("error accepting udp connection: %w", err)
+	}
+
+	if c.hopEnabled {
+		go c.hop()
+	}
 
-	c.log("RUNNING", "[+] Starting socks5 proxy at %s\n", c.SocksAddr)
+	go c.readUDPWriteTCP()
 
-	errCh := make(chan error)
-	go c.startSocksServer(errCh)
+	go c.readTCPWriteUDP()
 
 	c.mux.Unlock()
 
-	select {
-	case <-c.ctx.Done():
-		return true, nil
-	case err := <-errCh:
-		c.server = nil
-		return false, err
+	<-c.ctx.Done()
+
+	return true, nil
+}
+
+// updateState sets a new client state, logs it and sends an event to the clients
+// EventLogger in case it is available. Always set the state with this function in
+// order to ensure integrating clients receive an update state event via FFI.
+func (c *Client) updateState(state clientState) {
+	c.state = state
+	c.log("Update state: %v", state)
+}
+
+// pickRandomRemote returns a random remote from the internal array.
+// An obvious improvement to this function is to check the number of failures in c.obfs4Failures and avoid
+// a given remote if it failed more than a threshold. A consecuence is that
+// we'll have to return an unrecoverable error from hop() if there are no
+// more usable remotes. If we ever want to get fancy, an even better heuristic
+// can be to avoid IPs that have more failures than the average.
+func (c *Client) pickRandomEndpoint() *Obfs4Config {
+	// #nosec G404
+	i := rand.Intn(len(c.obfs4Endpoints))
+	endpoint := c.obfs4Endpoints[i]
+	// here we could check if the number of failures is ok-ish. we can also do moving averages etc.
+	return endpoint
+}
+
+func (c *Client) hop() {
+	for {
+		select {
+		case <-c.ctx.Done():
+			return
+		default:
+		}
+
+		// #nosec G404
+		sleepSeconds := rand.Intn(int(c.hopJitter)) + int(c.minHopSeconds)
+		c.log("Sleeping %d seconds...", sleepSeconds)
+		time.Sleep(time.Duration(sleepSeconds) * time.Second)
+
+		obfs4Endpoint := c.pickRandomEndpoint()
+
+		host, port, err := net.SplitHostPort(obfs4Endpoint.Remote)
+		if err != nil {
+			c.error("Could not split obfs4 remote: %v", err)
+			continue
+		}
+		remoteAddrs, err := net.DefaultResolver.LookupHost(c.ctx, host)
+		if err != nil {
+			c.error("Could not lookup obfs4 remote: %v", err)
+			continue
+		}
+
+		if len(remoteAddrs) <= 0 {
+			c.error("Could not lookup obfs4 remote: %v", err)
+			continue
+		}
+
+		newRemote := net.JoinHostPort(remoteAddrs[0], port)
+
+		for _, obfs4Conn := range c.obfs4Conns {
+			if obfs4Conn.RemoteAddr().String() == newRemote {
+				c.log("Not hopping to address already in obfs4Conns list: %v", newRemote)
+				continue
+			}
+		}
+
+		c.log("HOPPING to %+v", newRemote)
+
+		obfs4Dialer, err := obfsvpn.NewDialerFromCert(obfs4Endpoint.Cert)
+		if err != nil {
+			c.error("Could not dial obfs4 remote: %v", err)
+			return
+		}
+
+		if c.kcpConfig.Enabled {
+			c.obfs4Dialer.DialFunc = obfsvpn.GetKCPDialer(c.kcpConfig, c.log)
+		}
+
+		ctx, cancel := context.WithTimeout(context.Background(), dialGiveUpTime)
+		defer cancel()
+
+		c.log("Dialing new remote: %v", newRemote)
+		newObfs4Conn, err := obfs4Dialer.DialContext(ctx, "tcp", newRemote)
+
+		if err != nil {
+			_, ok := c.obfs4Failures[newRemote]
+			if ok {
+				c.obfs4Failures[newRemote] += 1
+			} else {
+				c.obfs4Failures[newRemote] = 1
+			}
+			c.error("Could not dial obfs4 remote: %v (failures: %d)", err, c.obfs4Failures[newRemote])
+		}
+
+		if newObfs4Conn == nil {
+			c.error("Did not get obfs4: %v ", err)
+		} else {
+			c.outLock.Lock()
+			c.obfs4Conns = append([]net.Conn{newObfs4Conn}, c.obfs4Conns...)
+			c.outLock.Unlock()
+
+			c.newObfs4Conn <- newObfs4Conn
+			c.log("Dialed new remote")
+
+			// If we wait sleepSeconds here to clean up the previous connection, we can guarantee that the
+			// connection list will not grow unbounded
+			go func() {
+				time.Sleep(time.Duration(sleepSeconds) * time.Second)
+
+				c.cleanupOldConn()
+			}()
+		}
 	}
 }
 
-func (c *Client) startSocksServer(ch chan error) {
-	if err := c.server.ListenAndServe(); err != nil {
-		c.error("error while listening: %v\n", err)
-		ch <- err
+func (c *Client) cleanupOldConn() {
+	c.outLock.Lock()
+	defer c.outLock.Unlock()
+
+	if len(c.obfs4Conns) > 1 {
+		c.log("Connections: %v", len(c.obfs4Conns))
+		connToClose := c.obfs4Conns[len(c.obfs4Conns)-1]
+		if connToClose != nil {
+			c.log("Cleaning up old connection to %v", connToClose.RemoteAddr())
+
+			err := connToClose.Close()
+			if err != nil {
+				c.log("Error closing obfs4 connection to %v: %v", connToClose.RemoteAddr(), err)
+			}
+		}
+
+		// Remove the connection from our tracking list
+		c.obfs4Conns = c.obfs4Conns[:len(c.obfs4Conns)-1]
 	}
 }
 
-func (c *Client) Stop() (bool, error) {
-	if !c.IsStarted() {
-		return false, ErrNotRunning
+func (c *Client) readUDPWriteTCP() {
+	datagramBuffer := make([]byte, obfsvpn.MaxUDPLen)
+	for {
+		select {
+		case <-c.ctx.Done():
+			return
+		default:
+		}
+
+		tcpBuffer, newOpenvpnAddr, err := obfsvpn.ReadUDPFrameTCP(c.openvpnConn, datagramBuffer)
+		if err != nil {
+			c.error("Read err from %v: %v", c.openvpnConn.LocalAddr(), err)
+			continue
+		}
+
+		if newOpenvpnAddr != c.openvpnAddr {
+			c.openvpnAddrLock.Lock()
+			c.openvpnAddr = newOpenvpnAddr
+			c.openvpnAddrLock.Unlock()
+		}
+
+		func() {
+			// Always write to the first connection in our list because it will be most up to date
+			func() {
+				conn, err := c.getUsableConnection()
+				if err != nil {
+					c.log("Cannot get connection: %s", err)
+					return
+				}
+				_, err = conn.Write(tcpBuffer)
+				if err != nil {
+					c.log("Write err from %v to %v: %v", conn.LocalAddr(), conn.RemoteAddr(), err)
+					return
+				}
+			}()
+		}()
+	}
+}
+
+func (c *Client) getUsableConnection() (net.Conn, error) {
+	c.outLock.Lock()
+	defer c.outLock.Unlock()
+
+	if len(c.obfs4Conns) == 0 {
+		return nil, errors.New("no usable connection")
+	} else {
+		return c.obfs4Conns[0], nil
+	}
+}
+
+func (c *Client) readTCPWriteUDP() {
+	for {
+		select {
+		case <-c.ctx.Done():
+			return
+		default:
+		}
+
+		fromTCP := make(chan []byte, 2048)
+
+		handleObfs4Conn := func(conn net.Conn) {
+			datagramBuffer := make([]byte, obfsvpn.MaxUDPLen)
+			lengthBuffer := make([]byte, 2)
+			for {
+				udpBuffer, err := obfsvpn.ReadTCPFrameUDP(conn, datagramBuffer, lengthBuffer)
+				if err != nil {
+					c.error("Reading/framing error: %v", err)
+					return
+				}
+
+				fromTCP <- udpBuffer
+			}
+		}
+
+		go func() {
+			for {
+				newObfs4Conn := <-c.newObfs4Conn
+
+				go handleObfs4Conn(newObfs4Conn)
+			}
+		}()
+
+		go handleObfs4Conn(c.obfs4Conns[0])
+
+		for {
+			tcpBytes := <-fromTCP
+
+			c.openvpnAddrLock.RLock()
+			_, err := c.openvpnConn.WriteToUDP(tcpBytes, c.openvpnAddr)
+			c.openvpnAddrLock.RUnlock()
+			if err != nil {
+				c.error("Write err from %v to %v: %v", c.openvpnConn.LocalAddr(), c.openvpnConn.RemoteAddr(), err)
+				return
+			}
+		}
 	}
+}
 
+func (c *Client) Stop() (bool, error) {
 	c.mux.Lock()
 	defer c.mux.Unlock()
 
-	if err := c.server.Close(); err != nil {
-		c.error("error while stopping: %v\n", err)
-		return false, err
+	if !c.IsStarted() {
+		return false, ErrNotRunning
 	}
 
-	c.server = nil
+	c.stop()
+	c.openvpnConn.Close()
+
+	c.updateState(stopped)
+
 	return true, nil
 }
 
-func (c *Client) log(state string, format string, a ...interface{}) {
+func (c *Client) log(format string, a ...interface{}) {
 	if c.EventLogger != nil {
-		c.EventLogger.Log(state, fmt.Sprintf(format, a...))
+		c.EventLogger.Log(string(c.state), fmt.Sprintf(format, a...))
 		return
 	}
 	if format == "" {
-		log.Print(a...)
+		log.Println(a...)
 		return
 	}
-	log.Printf(format, a...)
+	log.Printf(format+"\n", a...)
 }
 
 func (c *Client) error(format string, a ...interface{}) {
@@ -136,12 +486,12 @@ func (c *Client) error(format string, a ...interface{}) {
 		return
 	}
 	if format == "" {
-		log.Print(a...)
+		log.Println(a...)
 		return
 	}
-	log.Printf(format, a...)
+	log.Printf(format+"\n", a...)
 }
 
 func (c *Client) IsStarted() bool {
-	return c.server != nil
+	return c.state != stopped
 }
diff --git a/vendor/0xacab.org/leap/obfsvpn/client/hopclient.go b/vendor/0xacab.org/leap/obfsvpn/client/hopclient.go
deleted file mode 100644
index 2f5fbee0..00000000
--- a/vendor/0xacab.org/leap/obfsvpn/client/hopclient.go
+++ /dev/null
@@ -1,444 +0,0 @@
-// Package client exposes a socks5 proxy that uses obfs4 to communicate with the server,
-// with an optional KCP wire transport.
-package client
-
-import (
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"log"
-	"math/rand"
-	"net"
-	"sync"
-	"time"
-
-	"0xacab.org/leap/obfsvpn/obfsvpn"
-	"github.com/xtaci/kcp-go"
-)
-
-type clientState string
-
-const (
-	starting clientState = "STARTING"
-	running  clientState = "RUNNING"
-	stopping clientState = "STOPPING"
-	stopped  clientState = "STOPPED"
-)
-
-const (
-	dialGiveUpTime = 15 * time.Second
-)
-
-type Obfs4Config struct {
-	Remote string
-	Cert   string
-}
-
-func (oc *Obfs4Config) String() string {
-	return oc.Remote
-}
-
-type HoppingConfig struct {
-	KCP           bool     `json:"kcp"`
-	ProxyAddr     string   `json:"proxy_addr"`
-	Remotes       []string `json:"remotes"`
-	Certs         []string `json:"certs"`
-	PortSeed      int64    `json:"port_seed"`
-	PortCount     uint     `json:"port_count"`
-	MinHopSeconds uint     `json:"min_hop_seconds"`
-	HopJitter     uint     `json:"hop_jitter"`
-}
-
-type HopClient struct {
-	kcp             bool
-	ProxyAddr       string
-	newObfs4Conn    chan net.Conn
-	obfs4Conns      []net.Conn
-	obfs4Endpoints  []*Obfs4Config
-	obfs4Dialer     *obfsvpn.Dialer
-	obfs4Failures   map[string]int32
-	EventLogger     EventLogger
-	state           clientState
-	ctx             context.Context
-	stop            context.CancelFunc
-	openvpnConn     *net.UDPConn
-	openvpnAddr     *net.UDPAddr
-	openvpnAddrLock sync.RWMutex
-	outLock         sync.Mutex
-	minHopSeconds   uint
-	hopJitter       uint
-}
-
-func NewHopClient(ctx context.Context, stop context.CancelFunc, config HoppingConfig) ObfsClient {
-	obfs4Endpoints := generateObfs4Config(config.Remotes, config.PortSeed, config.PortCount, config.Certs)
-	return &HopClient{
-		ProxyAddr: config.ProxyAddr,
-
-		ctx:            ctx,
-		hopJitter:      config.HopJitter,
-		kcp:            config.KCP,
-		obfs4Failures:  map[string]int32{},
-		minHopSeconds:  config.MinHopSeconds,
-		newObfs4Conn:   make(chan net.Conn),
-		obfs4Endpoints: obfs4Endpoints,
-		stop:           stop,
-		state:          stopped,
-	}
-}
-
-// NewFFIHopClient creates a new Hopping PT client
-// This function is exposed to the JNI and since it's not allowed to pass objects that contain slices (other than byte slices) over the JNI
-// we have to pass a json formatted string and convert it to a HoppingConfig struct for further processing
-func NewFFIHopClient(hoppingConfig string) (*HopClient, error) {
-	config := HoppingConfig{}
-	err := json.Unmarshal([]byte(hoppingConfig), &config)
-	if err != nil {
-		return nil, err
-	}
-	ctx, stop := context.WithCancel(context.Background())
-	return NewHopClient(ctx, stop, config).(*HopClient), nil
-}
-
-func generateObfs4Config(remoteIPs []string, portSeed int64, portCount uint, certs []string) []*Obfs4Config {
-	obfsEndpoints := []*Obfs4Config{}
-
-	for i, obfs4Remote := range remoteIPs {
-		// We want a non-crypto RNG so that we can share a seed
-		// #nosec G404
-		r := rand.New(rand.NewSource(portSeed))
-		for pi := 0; pi < int(portCount); pi++ {
-			portOffset := r.Intn(obfsvpn.PortHopRange)
-			addr := net.JoinHostPort(obfs4Remote, fmt.Sprint(portOffset+obfsvpn.MinHopPort))
-			obfsEndpoints = append(obfsEndpoints, &Obfs4Config{
-				Cert:   certs[i],
-				Remote: addr,
-			})
-		}
-	}
-
-	log.Printf("obfs4 endpoints: %+v", obfsEndpoints)
-	return obfsEndpoints
-}
-
-func (c *HopClient) Start() (bool, error) {
-	defer func() {
-		c.state = stopped
-		c.log("Start function ended")
-	}()
-
-	if c.IsStarted() {
-		c.error("Cannot start proxy server, already running")
-		return false, ErrAlreadyRunning
-	}
-
-	if len(c.obfs4Endpoints) == 0 {
-		c.error("Cannot start proxy server, no valid endpoints")
-		return false, ErrBadConfig
-	}
-
-	c.state = starting
-
-	var err error
-
-	obfs4Endpoint := c.obfs4Endpoints[0]
-
-	c.obfs4Dialer, err = obfsvpn.NewDialerFromCert(obfs4Endpoint.Cert)
-	if err != nil {
-		return false, fmt.Errorf("could not dial obfs4 remote: %w", err)
-	}
-
-	if c.kcp {
-		c.obfs4Dialer.DialFunc = func(network, address string) (net.Conn, error) {
-			c.log("Dialing kcp://%s", address)
-			return kcp.Dial(address)
-		}
-	}
-
-	obfs4Conn, err := c.obfs4Dialer.Dial("tcp", obfs4Endpoint.Remote)
-	if err != nil {
-		c.error("Could not dial obfs4 remote: %v", err)
-	}
-
-	c.obfs4Conns = []net.Conn{obfs4Conn}
-
-	c.state = running
-
-	proxyAddr, err := net.ResolveUDPAddr("udp", c.ProxyAddr)
-	if err != nil {
-		return false, fmt.Errorf("cannot resolve UDP addr: %w", err)
-	}
-
-	c.openvpnConn, err = net.ListenUDP("udp", proxyAddr)
-	if err != nil {
-		return false, fmt.Errorf("error accepting udp connection: %w", err)
-	}
-
-	go c.hop()
-
-	go c.readUDPWriteTCP()
-
-	go c.readTCPWriteUDP()
-
-	<-c.ctx.Done()
-
-	return true, nil
-}
-
-// pickRandomRemote returns a random remote from the internal array.
-// An obvious improvement to this function is to check the number of failures in c.obfs4Failures and avoid
-// a given remote if it failed more than a threshold. A consecuence is that
-// we'll have to return an unrecoverable error from hop() if there are no
-// more usable remotes. If we ever want to get fancy, an even better heuristic
-// can be to avoid IPs that have more failures than the average.
-func (c *HopClient) pickRandomEndpoint() *Obfs4Config {
-	// #nosec G404
-	i := rand.Intn(len(c.obfs4Endpoints))
-	endpoint := c.obfs4Endpoints[i]
-	// here we could check if the number of failures is ok-ish. we can also do moving averages etc.
-	return endpoint
-}
-
-func (c *HopClient) hop() {
-	for {
-		select {
-		case <-c.ctx.Done():
-			return
-		default:
-		}
-
-		// #nosec G404
-		sleepSeconds := rand.Intn(int(c.hopJitter)) + int(c.minHopSeconds)
-		c.log("Sleeping %d seconds...", sleepSeconds)
-		time.Sleep(time.Duration(sleepSeconds) * time.Second)
-
-		obfs4Endpoint := c.pickRandomEndpoint()
-
-		host, port, err := net.SplitHostPort(obfs4Endpoint.Remote)
-		if err != nil {
-			c.error("Could not split obfs4 remote: %v", err)
-			continue
-		}
-		remoteAddrs, err := net.DefaultResolver.LookupHost(c.ctx, host)
-		if err != nil {
-			c.error("Could not lookup obfs4 remote: %v", err)
-			continue
-		}
-
-		if len(remoteAddrs) <= 0 {
-			c.error("Could not lookup obfs4 remote: %v", err)
-			continue
-		}
-
-		newRemote := net.JoinHostPort(remoteAddrs[0], port)
-
-		c.log("HOPPING to %+v", newRemote)
-
-		obfs4Dialer, err := obfsvpn.NewDialerFromCert(obfs4Endpoint.Cert)
-		if err != nil {
-			c.error("Could not dial obfs4 remote: %v", err)
-			return
-		}
-
-		if c.kcp {
-			obfs4Dialer.DialFunc = func(network, address string) (net.Conn, error) {
-				c.log("Dialing kcp://%s", address)
-				return kcp.Dial(address)
-			}
-		}
-
-		ctx, cancel := context.WithTimeout(context.Background(), dialGiveUpTime)
-		defer cancel()
-
-		c.log("Dialing new remote: %v", newRemote)
-		newObfs4Conn, err := obfs4Dialer.DialContext(ctx, "tcp", newRemote)
-
-		if err != nil {
-			_, ok := c.obfs4Failures[newRemote]
-			if ok {
-				c.obfs4Failures[newRemote] += 1
-			} else {
-				c.obfs4Failures[newRemote] = 1
-			}
-			c.error("Could not dial obfs4 remote: %v (failures: %d)", err, c.obfs4Failures[newRemote])
-		}
-
-		if newObfs4Conn == nil {
-			c.error("Did not get obfs4: %v ", err)
-		} else {
-			c.outLock.Lock()
-			c.obfs4Conns = append([]net.Conn{newObfs4Conn}, c.obfs4Conns...)
-			c.outLock.Unlock()
-
-			c.newObfs4Conn <- newObfs4Conn
-			c.log("Dialed new remote")
-
-			// If we wait sleepSeconds here to clean up the previous connection, we can guarantee that the
-			// connection list will not grow unbounded
-			go func() {
-				time.Sleep(time.Duration(sleepSeconds) * time.Second)
-
-				c.cleanupOldConn()
-			}()
-		}
-	}
-}
-
-func (c *HopClient) cleanupOldConn() {
-	c.outLock.Lock()
-	defer c.outLock.Unlock()
-
-	if len(c.obfs4Conns) > 1 {
-		c.log("Connections: %v", len(c.obfs4Conns))
-		connToClose := c.obfs4Conns[len(c.obfs4Conns)-1]
-		if connToClose != nil {
-			c.log("Cleaning up old connection to %v", connToClose.RemoteAddr())
-
-			err := connToClose.Close()
-			if err != nil {
-				c.log("Error closing obfs4 connection to %v: %v", connToClose.RemoteAddr(), err)
-			}
-		}
-
-		// Remove the connection from our tracking list
-		c.obfs4Conns = c.obfs4Conns[:len(c.obfs4Conns)-1]
-	}
-}
-
-func (c *HopClient) readUDPWriteTCP() {
-	datagramBuffer := make([]byte, obfsvpn.MaxUDPLen)
-	for {
-		select {
-		case <-c.ctx.Done():
-			return
-		default:
-		}
-
-		tcpBuffer, newOpenvpnAddr, err := obfsvpn.ReadUDPFrameTCP(c.openvpnConn, datagramBuffer)
-		if err != nil {
-			c.error("Read err from %v: %v", c.openvpnConn.LocalAddr(), err)
-			continue
-		}
-
-		if newOpenvpnAddr != c.openvpnAddr {
-			c.openvpnAddrLock.Lock()
-			c.openvpnAddr = newOpenvpnAddr
-			c.openvpnAddrLock.Unlock()
-		}
-
-		func() {
-			// Always write to the first connection in our list because it will be most up to date
-			func() {
-				conn, err := c.getUsableConnection()
-				if err != nil {
-					c.log("Cannot get connection: %s", err)
-					return
-				}
-				_, err = conn.Write(tcpBuffer)
-				if err != nil {
-					c.log("Write err from %v to %v: %v", conn.LocalAddr(), conn.RemoteAddr(), err)
-					return
-				}
-			}()
-		}()
-	}
-}
-
-func (c *HopClient) getUsableConnection() (net.Conn, error) {
-	c.outLock.Lock()
-	defer c.outLock.Unlock()
-
-	if len(c.obfs4Conns) == 0 {
-		return nil, errors.New("no usable connection")
-	} else {
-		return c.obfs4Conns[0], nil
-	}
-}
-
-func (c *HopClient) readTCPWriteUDP() {
-	for {
-		select {
-		case <-c.ctx.Done():
-			return
-		default:
-		}
-
-		fromTCP := make(chan []byte, 2048)
-
-		handleObfs4Conn := func(conn net.Conn) {
-			datagramBuffer := make([]byte, obfsvpn.MaxUDPLen)
-			lengthBuffer := make([]byte, 2)
-			for {
-				udpBuffer, err := obfsvpn.ReadTCPFrameUDP(conn, datagramBuffer, lengthBuffer)
-				if err != nil {
-					c.error("Reading/framing error: %v", err)
-					return
-				}
-
-				fromTCP <- udpBuffer
-			}
-		}
-
-		go func() {
-			for {
-				newObfs4Conn := <-c.newObfs4Conn
-
-				go handleObfs4Conn(newObfs4Conn)
-			}
-		}()
-
-		go handleObfs4Conn(c.obfs4Conns[0])
-
-		for {
-			tcpBytes := <-fromTCP
-
-			c.openvpnAddrLock.RLock()
-			_, err := c.openvpnConn.WriteToUDP(tcpBytes, c.openvpnAddr)
-			c.openvpnAddrLock.RUnlock()
-			if err != nil {
-				c.error("Write err from %v to %v: %v", c.openvpnConn.LocalAddr(), c.openvpnConn.RemoteAddr(), err)
-				return
-			}
-		}
-	}
-}
-
-func (c *HopClient) Stop() (bool, error) {
-	if !c.IsStarted() {
-		return false, ErrNotRunning
-	}
-
-	c.stop()
-
-	c.state = stopped
-
-	return true, nil
-}
-
-func (c *HopClient) log(format string, a ...interface{}) {
-	if c.EventLogger != nil {
-		c.EventLogger.Log(string(c.state), fmt.Sprintf(format, a...))
-		return
-	}
-	if format == "" {
-		log.Println(a...)
-		return
-	}
-	log.Printf(format+"\n", a...)
-}
-
-func (c *HopClient) error(format string, a ...interface{}) {
-	if c.EventLogger != nil {
-		c.EventLogger.Error(fmt.Sprintf(format, a...))
-		return
-	}
-	if format == "" {
-		log.Println(a...)
-		return
-	}
-	log.Printf(format+"\n", a...)
-}
-
-func (c *HopClient) IsStarted() bool {
-	return c.state != stopped
-}
diff --git a/vendor/0xacab.org/leap/obfsvpn/client/interfaces.go b/vendor/0xacab.org/leap/obfsvpn/client/interfaces.go
deleted file mode 100644
index 06174b36..00000000
--- a/vendor/0xacab.org/leap/obfsvpn/client/interfaces.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package client
-
-type ObfsClient interface {
-	Start() (bool, error)
-	Stop() (bool, error)
-	IsStarted() bool
-}
diff --git a/vendor/0xacab.org/leap/obfsvpn/obfsvpn/kcp.go b/vendor/0xacab.org/leap/obfsvpn/obfsvpn/kcp.go
new file mode 100644
index 00000000..05c92b7b
--- /dev/null
+++ b/vendor/0xacab.org/leap/obfsvpn/obfsvpn/kcp.go
@@ -0,0 +1,56 @@
+package obfsvpn
+
+import (
+	"net"
+
+	"github.com/xtaci/kcp-go/v5"
+)
+
+const (
+	DefaultKCPSendWindowSize    int = 65535
+	DefaultKCPReceiveWindowSize int = 65535
+	DefaultKCPReadBuffer        int = 16 * 1024 * 1024
+	DefaultKCPWriteBuffer       int = 16 * 1024 * 1024
+)
+
+type KCPConfig struct {
+	Enabled           bool
+	SendWindowSize    int
+	ReceiveWindowSize int
+	ReadBuffer        int
+	WriteBuffer       int
+}
+
+func DefaultKCPConfig() *KCPConfig {
+	return &KCPConfig{
+		Enabled:           true,
+		SendWindowSize:    DefaultKCPSendWindowSize,
+		ReceiveWindowSize: DefaultKCPReceiveWindowSize,
+		ReadBuffer:        DefaultKCPReadBuffer,
+		WriteBuffer:       DefaultKCPWriteBuffer,
+	}
+}
+
+func GetKCPDialer(kcpConfig KCPConfig, logger func(format string, a ...interface{})) func(network, address string) (net.Conn, error) {
+	return func(network, address string) (net.Conn, error) {
+		if logger != nil {
+			logger("Dialing kcp://%s", address)
+		}
+		kcpSession, err := kcp.DialWithOptions(address, nil, 10, 3)
+		if err != nil {
+			return nil, err
+		}
+		kcpSession.SetStreamMode(true)
+		kcpSession.SetWindowSize(kcpConfig.SendWindowSize, kcpConfig.ReceiveWindowSize)
+		if err := kcpSession.SetReadBuffer(kcpConfig.ReadBuffer); err != nil {
+			return nil, err
+		}
+		if err := kcpSession.SetWriteBuffer(kcpConfig.WriteBuffer); err != nil {
+			return nil, err
+		}
+		// https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration
+		kcpSession.SetNoDelay(1, 10, 2, 1)
+		return kcpSession, nil
+	}
+
+}
diff --git a/vendor/0xacab.org/leap/obfsvpn/obfsvpn/listener.go b/vendor/0xacab.org/leap/obfsvpn/obfsvpn/listener.go
index 2826cb49..2733430d 100644
--- a/vendor/0xacab.org/leap/obfsvpn/obfsvpn/listener.go
+++ b/vendor/0xacab.org/leap/obfsvpn/obfsvpn/listener.go
@@ -8,22 +8,19 @@ import (
 	"log"
 	"net"
 
-	"github.com/xtaci/kcp-go"
+	"github.com/xtaci/kcp-go/v5"
 	"gitlab.com/yawning/obfs4.git/common/ntor"
 	"gitlab.com/yawning/obfs4.git/transports/base"
 	"gitlab.com/yawning/obfs4.git/transports/obfs4"
 	pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
 )
 
-const (
-	netKCP = "kcp"
-)
-
 // ListenConfig contains options for listening to an address.
 // If Seed is not set it defaults to a randomized value.
 // If StateDir is not set the current working directory is used.
 type ListenConfig struct {
 	ListenConfig net.ListenConfig
+	KCPConfig    KCPConfig
 
 	NodeID     *ntor.NodeID
 	PrivateKey *ntor.PrivateKey
@@ -34,7 +31,7 @@ type ListenConfig struct {
 
 // NewListenConfig returns a ListenConfig and any error during the initialization.
 // perhaps this is redundant, but using the same json format than ss for debug.
-func NewListenConfig(nodeIDStr, privKeyStr, pubKeyStr, seedStr, stateDir string) (*ListenConfig, error) {
+func NewListenConfig(nodeIDStr, privKeyStr, pubKeyStr, seedStr, stateDir string, kcpConfig KCPConfig) (*ListenConfig, error) {
 	var err error
 	var seed [ntor.KeySeedLength]byte
 	var nodeID *ntor.NodeID
@@ -62,6 +59,7 @@ func NewListenConfig(nodeIDStr, privKeyStr, pubKeyStr, seedStr, stateDir string)
 		PublicKey:  pubKeyStr,
 		Seed:       seed,
 		StateDir:   stateDir,
+		KCPConfig:  kcpConfig,
 	}
 	return lc, nil
 }
@@ -119,21 +117,26 @@ func NewServerState(stateDir string) error {
 
 // Listen listens on the local network address.
 // See func net.Dial for a description of the network and address parameters.
-func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (*Listener, error) {
-	var ln net.Listener
-	var err error
-	switch network {
-	case netKCP:
+func (lc *ListenConfig) Listen(ctx context.Context, kcpConfig KCPConfig, address string) (*Listener, error) {
+	if kcpConfig.Enabled {
 		log.Println("kcp listen on", address)
-		ln, err = kcp.Listen(address)
+		ln, err := kcp.ListenWithOptions(address, nil, 10, 3)
 		if err != nil {
 			return nil, err
 		}
-	default:
-		ln, err = lc.ListenConfig.Listen(ctx, network, address)
-		if err != nil {
+
+		if err := ln.SetReadBuffer(kcpConfig.ReadBuffer); err != nil {
+			return nil, err
+		}
+		if err := ln.SetWriteBuffer(kcpConfig.WriteBuffer); err != nil {
 			return nil, err
 		}
+
+		return lc.Wrap(ctx, ln)
+	}
+	ln, err := lc.ListenConfig.Listen(ctx, "tcp", address)
+	if err != nil {
+		return nil, err
 	}
 	return lc.Wrap(ctx, ln)
 }
@@ -141,8 +144,9 @@ func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (*L
 // Listener is a network listener that accepts obfuscated connections and
 // performs the ntor handshake on them.
 type Listener struct {
-	sf base.ServerFactory
-	ln net.Listener
+	sf        base.ServerFactory
+	ln        net.Listener
+	kcpConfig KCPConfig
 }
 
 // Accept waits for and returns the next connection to the listener.
@@ -151,6 +155,13 @@ func (l *Listener) Accept() (net.Conn, error) {
 	if err != nil {
 		return nil, err
 	}
+	kcpSession, ok := conn.(*kcp.UDPSession)
+	if ok {
+		kcpSession.SetStreamMode(true)
+		kcpSession.SetWindowSize(l.kcpConfig.SendWindowSize, l.kcpConfig.ReceiveWindowSize)
+		// https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration
+		kcpSession.SetNoDelay(1, 10, 2, 1)
+	}
 	conn, err = l.sf.WrapConn(conn)
 	return conn, err
 }
diff --git a/vendor/github.com/kalikaneko/socks5/.gitignore b/vendor/github.com/kalikaneko/socks5/.gitignore
deleted file mode 100644
index acc70b4d..00000000
--- a/vendor/github.com/kalikaneko/socks5/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-main/
-.vscode/
-.idea/
\ No newline at end of file
diff --git a/vendor/github.com/kalikaneko/socks5/LICENSE b/vendor/github.com/kalikaneko/socks5/LICENSE
deleted file mode 100644
index 0e797b44..00000000
--- a/vendor/github.com/kalikaneko/socks5/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-MIT License
-
-Copyright (c) 2021 haochen233
-Copyright (c) 2022 kali kaneko
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/kalikaneko/socks5/README.md b/vendor/github.com/kalikaneko/socks5/README.md
deleted file mode 100644
index dde63b86..00000000
--- a/vendor/github.com/kalikaneko/socks5/README.md
+++ /dev/null
@@ -1,316 +0,0 @@
-# socks5
-
-This is a Golang implementation of the Socks5 protocol library.   
-To see in this [SOCKS Protocol Version 5](https://www.rfc-editor.org/rfc/rfc1928.html).  
-This library is also compatible with Socks4 and Socks4a.
-
-# Contents
-
-- [Features](#Features)
-- [Install](#Installation)
-- [Examples](#Examples)
-    - [Server example](#Server-example)
-        - [simple (no authentication)](#simple-no-authentication)
-        - [username/password authentication in memory](#username/password-authentication-in-memory)
-        - [custom transporter to transmit data between client and remote](#custom-transporter-to-transmit-data-between-client-and-remote)
-    - [Client example](#Client)
-        - [CONNECT usage](#CONNECT-usage)
-        - [UDP_ASSOCIATE usage](#UDP_ASSOCIATE-usage)
-        - [BIND usage](#BIND-usage)
-- [FAQ](#FAQ)
-
-# Features
-
-- socks5:
-    - command: **CONNECT**, **UDP ASSOCIATE**, **BIND**.
-    - auth methods:
-        - **Username/Password** authentication.
-        - No Authentication Required.
-- socks4:
-    - command: **CONNECT**, **BIND**.
-    - auth: (no support).
-- sock4a: same as socks4.
-- Custom client and server authenticator.
-- Easy to read source code.
-- Similar to the Golang standard library experience.
-
-# Installation
-
-``` sh
-$ go get "github.com/haochen233/socks5"`
-```
-
-# Examples
-
-## Server example
-
-### simple (no authentication):
-
-```go
-package main
-
-import (
-	"log"
-	"github.com/haochen233/socks5"
-)
-
-func main() {
-	// create socks server.
-	srv := &socks5.Server{
-		// socks server listen address.
-		Addr: "127.0.0.1:1080",
-		// UDP assocaite and bind command listen ip.
-		// Don't need port, the port will automatically chosen.
-		BindIP: "127.0.0.1",
-		// if nil server will provide no authentication required method.
-		Authenticators: nil,
-	}
-
-	// start listen
-	err := srv.ListenAndServe()
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-
-```
-
-### username/password authentication in memory:
-
-```go
-package main
-
-import (
-	"crypto/md5"
-	"log"
-
-	"github.com/haochen233/socks5"
-)
-
-func main() {
-	// create a username/password store in memory.
-	var userStorage socks5.UserPwdStore = socks5.NewMemeryStore(md5.New(), "secret")
-	// set a pair of username/password.
-	userStorage.Set("admin", "123456")
-
-	srv := &socks5.Server{
-		Addr:   "127.0.0.1:1080",
-		BindIP: "127.0.0.1",
-		// enable username/password method and authenticator.
-		Authenticators: map[socks5.METHOD]socks5.Authenticator{
-			socks5.USERNAME_PASSWORD: socks5.UserPwdAuth{UserPwdStore: userStorage},
-			// There is already an authentication method.
-			// If want enable no authentication required method.
-			// you should enable it explicit.
-			socks5.NO_AUTHENTICATION_REQUIRED: socks5.NoAuth{},
-		},
-	}
-
-	err := srv.ListenAndServe()
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-```
-
-### custom transporter to transmit data between client and remote.
-
-```go
-package main
-
-import (
-	"log"
-	"net"
-
-	"github.com/haochen233/socks5"
-)
-
-// simulate to impl socks5.Transporter interface.
-// transport encrypted data.
-type cryptTransport struct {
-}
-
-func (c *cryptTransport) TransportTCP(client *net.TCPConn, remote *net.TCPConn) <-chan error {
-	//encrypt data and send to remote
-	//decrypt data and send to client
-	return nil
-}
-
-func (c *cryptTransport) TransportUDP(server *socks5.UDPConn, request *socks5.Request) error {
-	panic("implement me")
-	return nil
-}
-
-func main() {
-	server := &socks5.Server{
-		Addr:   "127.0.0.1:1080",
-		BindIP: "127.0.0.1",
-		// replace default Transporter interface
-		Transporter: &cryptTransport{},
-	}
-
-	err := server.ListenAndServe()
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-```
-
-## Client example
-
-### CONNECT usage:
-
-```go
-package main
-
-import (
-	"log"
-
-	"github.com/haochen233/socks5"
-)
-
-func main() {
-	// create socks client
-	clnt := socks5.Client{
-		ProxyAddr: "127.0.0.1:1080",
-		// Authenticator supported by the client.
-		// It must not be nil.
-		Auth: map[socks5.METHOD]socks5.Authenticator{
-			// If client want send NO_AUTHENTICATION_REQUIRED method to server, must
-			// add socks5.NoAuth authenticator explicitly
-			socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
-		},
-	}
-
-	// client send CONNECT command and get a tcp connection.
-	// and use this connection transit data between you and www.google.com:80.
-	conn, err := clnt.Connect(socks5.Version5, "www.baidu.com:80")
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// close connection.
-	conn.Close()
-}
-
-```
-
-### UDP_ASSOCIATE usage:
-
-```go
-package main
-
-import (
-	"fmt"
-	"log"
-
-	"github.com/haochen233/socks5"
-)
-
-func main() {
-	clnt := socks5.Client{
-		ProxyAddr: "127.0.0.1:1080",
-		// client provide USERNAME_PASSWORD method and 
-		// NO_AUTHENTICATION_REQUIRED.
-		Auth: map[socks5.METHOD]socks5.Authenticator{
-			socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
-			socks5.USERNAME_PASSWORD:          &socks5.UserPasswd{Username: "admin", Password: "123456"},
-		},
-	}
-
-	// client send UDP_ASSOCIATE command and get a udp connection.
-	// Empty local addr string a local address (127.0.0.1:port) is automatically chosen.
-	// you can specific a address to tell socks server which client address will
-	// send udp data. Such as clnt.UDPForward("127.0.0.1:9999").
-	conn, err := clnt.UDPForward("")
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer conn.Close()
-
-	// send every datagram should add UDP request header.
-	someData := []byte("some data")
-	// dest addr where are you send to.
-	destAddr, _ := socks5.ParseAddress("127.0.0.1:9190")
-	// packing socks5 UDP data with dest addr.
-	pakcedData, err := socks5.PackUDPData(destAddr, someData)
-	// final send you data
-	conn.Write(pakcedData)
-
-	// on the contrary.
-	// you should unpacked the packet, after received  every packedData.
-	buf := make([]byte, 65507)
-	conn.Read(buf)
-
-	// unpacking data.
-	destAddr, unpackedData, err := socks5.UnpackUDPData(buf)
-	// operate your udp data. 
-	fmt.Println(unpackedData)
-}
-```
-
-### BIND usage:
-
-```go
-package main
-
-import (
-	"encoding/binary"
-	"github.com/haochen233/socks5"
-	"log"
-)
-
-func main() {
-	c := socks5.Client{
-		ProxyAddr: "172.16.1.28:1080",
-		Auth: map[socks5.METHOD]socks5.Authenticator{
-			socks5.USERNAME_PASSWORD:          &socks5.UserPasswd{"admin", "123456"},
-			socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
-		},
-	}
-
-	// connect
-	conn1, err := c.Connect(5, "127.0.0.1:9000")
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	dest := "127.0.0.1:9001"
-	// bind
-	bindAddr, errors, conn2, err := c.Bind(4, dest)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// An example tell dest about socks server bind address 
-	// via CONNECT proxy connection.
-	port := make([]byte, 2)
-	binary.BigEndian.PutUint16(port, bindAddr.Port)
-	conn1.Write(append(bindAddr.Addr, port...))
-
-	// wait the second reply. if nil the dest already
-	// established with socks server.
-	err = <-errors
-	if err != nil {
-		log.Fatal(err)
-		return
-	}
-
-	// bind success
-	_, err = conn2.Write([]byte("hello"))
-	if err != nil {
-		return
-		log.Fatal(err)
-	}
-}
-```
-
-# FAQ:
-- Server default enable socks4. How to disable socks4 support?  
-  when you initialize a socks5 server, you should spefic this flag to disable explicitly.
-   ```go
-   server := &socks5.Server{
-       DisableSocks4: true,
-   }
-   ```
\ No newline at end of file
diff --git a/vendor/github.com/kalikaneko/socks5/address.go b/vendor/github.com/kalikaneko/socks5/address.go
deleted file mode 100644
index 37f8f334..00000000
--- a/vendor/github.com/kalikaneko/socks5/address.go
+++ /dev/null
@@ -1,263 +0,0 @@
-package socks5
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-	"net"
-	"strconv"
-	"sync"
-)
-
-// Address represents address in socks protocol.
-type Address struct {
-	Addr net.IP
-	ATYPE
-	Port uint16
-}
-
-var bufPool = sync.Pool{New: func() interface{} {
-	buf := bytes.Buffer{}
-	return &buf
-}}
-
-// Address return address
-// Examples:
-//    127.0.0.1:80
-//    example.com:443
-//    [fe80::1%lo0]:80
-func (a *Address) String() string {
-	if a.ATYPE == DOMAINNAME {
-		return net.JoinHostPort(string(a.Addr), strconv.Itoa(int(a.Port)))
-	}
-	return net.JoinHostPort(a.Addr.String(), strconv.Itoa(int(a.Port)))
-}
-
-var errDomainMaxLengthLimit = errors.New("domain name out of max length")
-
-// Bytes return bytes slice of Address by ver param.
-// If ver is socks4, the returned socks4 address format as follows:
-//    +----+----+----+----+----+----+....+----+....+----+
-//    | DSTPORT |      DSTIP        | USERID       |NULL|
-//    +----+----+----+----+----+----+----+----+....+----+
-// If ver is socks4 and address type is domain name,
-// the returned socks4 address format as follows:
-//    +----+----+----+----+----+----+....+----+....+----+....+----+....+----+
-//    | DSTPORT |      DSTIP        | USERID       |NULL|   HOSTNAME   |NULL|
-//    +----+----+----+----+----+----+----+----+....+----+----+----+....+----+
-// If ver is socks5
-// the returned socks5 address format as follows:
-//    +------+----------+----------+
-//    | ATYP | DST.ADDR | DST.PORT |
-//    +------+----------+----------+
-//    |  1   | Variable |    2     |
-//    +------+----------+----------+
-// Socks4 call this method return bytes end with NULL, socks4 client use normally,
-// Socks4 server should trim terminative NULL.
-// Socks4 server should not call this method if server address type is DOMAINNAME
-func (a *Address) Bytes(ver VER) ([]byte, error) {
-	buf := bufPool.Get().(*bytes.Buffer)
-	defer buf.Reset()
-	defer bufPool.Put(buf)
-
-	// port
-	port := make([]byte, 2)
-	binary.BigEndian.PutUint16(port, a.Port)
-
-	switch ver {
-	case Version4:
-		// socks4a
-		buf.Write(port)
-		if a.ATYPE == DOMAINNAME {
-			buf.Write(net.IPv4(0, 0, 0, 1).To4())
-			// NULL
-			buf.WriteByte(NULL)
-			// hostname
-			buf.Write(a.Addr)
-		} else if a.ATYPE == IPV4_ADDRESS {
-			buf.Write(a.Addr)
-		} else {
-			return nil, fmt.Errorf("socks4 unsupported address type: %#x", a.ATYPE)
-		}
-		buf.WriteByte(NULL)
-	case Version5:
-		// address type
-		buf.WriteByte(a.ATYPE)
-		// domain name address type
-		if a.ATYPE == DOMAINNAME {
-			if len(a.Addr) > 255 {
-				return nil, errDomainMaxLengthLimit
-			}
-			buf.WriteByte(byte(len(a.Addr)))
-			buf.Write(a.Addr)
-		} else if a.ATYPE == IPV4_ADDRESS {
-			buf.Write(a.Addr.To4())
-		} else if a.ATYPE == IPV6_ADDRESS {
-			buf.Write(a.Addr.To16())
-		}
-		buf.Write(port)
-	}
-
-	return buf.Bytes(), nil
-}
-
-// readAddress read address info from follows:
-//    socks5 server's reply.
-//    socks5 client's request.
-//    socks5 server's udp reply header.
-//    socks5 client's udp request header.
-//
-//    socks4 client's  request.
-//    socks4a client's  request
-// exclude: socks4a server's reply, socks4 server's reply. Please use readSocks4ReplyAddress.
-func readAddress(r io.Reader, ver VER) (*Address, REP, error) {
-	addr := &Address{}
-
-	switch ver {
-	case Version4:
-		// DST.PORT
-		port, err := ReadNBytes(r, 2)
-		if err != nil {
-			return nil, Rejected, &OpError{Version5, "read", nil, "client dest port", err}
-		}
-		addr.Port = binary.BigEndian.Uint16(port)
-		// DST.IP
-		ip, err := ReadNBytes(r, 4)
-		if err != nil {
-			return nil, Rejected, &OpError{Version4, "read", nil, "\"process request dest ip\"", err}
-		}
-		addr.ATYPE = IPV4_ADDRESS
-
-		//Discard later bytes until read EOF
-		//Please see socks4 request format at(http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)
-		_, err = ReadUntilNULL(r)
-		if err != nil {
-			return nil, Rejected, &OpError{Version4, "read", nil, "\"process request useless header \"", err}
-		}
-
-		//Socks4a extension
-		//    +----+----+----+----+----+----+----+----+----+----++----++-----+-----++----+
-		//    | VN | CD | DSTPORT |      DSTIP        | USERID   |NULL|  HOSTNAME   |NULL|
-		//    +----+----+----+----+----+----+----+----+----+----++----++-----+-----++----+
-		//       1    1      2              4           variable    1    variable    1
-		//The client sets the first three bytes of DSTIP to NULL and
-		//the last byte to non-zero. The corresponding IP address is
-		//0.0.0.x, where x is non-zero
-		if ip[0] == 0 && ip[1] == 0 && ip[2] == 0 &&
-			ip[3] != 0 {
-			ip, err = ReadUntilNULL(r)
-			if err != nil {
-				return nil, Rejected, &OpError{Version4, "read", nil, "\"process socks4a extension request\"", err}
-			}
-			addr.ATYPE = DOMAINNAME
-		}
-		addr.Addr = ip
-		return addr, Granted, nil
-	case Version5:
-		// ATYP
-		aType, err := ReadNBytes(r, 1)
-		if err != nil {
-			return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "dest address type", err}
-		}
-		addr.ATYPE = aType[0]
-
-		var addrLen int
-		switch addr.ATYPE {
-		case IPV4_ADDRESS:
-			addrLen = 4
-		case IPV6_ADDRESS:
-			addrLen = 16
-		case DOMAINNAME:
-			fqdnLength, err := ReadNBytes(r, 1)
-			if err != nil {
-				return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "\"dest domain name length\"", err}
-			}
-			addrLen = int(fqdnLength[0])
-		default:
-			return nil, ADDRESS_TYPE_NOT_SUPPORTED, &OpError{Version5, "", nil, "\"dest address\"", &AtypeError{aType[0]}}
-		}
-
-		// DST.ADDR
-		ip, err := ReadNBytes(r, addrLen)
-		if err != nil {
-			return nil, GENERAL_SOCKS_SERVER_FAILURE, err
-		}
-		addr.Addr = ip
-
-		// DST.PORT
-		port, err := ReadNBytes(r, 2)
-		if err != nil {
-			return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "client dest port", err}
-		}
-		addr.Port = binary.BigEndian.Uint16(port)
-		return addr, SUCCESSED, nil
-	default:
-		return nil, UNASSIGNED, &VersionError{ver}
-	}
-}
-
-// readSocks4ReplyAddress read socks4 reply address. Why don't use readAddress,
-// because socks4 reply not end with NULL, they're not compatible
-func readSocks4ReplyAddress(r io.Reader, ver VER) (*Address, REP, error) {
-	addr := &Address{}
-
-	// DST.PORT
-	port, err := ReadNBytes(r, 2)
-	if err != nil {
-		return nil, Rejected, &OpError{Version5, "read", nil, "client dest port", err}
-	}
-	addr.Port = binary.BigEndian.Uint16(port)
-	// DST.IP
-	ip, err := ReadNBytes(r, 4)
-	if err != nil {
-		return nil, Rejected, &OpError{Version4, "read", nil, "\"process request dest ip\"", err}
-	}
-	addr.Addr = ip
-	addr.ATYPE = IPV4_ADDRESS
-
-	return addr, Granted, nil
-}
-
-// UDPAddr return UDP Address.
-func (a *Address) UDPAddr() (*net.UDPAddr, error) {
-	return net.ResolveUDPAddr("udp", a.String())
-}
-
-// TCPAddr return TCP Address.
-func (a *Address) TCPAddr() (*net.TCPAddr, error) {
-	return net.ResolveTCPAddr("tcp", a.String())
-}
-
-// ParseAddress parse address to *Address
-// Input Examples:
-//    127.0.0.1:80
-//    example.com:443
-//    [fe80::1%lo0]:80
-func ParseAddress(addr string) (*Address, error) {
-	Address := new(Address)
-
-	host, port, err := net.SplitHostPort(addr)
-	if err != nil {
-		return nil, err
-	}
-
-	ip := net.ParseIP(host)
-	if ip == nil {
-		Address.ATYPE = DOMAINNAME
-		Address.Addr = []byte(host)
-	} else if ip.To4() != nil {
-		Address.ATYPE = IPV4_ADDRESS
-		Address.Addr = ip.To4()
-	} else if ip.To16() != nil {
-		Address.ATYPE = IPV6_ADDRESS
-		Address.Addr = ip.To16()
-	}
-	atoi, err := strconv.Atoi(port)
-	if err != nil {
-		return nil, err
-	}
-	Address.Port = uint16(atoi)
-	return Address, nil
-}
diff --git a/vendor/github.com/kalikaneko/socks5/auth.go b/vendor/github.com/kalikaneko/socks5/auth.go
deleted file mode 100644
index d8f0e98b..00000000
--- a/vendor/github.com/kalikaneko/socks5/auth.go
+++ /dev/null
@@ -1,165 +0,0 @@
-package socks5
-
-import (
-	"bytes"
-	"fmt"
-	"hash"
-	"io"
-	"sync"
-)
-
-// Authenticator provides socks5's authentication sub negotiation.
-type Authenticator interface {
-	Authenticate(in io.Reader, out io.Writer) error
-}
-
-// NoAuth NO_AUTHENTICATION_REQUIRED implementation.
-type NoAuth struct {
-}
-
-// Authenticate NO_AUTHENTICATION_REQUIRED Authentication for socks5 Server and Client.
-func (n NoAuth) Authenticate(in io.Reader, out io.Writer) error {
-	return nil
-}
-
-// UserPwdAuth provides socks5 Server Username/Password Authenticator.
-type UserPwdAuth struct {
-	UserPwdStore
-}
-
-// Authenticate provide socks5 Server Username/Password authentication.
-func (u UserPwdAuth) Authenticate(in io.Reader, out io.Writer) error {
-	uname, passwd, err := u.ReadUserPwd(in)
-	if err != nil {
-		return err
-	}
-
-	err = u.Validate(string(uname), string(passwd))
-	if err != nil {
-		reply := []byte{1, 1}
-		_, err1 := out.Write(reply)
-		if err1 != nil {
-			return err
-		}
-		return err
-	}
-
-	//authentication successful,then send reply to client
-	reply := []byte{1, 0}
-	_, err = out.Write(reply)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// ReadUserPwd read Username/Password request from client
-// return username and password.
-// Username/Password request format is as follows:
-//    +----+------+----------+------+----------+
-//    |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
-//    +----+------+----------+------+----------+
-//    | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
-//    +----+------+----------+------+----------+
-// For standard details, please see (https://www.rfc-editor.org/rfc/rfc1929.html)
-func (u UserPwdAuth) ReadUserPwd(in io.Reader) ([]byte, []byte, error) {
-
-	ulen, err := ReadNBytes(in, 2)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	uname, err := ReadNBytes(in, int(ulen[1]))
-	if err != nil {
-		return nil, nil, err
-	}
-
-	plen, err := ReadNBytes(in, 1)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	passwd := make([]byte, plen[0])
-	passwd, err = ReadNBytes(in, int(plen[0]))
-	if err != nil {
-		return nil, nil, err
-	}
-
-	return uname, passwd, nil
-}
-
-// UserPwdStore provide username and password storage.
-type UserPwdStore interface {
-	Set(username string, password string) error
-	Del(username string) error
-	Validate(username string, password string) error
-}
-
-// MemoryStore store username&password in memory.
-// the password is encrypt with hash method.
-type MemoryStore struct {
-	Users map[string][]byte
-	mu    sync.Mutex
-	hash.Hash
-	algoSecret string
-}
-
-// NewMemeryStore return a new MemoryStore
-func NewMemeryStore(algo hash.Hash, secret string) *MemoryStore {
-	return &MemoryStore{
-		Users:      make(map[string][]byte),
-		Hash:       algo,
-		algoSecret: secret,
-	}
-}
-
-// Set the mapping of username and password.
-func (m *MemoryStore) Set(username string, password string) error {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	build := bytes.NewBuffer(nil)
-	build.WriteString(password + m.algoSecret)
-	cryptPasswd := m.Hash.Sum(build.Bytes())
-	m.Users[username] = cryptPasswd
-	return nil
-}
-
-// UserNotExist the error type used in UserPwdStore.Del() method and
-// UserPwdStore.Validate method.
-type UserNotExist struct {
-	username string
-}
-
-func (u UserNotExist) Error() string {
-	return fmt.Sprintf("user %s don't exist", u.username)
-}
-
-// Del delete by username
-func (m *MemoryStore) Del(username string) error {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	if _, ok := m.Users[username]; !ok {
-		return UserNotExist{username: username}
-	}
-
-	delete(m.Users, username)
-	return nil
-}
-
-// Validate validate username and password.
-func (m *MemoryStore) Validate(username string, password string) error {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	if _, ok := m.Users[username]; !ok {
-		return UserNotExist{username: username}
-	}
-
-	build := bytes.NewBuffer(nil)
-	build.WriteString(password + m.algoSecret)
-	cryptPasswd := m.Hash.Sum(build.Bytes())
-	if !bytes.Equal(cryptPasswd, m.Users[username]) {
-		return fmt.Errorf("user %s has bad password", username)
-	}
-	return nil
-}
diff --git a/vendor/github.com/kalikaneko/socks5/client.go b/vendor/github.com/kalikaneko/socks5/client.go
deleted file mode 100644
index a2f652b1..00000000
--- a/vendor/github.com/kalikaneko/socks5/client.go
+++ /dev/null
@@ -1,542 +0,0 @@
-package socks5
-
-import (
-	"errors"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"strconv"
-	"time"
-)
-
-// Client defines parameters for running socks client.
-type Client struct {
-	// ProxyAddr in the form "host:port". It not be empty.
-	ProxyAddr string
-
-	// Timeout specifies a time limit for requests made by this
-	// Client. The timeout includes connection time, reading the response body.
-	//
-	// A Timeout of zero means no timeout.
-	//
-	// The Client cancels requests to the underlying Transport
-	// as if the Request's Context ended.
-	Timeout time.Duration
-
-	// method mapping to the authenticator
-	Auth map[METHOD]Authenticator
-
-	// ErrorLog specifics an options logger for errors accepting
-	// If nil, logging is done via log package's standard logger.
-	ErrorLog *log.Logger
-
-	// DisableSocks4A client disable socks4a client, default enable socks4a extension.
-	DisableSocks4A bool
-}
-
-// UserPasswd provide socks5 Client Username/Password Authenticator.
-type UserPasswd struct {
-	Username string
-	Password string
-}
-
-// Authenticate socks5 Client Username/Password Authentication.
-func (c *UserPasswd) Authenticate(in io.Reader, out io.Writer) error {
-	//This begins with the client producing a Username/Password request:
-	//    +----+------+----------+------+----------+
-	//    |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
-	//    +----+------+----------+------+----------+
-	//    | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
-	//    +----+------+----------+------+----------+
-	_, err := out.Write(append(append(append([]byte{0x01, byte(len(c.Username))}, []byte(c.Username)...), byte(len(c.Password))), []byte(c.Password)...))
-	if err != nil {
-		return err
-	}
-	//Get reply, the following response:
-
-	//    +----+--------+
-	//    |VER | STATUS |
-	//    +----+--------+
-	//    | 1  |   1    |
-	//    +----+--------+
-	tmp, err := ReadNBytes(in, 2)
-	if err != nil {
-		return err
-	}
-	if tmp[0] != 0x01 {
-		return errors.New("not support method")
-	}
-	if tmp[1] != SUCCESSED {
-		return errors.New("user authentication failed")
-	}
-	return nil
-}
-
-// handshake socks TCP connect,get a tcp connect and reply addr
-func (clt *Client) handshake(request *Request) (conn *net.TCPConn, replyAddr *Address, err error) {
-	// get Socks server Address
-	proxyTCPAddr, err := net.ResolveTCPAddr("tcp", clt.ProxyAddr)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	// dial to Socks server.
-	proxyTCPConn, err := net.DialTCP("tcp", nil, proxyTCPAddr)
-	if err != nil {
-		return nil, nil, err
-	}
-	if clt.Timeout != 0 {
-		err = proxyTCPConn.SetDeadline(time.Now().Add(clt.Timeout))
-		if err != nil {
-			return nil, nil, err
-		}
-		defer proxyTCPConn.SetDeadline(time.Time{})
-	}
-
-	// process handshake by version
-	if request.VER == Version5 {
-		replyAddr, err = clt.handShake5(request, proxyTCPConn)
-	} else if request.VER == Version4 {
-		if request.ATYPE == DOMAINNAME && clt.DisableSocks4A {
-			return nil, nil, errors.New("socks4a client had been disabled")
-		}
-		replyAddr, err = clt.handshake4(request, proxyTCPConn)
-	}
-
-	// handshake wrong.
-	if err != nil {
-		proxyTCPConn.Close()
-		return nil, nil, err
-	}
-
-	return proxyTCPConn, replyAddr, nil
-}
-
-// handShake5 Socks 5 version of the connection handshake
-func (clt *Client) handShake5(request *Request, proxyTCPConn net.Conn) (*Address, error) {
-	err := clt.authentication(proxyTCPConn)
-	if err != nil {
-		return nil, err
-	}
-	destAddrByte, err := request.Address.Bytes(Version5)
-	if err != nil {
-		return nil, err
-	}
-	// The SOCKS request is formed as follows:
-	//    +----+-----+-------+------+----------+----------+
-	//    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
-	//    +----+-----+-------+------+----------+----------+
-	//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-	//    +----+-----+-------+------+----------+----------+
-	if _, err := proxyTCPConn.Write(append([]byte{request.VER, request.CMD, request.RSV}, destAddrByte...)); err != nil {
-		return nil, err
-	}
-	// reply formed as follows:
-	//    +----+-----+-------+------+----------+----------+
-	//    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
-	//    +----+-----+-------+------+----------+----------+
-	//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-	//    +----+-----+-------+------+----------+----------+
-	reply := &Reply{}
-	tmp, err := ReadNBytes(proxyTCPConn, 3)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get reply version and command and reserved, %v", err)
-	}
-	reply.VER, reply.REP, reply.RSV = tmp[0], tmp[1], tmp[2]
-	if reply.VER != Version5 {
-		return nil, fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER)
-	}
-	// read address
-	serverBoundAddr, _, err := readAddress(proxyTCPConn, request.VER)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get reply address, %v", err)
-	}
-	reply.Address = serverBoundAddr
-	if reply.REP != SUCCESSED {
-		return nil, fmt.Errorf("server refuse client request, %s", rep2Str[reply.REP])
-	}
-	return reply.Address, nil
-}
-
-// authentication
-func (clt *Client) authentication(proxyConn net.Conn) error {
-	var methods []byte
-	for method := range clt.Auth {
-		methods = append(methods, method)
-	}
-	// The client connects to the server, and sends a version identifier/method selection message:
-	//    +----+----------+----------+
-	//    |VER | NMETHODS | METHODS  |
-	//    +----+----------+----------+
-	//    | 1  |    1     | 1 to 255 |
-	//    +----+----------+----------+
-	_, err := proxyConn.Write(append([]byte{Version5, byte(len(methods))}, methods...))
-	if err != nil {
-		return nil
-	}
-	//Get reply, a METHOD selection message:
-	//    +----+--------+
-	//    |VER | METHOD |
-	//    +----+--------+
-	//    | 1  |   1    |
-	//    +----+--------+
-	reply, err := ReadNBytes(proxyConn, 2)
-	if err != nil {
-		return err
-	}
-	if reply[0] != Version5 {
-		return &VersionError{reply[0]}
-	}
-
-	// Is client has this method?
-	if _, ok := clt.Auth[reply[1]]; !ok {
-		return &MethodError{reply[1]}
-	}
-
-	// process authentication sub negotiation
-	err = clt.Auth[reply[1]].Authenticate(proxyConn, proxyConn)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// handShake4 Socks 4 version of the connection handshake
-func (clt *Client) handshake4(request *Request, proxyConn net.Conn) (*Address, error) {
-	destAddrByte, err := request.Address.Bytes(Version4)
-	if err != nil {
-		return nil, err
-	}
-	// The client connects to the SOCKS server and sends a CONNECT request when it wants to establish a connection to an application server.
-	// The client includes in the request packet the IP address and the port number of the destination host, and userid, in the following format.
-	//    +----+----+----+----+----+----+----+----+----+----+....+----+
-	//    | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
-	//    +----+----+----+----+----+----+----+----+----+----+....+----+
-	//      1    1      2              4           variable       1
-	if _, err := proxyConn.Write(append([]byte{request.VER, request.CMD}, destAddrByte...)); err != nil {
-		return nil, err
-	}
-	// A reply packet is sent to the client when this connection is established,or when the request is rejected or the operation fails.
-	//    +----+----+----+----+----+----+----+----+
-	//    | VN | CD | DSTPORT |      DSTIP        |
-	//    +----+----+----+----+----+----+----+----+
-	//       1    1      2              4
-	tmp, err := ReadNBytes(proxyConn, 2)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get reply version and command, %v", err)
-	}
-	if tmp[0] != 0 {
-		return nil, fmt.Errorf("response VN wrong[%d]", tmp[0])
-	}
-	if tmp[1] != Granted {
-		return nil, errors.New("server refuse client request")
-	}
-	// Read address
-	replyAddr, _, err := readSocks4ReplyAddress(proxyConn, request.VER)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get reply address, %v", err)
-	}
-	return replyAddr, nil
-}
-
-// Connect send CONNECT Request. Returned a connected proxy connection.
-func (clt *Client) Connect(ver VER, dest string) (*net.TCPConn, error) {
-	if ver != Version4 && ver != Version5 {
-		return nil, &VersionError{ver}
-	}
-
-	destAddr, err := ParseAddress(dest)
-	if err != nil {
-		return nil, err
-	}
-	req := &Request{
-		VER:     ver,
-		CMD:     CONNECT,
-		RSV:     0,
-		Address: destAddr,
-	}
-
-	conn, _, err := clt.handshake(req)
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
-}
-
-// UDPForward send UDP_ASSOCIATE Request.
-// The laddr Param specific Client address to send udp datagram.
-// If laddr is empty string, a local address (127.0.0.1:port) is automatically chosen.
-// If port is occupied will return error.
-func (clt *Client) UDPForward(laddr string) (*UDPConn, error) {
-	if laddr == "" {
-		laddr = "127.0.0.1:0"
-	}
-
-	// split laddr to host/port
-	host, portStr, err := net.SplitHostPort(laddr)
-	p, err := strconv.Atoi(portStr)
-	if err != nil {
-		return nil, err
-	}
-	port := uint16(p)
-
-	// zero port, will automatically chosen.
-	if port == 0 {
-		err, port = GetRandomPort("udp")
-		if err != nil {
-			return nil, errors.New("automatically chosen port fail")
-		}
-		laddr = net.JoinHostPort(host, strconv.Itoa(int(port)))
-	}
-
-	// get addr
-	addr, err := ParseAddress(laddr)
-	if err != nil {
-		return nil, err
-	}
-
-	req := &Request{
-		VER:     Version5,
-		CMD:     UDP_ASSOCIATE,
-		RSV:     0,
-		Address: addr,
-	}
-
-	// Handshake base on TCP connection
-	proxyTCPConn, UDPRelayAddr, err := clt.handshake(req)
-	if err != nil {
-		return nil, err
-	}
-
-	// Get local UDP addr
-	localUDPAddr, err := addr.UDPAddr()
-	if err != nil {
-		return nil, err
-	}
-
-	// Get udp relay server bind addr.
-	serverListenUDPAddr, err := UDPRelayAddr.UDPAddr()
-	if err != nil {
-		return nil, err
-	}
-
-	// Dial UDP relay Server
-	err = IsFreePort("udp", port)
-	if err != nil {
-		proxyTCPConn.Close()
-		return nil, fmt.Errorf("port %d is occupied", port)
-	}
-	proxyUDPConn, err := net.DialUDP("udp", localUDPAddr, serverListenUDPAddr)
-	if err != nil {
-		proxyTCPConn.Close()
-		return nil, err
-	}
-	return NewUDPConn(proxyUDPConn, proxyTCPConn), nil
-}
-
-// Bind send BIND Request. return 4 params:
-// 1. Server bind address.
-// 2. a readable chan to recv second reply from socks server.
-// 3. A connection that is not immediately available, until read a nil from err chan.
-// 4. An error, indicate the first reply result. If nil, successes.
-func (clt *Client) Bind(ver VER, destAddr string) (*Address, <-chan error, net.Conn, error) {
-	dest, err := ParseAddress(destAddr)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	request := &Request{
-		Address: dest,
-		CMD:     BIND,
-		VER:     ver,
-	}
-	proxyConn, err := net.Dial("tcp", clt.ProxyAddr)
-	if err != nil {
-		clt.logf()(err.Error())
-		return nil, nil, nil, err
-	}
-	if clt.Timeout != 0 {
-		err = proxyConn.SetDeadline(time.Now().Add(clt.Timeout))
-		if err != nil {
-			clt.logf()(err.Error())
-			return nil, nil, nil, err
-		}
-		defer proxyConn.SetDeadline(time.Time{})
-	}
-	switch request.VER {
-	case Version4:
-		serverBindAddr, secondReply, err := clt.bind4(request, proxyConn)
-		if err != nil {
-			proxyConn.Close()
-			clt.logf()(err.Error())
-			return nil, nil, nil, err
-		}
-		return serverBindAddr, secondReply, proxyConn, nil
-	case Version5:
-		serverBindAddr, secondReply, err := clt.bind5(request, proxyConn)
-		if err != nil {
-			proxyConn.Close()
-			clt.logf()(err.Error())
-			return nil, nil, nil, err
-		}
-		return serverBindAddr, secondReply, proxyConn, nil
-	default:
-		proxyConn.Close()
-		return nil, nil, nil, &VersionError{request.VER}
-	}
-}
-
-// bind5 socks5 bind
-func (clt *Client) bind5(request *Request, proxyBindConn net.Conn) (*Address, <-chan error, error) {
-	err := clt.authentication(proxyBindConn)
-	if err != nil {
-		return nil, nil, err
-	}
-	destAddrByte, err := request.Address.Bytes(Version5)
-	if err != nil {
-		return nil, nil, err
-	}
-	// The SOCKS request is formed as follows:
-	//    +----+-----+-------+------+----------+----------+
-	//	//    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
-	//	//    +----+-----+-------+------+----------+----------+
-	//	//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-	//    +----+-----+-------+------+----------+----------+
-	if _, err := proxyBindConn.Write(append([]byte{request.VER, request.CMD, request.RSV}, destAddrByte...)); err != nil {
-		return nil, nil, err
-	}
-	// reply formed as follows:
-	//    +----+-----+-------+------+----------+----------+
-	//    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
-	//    +----+-----+-------+------+----------+----------+
-	//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-	//    +----+-----+-------+------+----------+----------+
-	reply := &Reply{}
-	tmp, err := ReadNBytes(proxyBindConn, 3)
-	if err != nil {
-		return nil, nil, fmt.Errorf("failed to get reply version and command and reserved, %v", err)
-	}
-	reply.VER, reply.REP, reply.RSV = tmp[0], tmp[1], tmp[2]
-	if reply.VER != Version5 {
-		return nil, nil, fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER)
-	}
-	// read address
-	serverBoundAddr, _, err := readAddress(proxyBindConn, request.VER)
-	if err != nil {
-		return nil, nil, fmt.Errorf("failed to get reply address, %v", err)
-	}
-	reply.Address = serverBoundAddr
-	if reply.REP != SUCCESSED {
-		return nil, nil, fmt.Errorf("server refuse client request, %s,when first time reply", rep2Str[reply.REP])
-	}
-	errorChan := make(chan error)
-	go func() {
-		reply2 := &Reply{}
-		// The second time reply formed as follows:
-		//    +----+-----+-------+------+----------+----------+
-		//    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
-		//    +----+-----+-------+------+----------+----------+
-		//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-		//    +----+-----+-------+------+----------+----------+
-		tmp, err := ReadNBytes(proxyBindConn, 3)
-		if err != nil {
-			errorChan <- fmt.Errorf("failed to get reply version and command and reserved, %v", err)
-			proxyBindConn.Close()
-		}
-		reply2.VER, reply2.REP, reply2.RSV = tmp[0], tmp[1], tmp[2]
-		if reply2.VER != Version5 {
-			errorChan <- fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER)
-			proxyBindConn.Close()
-		}
-		// read address
-		serverBoundAddr, _, err := readAddress(proxyBindConn, request.VER)
-		if err != nil {
-			errorChan <- fmt.Errorf("failed to get reply address, %v", err)
-			proxyBindConn.Close()
-		}
-		reply2.Address = serverBoundAddr
-		if reply2.REP != SUCCESSED {
-			errorChan <- errors.New("server refuse client request,when second time reply")
-			proxyBindConn.Close()
-		}
-		errorChan <- nil
-	}()
-	return serverBoundAddr, errorChan, nil
-}
-
-// bind4 socks4 bind
-func (clt *Client) bind4(request *Request, proxyBindConn net.Conn) (*Address, <-chan error, error) {
-	destAddrByte, err := request.Address.Bytes(Version4)
-	if err != nil {
-		return nil, nil, err
-	}
-	// The client connects to the SOCKS server and sends a CONNECT request when it wants to establish a connection to an application server.
-	// The client includes in the request packet the IP address and the port number of the destination host, and userid, in the following format.
-	//    +----+----+----+----+----+----+----+----+----+----+....+----+
-	//    | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
-	//    +----+----+----+----+----+----+----+----+----+----+....+----+
-	//      1    1      2              4           variable       1
-	if _, err := proxyBindConn.Write(append([]byte{request.VER, request.CMD}, destAddrByte...)); err != nil {
-		return nil, nil, err
-	}
-	// A reply packet is sent to the client when this connection is established,or when the request is rejected or the operation fails.
-	//    +----+----+----+----+----+----+----+----+
-	//    | VN | CD | DSTPORT |      DSTIP        |
-	//    +----+----+----+----+----+----+----+----+
-	//       1    1      2              4
-	tmp, err := ReadNBytes(proxyBindConn, 2)
-	if err != nil {
-		return nil, nil, fmt.Errorf("failed to get reply version and command, %v", err)
-	}
-	if tmp[0] != 0 {
-		return nil, nil, fmt.Errorf("response VN wrong[%d]", tmp[0])
-	}
-	// Read address
-	serverBoundAddr, _, err := readSocks4ReplyAddress(proxyBindConn, request.VER)
-	if err != nil {
-		return nil, nil, fmt.Errorf("failed to get reply address, %v", err)
-	}
-	if tmp[1] != Granted {
-		return nil, nil, errors.New("server refuse client request,when first time reply")
-	}
-	errorChan := make(chan error)
-	go func() {
-		// A reply packet is sent to the client,or when the request is rejected or the operation fails.
-		//    +----+----+----+----+----+----+----+----+
-		//    | VN | CD | DSTPORT |      DSTIP        |
-		//    +----+----+----+----+----+----+----+----+
-		//       1    1      2              4
-		tmp, err := ReadNBytes(proxyBindConn, 2)
-		if err != nil {
-			errorChan <- fmt.Errorf("failed to get reply version and command, %v", err)
-			proxyBindConn.Close()
-		}
-		if tmp[0] != 0 {
-			errorChan <- fmt.Errorf("response VN wrong[%d]", tmp[0])
-			proxyBindConn.Close()
-		}
-		// read address
-		_, _, err = readSocks4ReplyAddress(proxyBindConn, request.VER)
-		if err != nil {
-			errorChan <- fmt.Errorf("failed to get reply address, %v", err)
-			proxyBindConn.Close()
-		}
-
-		if tmp[1] != Granted {
-			errorChan <- errors.New("server refuse client request,when second time reply")
-			proxyBindConn.Close()
-		}
-		errorChan <- nil
-	}()
-	return serverBoundAddr, errorChan, nil
-}
-
-// logf Logging is done using the client's errorlog
-func (clt *Client) logf() func(format string, args ...interface{}) {
-	if clt.ErrorLog == nil {
-		return log.Printf
-	}
-	return clt.ErrorLog.Printf
-}
diff --git a/vendor/github.com/kalikaneko/socks5/common.go b/vendor/github.com/kalikaneko/socks5/common.go
deleted file mode 100644
index ea64b2f5..00000000
--- a/vendor/github.com/kalikaneko/socks5/common.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package socks5
-
-import (
-	"bytes"
-	"errors"
-	"io"
-)
-
-var errUnexpectMinusLength = errors.New("arg number should not be minus")
-
-// ReadNBytes wrap io.ReadFull. read n bytes.
-// The error is EOF only if no bytes were read.
-// If an EOF happens after reading some but not all the bytes,
-// ReadFull returns ErrUnexpectedEOF.
-func ReadNBytes(reader io.Reader, n int) ([]byte, error) {
-	if n < 0 {
-		return nil, errUnexpectMinusLength
-	}
-	data := make([]byte, n)
-	_, err := io.ReadFull(reader, data)
-	if err != nil {
-		return nil, err
-	}
-
-	return data, nil
-}
-
-// ReadUntilNULL Read all not Null byte.
-// Until read first Null byte(all zero bits)
-func ReadUntilNULL(reader io.Reader) ([]byte, error) {
-	data := &bytes.Buffer{}
-	b := make([]byte, 1)
-	for {
-		_, err := reader.Read(b)
-		if err != nil {
-			if err == io.EOF {
-				return nil, nil
-			}
-			return nil, err
-		}
-
-		if b[0] == NULL {
-			return data.Bytes(), nil
-		}
-		data.WriteByte(b[0])
-	}
-}
diff --git a/vendor/github.com/kalikaneko/socks5/conn.go b/vendor/github.com/kalikaneko/socks5/conn.go
deleted file mode 100644
index a94aee21..00000000
--- a/vendor/github.com/kalikaneko/socks5/conn.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package socks5
-
-import (
-	"io"
-	"net"
-	"sync"
-	"time"
-)
-
-// UDPConn be associated with TCP connections.
-// The UDP connection will close immediately, When TCP connection closed,
-// UDPConn only use in UDP_ASSOCIATE command.
-type UDPConn struct {
-	mu        sync.Mutex
-	udp       *net.UDPConn
-	tcp       *net.TCPConn
-	closeChan chan struct{}
-}
-
-// NewUDPConn get a *UDPConn through provide a tcp and udp connection.
-// the tcp connection is used for socks UDP_ASSOCIATE handshake.
-// the udp connection is used for socks udp forwarding.
-//
-// After UDP_ASSOCIATE handshake, the tcp transit nothing. Its only
-// function is udp relay connection still running.
-//
-// If one of them shuts off, it will close them all.
-func NewUDPConn(udp *net.UDPConn, tcp *net.TCPConn) *UDPConn {
-	if udp == nil || tcp == nil {
-		return nil
-	}
-
-	u := &UDPConn{
-		udp:       udp,
-		tcp:       tcp,
-		closeChan: make(chan struct{}),
-	}
-
-	go func() {
-		// guard tcp connection, if it closed should close tcp relay too.
-		io.Copy(io.Discard, tcp)
-		u.Close()
-	}()
-
-	return u
-}
-
-func (u *UDPConn) LocalAddr() net.Addr {
-	return u.udp.LocalAddr()
-}
-
-func (u *UDPConn) RemoteAddr() net.Addr {
-	return u.udp.RemoteAddr()
-}
-
-func (u *UDPConn) SetDeadline(t time.Time) error {
-	return u.udp.SetDeadline(t)
-}
-
-func (u *UDPConn) SetReadDeadline(t time.Time) error {
-	return u.udp.SetReadDeadline(t)
-}
-
-func (u *UDPConn) SetWriteDeadline(t time.Time) error {
-	return u.udp.SetWriteDeadline(t)
-}
-
-func (u *UDPConn) Read(b []byte) (n int, err error) {
-	return u.udp.Read(b)
-}
-
-func (u *UDPConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) {
-	return u.udp.WriteToUDP(b, addr)
-}
-
-func (u *UDPConn) ReadFromUDP(b []byte) (int, *net.UDPAddr, error) {
-	return u.udp.ReadFromUDP(b)
-}
-
-func (u *UDPConn) Write(b []byte) (n int, err error) {
-	return u.udp.Write(b)
-}
-
-func (u *UDPConn) Close() error {
-	var err error
-	u.mu.Lock()
-	defer u.mu.Unlock()
-
-	ch := u.getCloseChanLocked()
-	select {
-	case <-ch:
-		return nil
-	default:
-		if err2 := u.udp.Close(); err2 != nil {
-			err = err2
-		}
-		if err2 := u.tcp.Close(); err2 != nil {
-			err = err2
-		}
-		close(u.closeChan)
-	}
-	return err
-}
-
-func (u *UDPConn) CloseCh() <-chan struct{} {
-	u.mu.Lock()
-	defer u.mu.Unlock()
-	return u.getCloseChanLocked()
-}
-
-func (u *UDPConn) getCloseChanLocked() <-chan struct{} {
-	if u.closeChan == nil {
-		u.closeChan = make(chan struct{})
-	}
-	return u.closeChan
-}
diff --git a/vendor/github.com/kalikaneko/socks5/port.go b/vendor/github.com/kalikaneko/socks5/port.go
deleted file mode 100644
index 5e1a8524..00000000
--- a/vendor/github.com/kalikaneko/socks5/port.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package socks5
-
-import (
-	"errors"
-	"net"
-	"strconv"
-	"strings"
-)
-
-// GetRandomPort return a random port by specific network.
-// The network must be "tcp", "udp".
-func GetRandomPort(network string) (err error, port uint16) {
-	network = strings.ToLower(network)
-	addr := "0.0.0.0:0"
-
-	switch network {
-	case "tcp", "tcp4", "tcp6":
-		tcpAddr, err := net.ResolveTCPAddr(network, addr)
-		if err != nil {
-			return err, 0
-		}
-		ln, err := net.ListenTCP(network, tcpAddr)
-		if err != nil {
-			return err, 0
-		}
-
-		_, portStr, err := net.SplitHostPort(ln.Addr().String())
-		p, err := strconv.Atoi(portStr)
-		port = uint16(p)
-
-		err = ln.Close()
-		if err != nil {
-			return err, 0
-		}
-		return err, port
-	case "udp", "udp4", "udp6":
-		udpAddr, err := net.ResolveUDPAddr(network, addr)
-		if err != nil {
-			return err, 0
-		}
-		ln, err := net.ListenUDP(network, udpAddr)
-		if err != nil {
-			return err, 0
-		}
-
-		_, portStr, err := net.SplitHostPort(ln.LocalAddr().String())
-		p, err := strconv.Atoi(portStr)
-		port = uint16(p)
-
-		err = ln.Close()
-		if err != nil {
-			return err, 0
-		}
-		return err, port
-	default:
-		return errors.New("unknown network type " + network), 0
-	}
-}
-
-// IsFreePort indicates the port is available.
-// The network must be "tcp", "udp".
-func IsFreePort(network string, port uint16) error {
-	network = strings.ToLower(network)
-	portStr := strconv.Itoa(int(port))
-	addr := "0.0.0.0:" + portStr
-
-	switch network {
-	case "tcp":
-		tcpAddr, err := net.ResolveTCPAddr(network, addr)
-		if err != nil {
-			return err
-		}
-		ln, err := net.ListenTCP(network, tcpAddr)
-		if err != nil {
-			return err
-		}
-
-		ln.Close()
-		if err != nil {
-			return err
-		}
-		return nil
-	case "udp":
-		udpAddr, err := net.ResolveUDPAddr(network, addr)
-		if err != nil {
-			return err
-		}
-		ln, err := net.ListenUDP(network, udpAddr)
-		if err != nil {
-			return err
-		}
-
-		ln.Close()
-		if err != nil {
-			return err
-		}
-		return nil
-	default:
-		return errors.New("unknown network type " + network)
-	}
-}
diff --git a/vendor/github.com/kalikaneko/socks5/protocol.go b/vendor/github.com/kalikaneko/socks5/protocol.go
deleted file mode 100644
index d0194eaf..00000000
--- a/vendor/github.com/kalikaneko/socks5/protocol.go
+++ /dev/null
@@ -1,155 +0,0 @@
-package socks5
-
-import "fmt"
-
-type VersionError struct {
-	VER
-}
-
-func (v *VersionError) Error() string {
-	return fmt.Sprintf("error socks protocol version: %d", v.VER)
-}
-
-// VER indicates protocol version
-type VER = uint8
-
-const (
-	Version4 = 0x04
-	Version5 = 0x05
-)
-
-type MethodError struct {
-	METHOD
-}
-
-func (m *MethodError) Error() string {
-	if _, ok := method2Str[m.METHOD]; ok {
-		return fmt.Sprintf("don't support this method %s", method2Str[m.METHOD])
-	} else {
-		return fmt.Sprintf("unknown mehotd %#x", m.METHOD)
-	}
-}
-
-// METHOD Defined authentication methods
-type METHOD = uint8
-
-const (
-	NO_AUTHENTICATION_REQUIRED METHOD = 0x00
-	GSSAPI                     METHOD = 0x01
-	USERNAME_PASSWORD          METHOD = 0x02
-	IANA_ASSIGNED              METHOD = 0x03
-	NO_ACCEPTABLE_METHODS      METHOD = 0xff
-)
-
-var method2Str = map[METHOD]string{
-	NO_AUTHENTICATION_REQUIRED: "NO_AUTHENTICATION_REQUIRED",
-	GSSAPI:                     "GSSAPI",
-	USERNAME_PASSWORD:          "USERNAME_PASSWORD",
-	IANA_ASSIGNED:              "IANA_ASSIGNED",
-	NO_ACCEPTABLE_METHODS:      "NO_ACCEPTABLE_METHODS",
-}
-
-// CMDError cmd error type
-type CMDError struct {
-	CMD
-}
-
-func (c *CMDError) Error() string {
-	if _, ok := cmd2Str[c.CMD]; !ok {
-		return fmt.Sprintf("unknown command:%#x", c.CMD)
-	}
-	return fmt.Sprintf("don't support this command:%s", cmd2Str[c.CMD])
-}
-
-// CMD is one of a field in Socks5 Request
-type CMD = uint8
-
-const (
-	CONNECT       CMD = 0x01
-	BIND          CMD = 0x02
-	UDP_ASSOCIATE CMD = 0x03
-)
-
-var cmd2Str = map[CMD]string{
-	CONNECT:       "CONNECT",
-	BIND:          "BIND",
-	UDP_ASSOCIATE: "UDP_ASSOCIATE",
-	Rejected:      "Rejected",
-	Granted:       "Granted",
-}
-
-type REPError struct {
-	REP
-}
-
-func (r *REPError) Error() string {
-	if _, ok := cmd2Str[r.REP]; !ok {
-		return fmt.Sprintf("unknown rep:%#x", r.REP)
-	}
-	return fmt.Sprintf("don't support this rep:%s", rep2Str[r.REP])
-}
-
-// REP is one of a filed in Socks5 Reply
-type REP = uint8
-
-//socks5 reply
-const (
-	SUCCESSED                       REP = 0x00
-	GENERAL_SOCKS_SERVER_FAILURE    REP = 0x01
-	CONNECTION_NOT_ALLOW_BY_RULESET REP = 0x02
-	NETWORK_UNREACHABLE             REP = 0x03
-	HOST_UNREACHABLE                REP = 0x04
-	CONNECTION_REFUSED              REP = 0x05
-	TTL_EXPIRED                     REP = 0x06
-	COMMAND_NOT_SUPPORTED           REP = 0x07
-	ADDRESS_TYPE_NOT_SUPPORTED      REP = 0x08
-	UNASSIGNED                      REP = 0x09
-)
-
-var rep2Str = map[REP]string{
-	SUCCESSED:                       "successes",
-	GENERAL_SOCKS_SERVER_FAILURE:    "general_socks_server_failure",
-	CONNECTION_NOT_ALLOW_BY_RULESET: "connection_not_allow_by_ruleset",
-	NETWORK_UNREACHABLE:             "network_unreachable",
-	HOST_UNREACHABLE:                "host_unreachable",
-	CONNECTION_REFUSED:              "connection_refused",
-	TTL_EXPIRED:                     "ttl_expired",
-	COMMAND_NOT_SUPPORTED:           "command_not_supported",
-	ADDRESS_TYPE_NOT_SUPPORTED:      "address_type_not_supported",
-	UNASSIGNED:                      "unassigned",
-	Granted:                         "granted",
-	Rejected:                        "rejected",
-}
-
-//socks4 reply
-const (
-	// Granted means server allow  client request
-	Granted = 90
-	// Rejected means server refuse client request
-	Rejected = 91
-)
-
-type AtypeError struct {
-	ATYPE
-}
-
-func (a *AtypeError) Error() string {
-	return fmt.Sprintf("unknown address type:%#x", a.ATYPE)
-}
-
-// ATYPE indicates address type in Request and Reply struct
-type ATYPE = uint8
-
-const (
-	IPV4_ADDRESS ATYPE = 0x01
-	DOMAINNAME   ATYPE = 0x03
-	IPV6_ADDRESS ATYPE = 0x04
-)
-
-var atype2Str = map[ATYPE]string{
-	IPV4_ADDRESS: "IPV4_ADDRESS",
-	DOMAINNAME:   "DOMAINNAME",
-	IPV6_ADDRESS: "IPV6_ADDRESS",
-}
-
-const NULL byte = 0
diff --git a/vendor/github.com/kalikaneko/socks5/reply.go b/vendor/github.com/kalikaneko/socks5/reply.go
deleted file mode 100644
index 4cf3b043..00000000
--- a/vendor/github.com/kalikaneko/socks5/reply.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package socks5
-
-// Reply a reply formed as follows:
-//    +----+-----+-------+------+----------+----------+
-//    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
-//    +----+-----+-------+------+----------+----------+
-//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-//    +----+-----+-------+------+----------+----------+
-type Reply struct {
-	VER
-	REP
-	RSV uint8
-	*Address
-}
diff --git a/vendor/github.com/kalikaneko/socks5/request.go b/vendor/github.com/kalikaneko/socks5/request.go
deleted file mode 100644
index ecfea039..00000000
--- a/vendor/github.com/kalikaneko/socks5/request.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package socks5
-
-import (
-	"bytes"
-	"errors"
-)
-
-// Request The SOCKS request is formed as follows:
-//    +----+-----+-------+------+----------+----------+
-//    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
-//    +----+-----+-------+------+----------+----------+
-//    | 1  |  1  | X'00' |  1   | Variable |    2     |
-//    +----+-----+-------+------+----------+----------+
-type Request struct {
-	VER
-	CMD
-	RSV uint8
-	*Address
-}
-
-// UDPHeader Each UDP datagram carries a UDP request
-// header with it:
-//    +----+------+------+----------+----------+----------+
-//    |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
-//    +----+------+------+----------+----------+----------+
-//    | 2  |  1   |  1   | Variable |    2     | Variable |
-//    +----+------+------+----------+----------+----------+
-type UDPHeader struct {
-	RSV  uint16
-	FRAG uint8
-	*Address
-	Data []byte
-}
-
-var errEmptyPayload = errors.New("empty payload")
-
-// PackUDPData add UDP request header before payload.
-func PackUDPData(addr *Address, payload []byte) ([]byte, error) {
-	if len(payload) == 0 {
-		return nil, errEmptyPayload
-	}
-	if addr == nil {
-		return nil, errors.New("addr is nil")
-	}
-	// RSV, FRAG
-	data := []byte{0x00, 0x00, 0x00}
-	dest, err := addr.Bytes(Version5)
-	if err != nil {
-		return nil, err
-	}
-	// ATYP, DEST.IP, DEST.PORT
-	data = append(data, dest...)
-	// DATA
-	data = append(data, payload...)
-	return data, nil
-}
-
-// UnpackUDPData split UDP header and payload.
-func UnpackUDPData(data []byte) (addr *Address, payload []byte, err error) {
-	// trim RSV, FRAG
-	data = data[3:]
-	buf := bytes.NewBuffer(data)
-	addr, _, err = readAddress(buf, Version5)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	payload = buf.Bytes()
-	return
-}
diff --git a/vendor/github.com/kalikaneko/socks5/server.go b/vendor/github.com/kalikaneko/socks5/server.go
deleted file mode 100644
index 33059e2a..00000000
--- a/vendor/github.com/kalikaneko/socks5/server.go
+++ /dev/null
@@ -1,653 +0,0 @@
-package socks5
-
-import (
-	"errors"
-	"io"
-	"log"
-	"net"
-	"strconv"
-	"sync"
-	"sync/atomic"
-	"time"
-)
-
-// Server defines parameters for running socks server.
-// The zero value for Server is a valid configuration(tcp listen on :1080).
-type Server struct {
-	// Addr optionally specifies the TCP address for the server to listen on,
-	// in the form "host:port". If empty, ":1080" (port 1080) is used.
-	Addr string
-
-	// BindIP specific UDP relay server IP and bind listen IP.
-	// It shouldn't be ipv4zero like "0,0,0,0" or ipv6zero like [:]
-	// If empty, localhost used.
-	BindIP string
-
-	// ReadTimeout is the maximum duration for reading from socks client.
-	// it's only effective to socks server handshake process.
-	//
-	// If zero, there is no timeout.
-	ReadTimeout time.Duration
-
-	// WriteTimeout is the maximum duration for writing to socks client.
-	// it's only effective to socks server handshake process.
-	//
-	// If zero, there is no timeout.
-	WriteTimeout time.Duration
-
-	// method mapping to the authenticator
-	// if nil server provide NO_AUTHENTICATION_REQUIRED method by default
-	Authenticators map[METHOD]Authenticator
-
-	// The server select method to use policy
-	//MethodSelector
-
-	Dial DialFunc
-
-	// Server transmit data between client and dest server.
-	// if nil, DefaultTransport is used.
-	Transporter
-
-	// ErrorLog specifics an options logger for errors accepting
-	// connections, unexpected socks protocol handshake process,
-	// and server to remote connection errors.
-	// If nil, logging is done via log package's standard logger.
-	ErrorLog *log.Logger
-
-	// DisableSocks4, disable socks4 server, default enable socks4 compatible.
-	DisableSocks4 bool
-
-	// 1 indicate server is shutting down.
-	// 0 indicate server is running.
-	// Atomic operation must be guaranteed.
-	isShutdown int32
-
-	mu         sync.Mutex
-	listeners  map[*net.Listener]struct{}
-	activeConn map[net.Conn]struct{}
-	doneCh     chan struct{}
-}
-
-type DialFunc func(string, string) (net.Conn, error)
-
-func (srv *Server) getDoneChan() <-chan struct{} {
-	srv.mu.Lock()
-	defer srv.mu.Unlock()
-	return srv.getDoneChanLocked()
-}
-
-func (srv *Server) getDoneChanLocked() chan struct{} {
-	if srv.doneCh == nil {
-		srv.doneCh = make(chan struct{})
-	}
-	return srv.doneCh
-}
-
-func (srv *Server) closeDoneChanLocked() {
-	ch := srv.getDoneChanLocked()
-	select {
-	case <-ch:
-	default:
-		close(srv.doneCh)
-	}
-}
-
-func (srv *Server) Close() error {
-	atomic.StoreInt32(&srv.isShutdown, 1)
-	srv.mu.Lock()
-	defer srv.mu.Unlock()
-	// close all listeners.
-	err := srv.closeListenerLocked()
-	if err != nil {
-		return err
-	}
-	// close doneCh to broadcast close message.
-	srv.closeDoneChanLocked()
-	// Close all open connections.
-	for conn, _ := range srv.activeConn {
-		conn.Close()
-	}
-	return nil
-}
-
-func (srv *Server) inShuttingDown() bool {
-	return atomic.LoadInt32(&srv.isShutdown) != 0
-}
-
-func (srv *Server) closeListenerLocked() error {
-	var err error
-	for ln := range srv.listeners {
-		if cerr := (*ln).Close(); cerr != nil {
-			err = cerr
-		}
-	}
-	return err
-}
-
-// trackListener adds or removes a net.Listener to the set of tracked
-// listeners.
-//
-// We store a pointer to interface in the map set, in case the
-// net.Listener is not comparable. This is safe because we only call
-// trackListener via Serve and can track+defer untrack the same
-// pointer to local variable there. We never need to compare a
-// Listener from another caller.
-//
-// It reports whether the server is still up (not Shutdown or Closed).
-func (srv *Server) trackListener(l *net.Listener, add bool) bool {
-	srv.mu.Lock()
-	defer srv.mu.Unlock()
-	if srv.listeners == nil {
-		srv.listeners = make(map[*net.Listener]struct{})
-	}
-
-	if add {
-		if srv.inShuttingDown() {
-			return false
-		}
-		srv.listeners[l] = struct{}{}
-	} else {
-		delete(srv.listeners, l)
-	}
-	return true
-}
-
-func (srv *Server) trackConn(c net.Conn, add bool) {
-	srv.mu.Lock()
-	defer srv.mu.Unlock()
-	if srv.activeConn == nil {
-		srv.activeConn = make(map[net.Conn]struct{})
-	}
-	if add {
-		srv.activeConn[c] = struct{}{}
-	} else {
-		delete(srv.activeConn, c)
-	}
-}
-
-// ListenAndServe listens on the TCP network address srv.Addr and then
-// calls serve to handle requests on incoming connections.
-//
-// If srv.Addr is blank, ":1080" is used.
-func (srv *Server) ListenAndServe() error {
-	if srv.inShuttingDown() {
-		return ErrServerClosed
-	}
-
-	addr := srv.Addr
-	if addr == "" {
-		addr = "0.0.0.0:1080"
-	}
-
-	if srv.BindIP == "" {
-		srv.BindIP = "localhost"
-	} else if srv.BindIP == net.IPv4zero.String() || srv.BindIP == net.IPv6zero.String() {
-		return errors.New("socks: server bindIP shouldn't be zero")
-	}
-
-	ln, err := net.Listen("tcp", addr)
-	if err != nil {
-		return err
-	}
-	return srv.Serve(ln)
-}
-
-// ErrServerClosed is returned by the Server's Serve, ListenAndServe methods after a call to Shutdown or Close.
-var ErrServerClosed = errors.New("socks: Server closed")
-
-// Serve accepts incoming connections on the Listener l, creating a
-// new service goroutine for each. The service goroutine select client
-// list methods and reply client. Then process authentication and reply
-// to them. At then end of handshake, read socks request from client and
-// establish a connection to the target.
-func (srv *Server) Serve(l net.Listener) error {
-	srv.trackListener(&l, true)
-	defer srv.trackListener(&l, false)
-
-	var tempDelay time.Duration
-
-	for {
-		client, err := l.Accept()
-		if err != nil {
-			select {
-			case <-srv.getDoneChan():
-				return ErrServerClosed
-			default:
-			}
-			if ne, ok := err.(net.Error); ok && ne.Temporary() {
-				if tempDelay == 0 {
-					tempDelay = 5 * time.Millisecond
-				} else {
-					tempDelay *= 2
-				}
-				if max := time.Second; tempDelay > max {
-					tempDelay = max
-				}
-				srv.logf()("socks: Accept error: %v, retrying in %v", err, tempDelay)
-				time.Sleep(tempDelay)
-				continue
-			}
-			return err
-		}
-		go srv.serveconn(client)
-	}
-}
-
-func (srv *Server) serveconn(client net.Conn) {
-	if srv.ReadTimeout != 0 {
-		client.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
-	}
-	if srv.WriteTimeout != 0 {
-		client.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
-	}
-
-	// handshake
-	request, err := srv.handShake(client)
-	if err != nil {
-		srv.logf()(err.Error())
-		client.Close()
-		return
-	}
-
-	// establish connection to remote
-	remote, err := srv.establish(client, request)
-	if err != nil {
-		srv.logf()(err.Error())
-		client.Close()
-		return
-	}
-
-	// establish over, reset deadline.
-	client.SetReadDeadline(time.Time{})
-	client.SetWriteDeadline(time.Time{})
-
-	// transport data
-	switch request.CMD {
-	case CONNECT, BIND:
-		srv.trackConn(client, true)
-		defer srv.trackConn(client, false)
-		srv.trackConn(remote, true)
-		defer srv.trackConn(remote, false)
-
-		errCh := srv.transport().TransportTCP(client, remote)
-		for err := range errCh {
-			if err != nil {
-				srv.logf()(err.Error())
-			}
-		}
-	case UDP_ASSOCIATE:
-		relay := NewUDPConn(remote.(*net.UDPConn), client.(*net.TCPConn))
-		srv.trackConn(relay, true)
-		defer srv.trackConn(relay, false)
-
-		err = srv.transport().TransportUDP(relay, request)
-		if err != nil {
-			srv.logf()(err.Error())
-		}
-	}
-}
-
-func (srv *Server) transport() Transporter {
-	if srv.Transporter == nil {
-		return DefaultTransporter
-	}
-	return srv.Transporter
-}
-
-func (srv *Server) dialFn() DialFunc {
-	if srv.Dial == nil {
-		return net.Dial
-	}
-	return srv.Dial
-}
-
-var errDisableSocks4 = errors.New("socks4 server has been disabled")
-
-// handShake socks protocol handshake process
-func (srv *Server) handShake(client net.Conn) (*Request, error) {
-	//validate socks version message
-	_, err := checkVersion(client)
-
-	if err != nil {
-		return nil, &OpError{Version5, "read", client.RemoteAddr(), "\"check version\"", err}
-	}
-
-	//socks5 protocol authentication
-	err = srv.authentication(client)
-	if err != nil {
-		return nil, err
-	}
-
-	//handle socks5 request
-	return srv.readSocks5Request(client)
-}
-
-// authentication socks5 authentication process
-func (srv *Server) authentication(client net.Conn) error {
-	//get nMethods
-	nMethods, err := ReadNBytes(client, 1)
-	if err != nil {
-		return err
-	}
-
-	//Get methods
-	methods, err := ReadNBytes(client, int(nMethods[0]))
-	if err != nil {
-		return err
-	}
-
-	return srv.MethodSelect(methods, client)
-}
-
-// readSocks5Request read socks5 protocol client request.
-func (srv *Server) readSocks5Request(client net.Conn) (*Request, error) {
-	reply := &Reply{
-		VER:     Version5,
-		Address: &Address{net.IPv4zero, IPV4_ADDRESS, 0},
-	}
-	req := &Request{}
-	//VER, CMD, RSV
-	cmd, err := ReadNBytes(client, 3)
-	if err != nil {
-		return nil, &OpError{req.VER, "read", client.RemoteAddr(), "\"process request ver,cmd,rsv\"", err}
-	}
-	req.VER = cmd[0]
-	req.CMD = cmd[1]
-	req.RSV = cmd[2]
-	// ATYPE, DST.IP, DST.PORT
-	addr, rep, err := readAddress(client, req.VER)
-	if err != nil {
-		reply.REP = rep
-		err := srv.sendReply(client, reply)
-		if err != nil {
-			return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request address\"", err}
-		}
-	}
-	req.Address = addr
-
-	return req, nil
-}
-
-// IsAllowNoAuthRequired  return true if server enable NO_AUTHENTICATION_REQUIRED.
-// Or the server doesn't has no Authenticator return true. Otherwise return false.
-func (srv *Server) IsAllowNoAuthRequired() bool {
-	if len(srv.Authenticators) == 0 {
-		return true
-	}
-	for method := range srv.Authenticators {
-		if method == NO_AUTHENTICATION_REQUIRED {
-			return true
-		}
-	}
-	return false
-}
-
-// establish tcp connection to remote host if command is CONNECT or
-// start listen on udp socket when command is UDP_ASSOCIATE. Listen
-// and accept host connection when command is BIND. Finally, send
-// corresponding reply to client.
-func (srv *Server) establish(client net.Conn, req *Request) (dest net.Conn, err error) {
-	reply := &Reply{
-		VER:     req.VER,
-		Address: &Address{net.IPv4zero, IPV4_ADDRESS, 0},
-	}
-	if req.VER != Version5 {
-		// unknown version
-		return nil, &VersionError{req.VER}
-	}
-
-	switch req.CMD {
-	case CONNECT:
-		// dial dest host.
-		dest, err = srv.dialFn()("tcp", req.Address.String())
-		if err != nil {
-			reply.REP = HOST_UNREACHABLE
-			err2 := srv.sendReply(client, reply)
-			if err2 != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2}
-
-			}
-			return nil, err
-		}
-
-		// parse remote host address.
-		remoteAddr, err := ParseAddress(dest.RemoteAddr().String())
-		if err != nil {
-			reply.REP = GENERAL_SOCKS_SERVER_FAILURE
-			err2 := srv.sendReply(client, reply)
-			if err2 != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2}
-			}
-			return nil, err
-		}
-		reply.Address = remoteAddr
-
-		// success
-		reply.REP = SUCCESSED
-		err = srv.sendReply(client, reply)
-		if err != nil {
-			return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-		}
-	case UDP_ASSOCIATE:
-		addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(srv.BindIP, "0"))
-		if err != nil {
-			return nil, err
-		}
-
-		// start udp listening on random port.
-		dest, err = net.ListenUDP("udp", addr)
-		if err != nil {
-			reply.REP = GENERAL_SOCKS_SERVER_FAILURE
-			err2 := srv.sendReply(client, reply)
-			if err2 != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2}
-			}
-			return nil, err
-		}
-
-		// success
-		reply.REP = SUCCESSED
-		relayAddr, err := ParseAddress(dest.LocalAddr().String())
-		if err != nil {
-			return nil, err
-		}
-		reply.Address = relayAddr
-		err = srv.sendReply(client, reply)
-		if err != nil {
-			return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-		}
-	case BIND:
-		bindAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(srv.BindIP, "0"))
-		if err != nil {
-			return nil, err
-		}
-
-		// start tcp listening on random port.
-		bindServer, err := net.ListenTCP("tcp", bindAddr)
-		if err != nil {
-			reply.REP = GENERAL_SOCKS_SERVER_FAILURE
-			err2 := srv.sendReply(client, reply)
-			if err2 != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2}
-			}
-			return nil, err
-		}
-		defer bindServer.Close()
-		reply.REP = SUCCESSED
-		reply.Address, err = ParseAddress(bindServer.Addr().String())
-		if err != nil {
-			return nil, err
-		}
-
-		// send first reply to client.
-		err = srv.sendReply(client, reply)
-		if err != nil {
-			return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-		}
-		dest, err = bindServer.Accept()
-		if err != nil {
-			reply.REP = GENERAL_SOCKS_SERVER_FAILURE
-			err2 := srv.sendReply(client, reply)
-			if err2 != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2}
-			}
-			return nil, err
-		}
-
-		// send second reply to client.
-		if req.Address.String() == dest.RemoteAddr().String() {
-			reply.Address, err = ParseAddress(dest.RemoteAddr().String())
-			if err != nil {
-				return nil, err
-			}
-			err = srv.sendReply(client, reply)
-			if err != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-			}
-		} else {
-			reply.REP = GENERAL_SOCKS_SERVER_FAILURE
-			err = srv.sendReply(client, reply)
-			if err != nil {
-				return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-			}
-		}
-	default:
-		reply.REP = COMMAND_NOT_SUPPORTED
-		err = srv.sendReply(client, reply)
-		if err != nil {
-			return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err}
-		}
-
-		return nil, &OpError{Version5, "", client.RemoteAddr(), "\"process request\"", &CMDError{req.CMD}}
-	}
-	return
-}
-
-// sendReply The server send socks protocol reply to client
-func (srv *Server) sendReply(out io.Writer, r *Reply) error {
-	var reply []byte
-	var err error
-
-	if r.VER == Version4 {
-		if r.Address.ATYPE != IPV4_ADDRESS {
-			return errErrorATPE
-		}
-		addr, err := r.Address.Bytes(r.VER)
-		if err != nil {
-			return err
-		}
-		reply = append(reply, 0, r.REP)
-		// Remove NULL at the end. Please see Address.Bytes() Method.
-		reply = append(reply, addr[:len(addr)-1]...)
-	} else if r.VER == Version5 {
-		addr, err := r.Address.Bytes(r.VER)
-		if err != nil {
-			return err
-		}
-		reply = append(reply, r.VER, r.REP, r.RSV)
-		reply = append(reply, addr...)
-	} else {
-		return &VersionError{r.VER}
-	}
-
-	_, err = out.Write(reply)
-	return err
-}
-
-// MethodSelect select authentication method and reply to client.
-func (srv *Server) MethodSelect(methods []CMD, client net.Conn) error {
-	// Select method to authenticate, then send selected method to client.
-	for _, method := range methods {
-		//Preferred to use NO_AUTHENTICATION_REQUIRED method
-		if method == NO_AUTHENTICATION_REQUIRED && srv.IsAllowNoAuthRequired() {
-			reply := []byte{Version5, NO_AUTHENTICATION_REQUIRED}
-			_, err := client.Write(reply)
-			if err != nil {
-				return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err}
-			}
-			return nil
-		}
-		for m := range srv.Authenticators {
-			//Select the first matched method to authenticate
-			if m == method {
-				reply := []byte{Version5, method}
-				_, err := client.Write(reply)
-				if err != nil {
-					return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err}
-				}
-
-				err = srv.Authenticators[m].Authenticate(client, client)
-				if err != nil {
-					return &OpError{Version5, "", client.RemoteAddr(), "authentication", err}
-				}
-				return nil
-			}
-		}
-	}
-
-	// There are no Methods can use
-	reply := []byte{Version5, NO_ACCEPTABLE_METHODS}
-	_, err := client.Write(reply)
-	if err != nil {
-		return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err}
-	}
-	return &OpError{Version5, "", client.RemoteAddr(), "authentication", &MethodError{methods[0]}}
-}
-
-func (srv *Server) logf() func(format string, args ...interface{}) {
-	if srv.ErrorLog == nil {
-		return log.Printf
-	}
-	return srv.ErrorLog.Printf
-}
-
-// checkVersion check version is 4 or 5.
-func checkVersion(in io.Reader) (VER, error) {
-	version, err := ReadNBytes(in, 1)
-	if err != nil {
-		return 0, err
-	}
-
-	if (version[0] != Version5) && (version[0] != Version4) {
-		return 0, &VersionError{version[0]}
-	}
-	return version[0], nil
-}
-
-// OpError is the error type usually returned by functions in the socks5
-// package. It describes the socks version, operation, client address,
-// and address of an error.
-type OpError struct {
-	// VER describe the socks server version on process.
-	VER
-
-	// Op is the operation which caused the error, such as
-	// "read", "write".
-	Op string
-
-	// Addr define client's address which caused the error.
-	Addr net.Addr
-
-	// Step is the client's current connection stage, such as
-	// "check version", "authentication", "process request",
-	Step string
-
-	// Err is the error that occurred during the operation.
-	// The Error method panics if the error is nil.
-	Err error
-}
-
-func (o *OpError) Error() string {
-	str := "socks" + strconv.Itoa(int(o.VER))
-	str += " " + o.Op
-	if o.Addr == nil {
-		str += " "
-	} else {
-		str += " " + o.Addr.String()
-	}
-	str += " " + o.Step
-	str += ":" + o.Err.Error()
-	return str
-}
-
-var errErrorATPE = errors.New("socks4 server bind address type should be ipv4")
diff --git a/vendor/github.com/kalikaneko/socks5/transport.go b/vendor/github.com/kalikaneko/socks5/transport.go
deleted file mode 100644
index fc7a739c..00000000
--- a/vendor/github.com/kalikaneko/socks5/transport.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package socks5
-
-import (
-	"io"
-	"net"
-	"strings"
-	"sync"
-)
-
-// Transporter transmit data between client and dest server.
-type Transporter interface {
-	TransportTCP(client net.Conn, remote net.Conn) <-chan error
-	TransportUDP(server *UDPConn, request *Request) error
-}
-
-type transport struct {
-}
-
-const maxLenOfDatagram = 65507
-
-var transportPool = &sync.Pool{
-	New: func() interface{} {
-		return make([]byte, maxLenOfDatagram)
-	},
-}
-
-// TransportTCP use io.CopyBuffer transmit data.
-func (t *transport) TransportTCP(client net.Conn, remote net.Conn) <-chan error {
-	errCh := make(chan error)
-	var wg = sync.WaitGroup{}
-
-	f := func(dst net.Conn, src net.Conn) {
-		defer wg.Done()
-		buf := transportPool.Get().([]byte)
-		defer transportPool.Put(buf)
-		_, err := io.CopyBuffer(dst, src, buf)
-		errCh <- err
-	}
-
-	wg.Add(2)
-	go func() {
-		wg.Wait()
-		defer client.Close()
-		defer remote.Close()
-		close(errCh)
-	}()
-
-	go f(remote, client)
-	go f(client, remote)
-
-	return errCh
-}
-
-// TransportUDP forwarding UDP packet between client and dest.
-func (t *transport) TransportUDP(server *UDPConn, request *Request) error {
-	// Client udp address, limit access to the association.
-	clientAddr, err := request.Address.UDPAddr()
-	if err != nil {
-		return err
-	}
-
-	// Record dest address, limit access to the association.
-	forwardAddr := make(map[string]struct{})
-	buf := transportPool.Get().([]byte)
-	defer transportPool.Put(buf)
-
-	defer server.Close()
-	for {
-		select {
-		default:
-			// Receive data from remote.
-			n, addr, err := server.ReadFromUDP(buf)
-			if err != nil {
-				return err
-			}
-
-			// Should unpack data when data from client.
-			if strings.EqualFold(clientAddr.String(), addr.String()) {
-				destAddr, payload, err := UnpackUDPData(buf[:n])
-				if err != nil {
-					return err
-				}
-
-				destUDPAddr, err := destAddr.UDPAddr()
-				if err != nil {
-					return err
-				}
-				forwardAddr[destUDPAddr.String()] = struct{}{}
-
-				// send payload to dest address
-				_, err = server.WriteToUDP(payload, destUDPAddr)
-				if err != nil {
-					return err
-				}
-			}
-
-			// Should pack data when data from dest host
-			if _, ok := forwardAddr[addr.String()]; ok {
-				address, err := ParseAddress(addr.String())
-				if err != nil {
-					return err
-				}
-
-				// packed Data
-				packedData, err := PackUDPData(address, buf[:n])
-				if err != nil {
-					return err
-				}
-
-				// send payload to client
-				_, err = server.WriteToUDP(packedData, clientAddr)
-				if err != nil {
-					return err
-				}
-			}
-		case <-server.CloseCh():
-			return nil
-		}
-	}
-}
-
-var DefaultTransporter Transporter = &transport{}
diff --git a/vendor/github.com/xtaci/kcp-go/v5/.travis.yml b/vendor/github.com/xtaci/kcp-go/v5/.travis.yml
index 0e7c4ac1..6754ef67 100644
--- a/vendor/github.com/xtaci/kcp-go/v5/.travis.yml
+++ b/vendor/github.com/xtaci/kcp-go/v5/.travis.yml
@@ -1,4 +1,8 @@
+arch:
+    - amd64
+    - ppc64le
 language: go
+
 go:
     - 1.11.x
     - 1.12.x
diff --git a/vendor/github.com/xtaci/kcp-go/v5/README.md b/vendor/github.com/xtaci/kcp-go/v5/README.md
index d2273f89..f68406d9 100644
--- a/vendor/github.com/xtaci/kcp-go/v5/README.md
+++ b/vendor/github.com/xtaci/kcp-go/v5/README.md
@@ -277,9 +277,3 @@ A: Yes, for the safety of protocol, even if the upper layer has encrypted.
 1. https://github.com/xtaci/libkcp -- FEC enhanced KCP session library for iOS/Android in C++
 1. https://github.com/skywind3000/kcp -- A Fast and Reliable ARQ Protocol
 1. https://github.com/klauspost/reedsolomon -- Reed-Solomon Erasure Coding in Go
-
-## Consulting 
-
-WeChat(付费技术咨询)
-
-<img src="wechat_donate.jpg" alt="kcptun" height="120px" /> 
diff --git a/vendor/github.com/xtaci/kcp-go/v5/donate.png b/vendor/github.com/xtaci/kcp-go/v5/donate.png
deleted file mode 100644
index 0f353d96e902936aed15a7312a6e8b4b332fe960..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4420
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

diff --git a/vendor/github.com/xtaci/kcp-go/v5/fec.go b/vendor/github.com/xtaci/kcp-go/v5/fec.go
index 0a203ee3..88f5a9c4 100644
--- a/vendor/github.com/xtaci/kcp-go/v5/fec.go
+++ b/vendor/github.com/xtaci/kcp-go/v5/fec.go
@@ -41,9 +41,6 @@ type fecDecoder struct {
 	decodeCache [][]byte
 	flagCache   []bool
 
-	// zeros
-	zeros []byte
-
 	// RS decoder
 	codec reedsolomon.Encoder
 
@@ -68,7 +65,6 @@ func newFECDecoder(dataShards, parityShards int) *fecDecoder {
 	dec.codec = codec
 	dec.decodeCache = make([][]byte, dec.shardSize)
 	dec.flagCache = make([]bool, dec.shardSize)
-	dec.zeros = make([]byte, mtuLimit)
 	return dec
 }
 
@@ -199,7 +195,7 @@ func (dec *fecDecoder) decode(in fecPacket) (recovered [][]byte) {
 				if shards[k] != nil {
 					dlen := len(shards[k])
 					shards[k] = shards[k][:maxlen]
-					copy(shards[k][dlen:], dec.zeros)
+					clear(shards[k][dlen:])
 				} else if k < dec.dataShards {
 					shards[k] = xmitBuf.Get().([]byte)[:0]
 				}
@@ -279,9 +275,6 @@ type (
 		shardCache  [][]byte
 		encodeCache [][]byte
 
-		// zeros
-		zeros []byte
-
 		// RS encoder
 		codec reedsolomon.Encoder
 	}
@@ -311,7 +304,6 @@ func newFECEncoder(dataShards, parityShards, offset int) *fecEncoder {
 	for k := range enc.shardCache {
 		enc.shardCache[k] = make([]byte, mtuLimit)
 	}
-	enc.zeros = make([]byte, mtuLimit)
 	return enc
 }
 
@@ -341,7 +333,7 @@ func (enc *fecEncoder) encode(b []byte) (ps [][]byte) {
 		for i := 0; i < enc.dataShards; i++ {
 			shard := enc.shardCache[i]
 			slen := len(shard)
-			copy(shard[slen:enc.maxSize], enc.zeros)
+			clear(shard[slen:enc.maxSize])
 		}
 
 		// construct equal-sized slice with stripped header
diff --git a/vendor/github.com/xtaci/kcp-go/v5/sess.go b/vendor/github.com/xtaci/kcp-go/v5/sess.go
index 2dedd745..35e7b804 100644
--- a/vendor/github.com/xtaci/kcp-go/v5/sess.go
+++ b/vendor/github.com/xtaci/kcp-go/v5/sess.go
@@ -195,6 +195,16 @@ func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn
 
 // Read implements net.Conn
 func (s *UDPSession) Read(b []byte) (n int, err error) {
+	var timeout *time.Timer
+	// deadline for current reading operation
+	var c <-chan time.Time
+	if !s.rd.IsZero() {
+		delay := time.Until(s.rd)
+		timeout = time.NewTimer(delay)
+		c = timeout.C
+		defer timeout.Stop()
+	}
+
 	for {
 		s.mu.Lock()
 		if len(s.bufptr) > 0 { // copy from buffer into b
@@ -228,27 +238,11 @@ func (s *UDPSession) Read(b []byte) (n int, err error) {
 			return n, nil
 		}
 
-		// deadline for current reading operation
-		var timeout *time.Timer
-		var c <-chan time.Time
-		if !s.rd.IsZero() {
-			if time.Now().After(s.rd) {
-				s.mu.Unlock()
-				return 0, errors.WithStack(errTimeout)
-			}
-
-			delay := time.Until(s.rd)
-			timeout = time.NewTimer(delay)
-			c = timeout.C
-		}
 		s.mu.Unlock()
 
 		// wait for read event or timeout or error
 		select {
 		case <-s.chReadEvent:
-			if timeout != nil {
-				timeout.Stop()
-			}
 		case <-c:
 			return 0, errors.WithStack(errTimeout)
 		case <-s.chSocketReadError:
@@ -264,6 +258,15 @@ func (s *UDPSession) Write(b []byte) (n int, err error) { return s.WriteBuffers(
 
 // WriteBuffers write a vector of byte slices to the underlying connection
 func (s *UDPSession) WriteBuffers(v [][]byte) (n int, err error) {
+	var timeout *time.Timer
+	var c <-chan time.Time
+	if !s.wd.IsZero() {
+		delay := time.Until(s.wd)
+		timeout = time.NewTimer(delay)
+		c = timeout.C
+		defer timeout.Stop()
+	}
+
 	for {
 		select {
 		case <-s.chSocketWriteError:
@@ -301,24 +304,10 @@ func (s *UDPSession) WriteBuffers(v [][]byte) (n int, err error) {
 			return n, nil
 		}
 
-		var timeout *time.Timer
-		var c <-chan time.Time
-		if !s.wd.IsZero() {
-			if time.Now().After(s.wd) {
-				s.mu.Unlock()
-				return 0, errors.WithStack(errTimeout)
-			}
-			delay := time.Until(s.wd)
-			timeout = time.NewTimer(delay)
-			c = timeout.C
-		}
 		s.mu.Unlock()
 
 		select {
 		case <-s.chWriteEvent:
-			if timeout != nil {
-				timeout.Stop()
-			}
 		case <-c:
 			return 0, errors.WithStack(errTimeout)
 		case <-s.chSocketWriteError:
diff --git a/vendor/github.com/xtaci/kcp-go/v5/wechat_donate.jpg b/vendor/github.com/xtaci/kcp-go/v5/wechat_donate.jpg
deleted file mode 100644
index ad72505ce56882faf47353fbc27c54826df29526..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 35307
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
F|JmoHbYK7g

diff --git a/vendor/modules.txt b/vendor/modules.txt
index ffa7d6a2..807ebea4 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -7,8 +7,8 @@
 0xacab.org/leap/bitmask-core/pkg/introducer
 0xacab.org/leap/bitmask-core/pkg/models
 0xacab.org/leap/bitmask-core/pkg/storage
-# 0xacab.org/leap/obfsvpn v0.0.0-20240422180703-83037b24d5cc
-## explicit; go 1.20
+# 0xacab.org/leap/obfsvpn v1.0.1-0.20240625123757-59f234eea051
+## explicit; go 1.22
 0xacab.org/leap/obfsvpn/client
 0xacab.org/leap/obfsvpn/obfsvpn
 # filippo.io/edwards25519 v1.1.0
@@ -126,9 +126,6 @@ github.com/josharian/intern
 # github.com/jtolds/gls v4.20.0+incompatible
 ## explicit
 github.com/jtolds/gls
-# github.com/kalikaneko/socks5 v1.0.1
-## explicit; go 1.16
-github.com/kalikaneko/socks5
 # github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
 ## explicit
 github.com/kardianos/osext
@@ -328,8 +325,8 @@ github.com/tjfoc/gmsm/sm4
 # github.com/xtaci/kcp-go v5.4.20+incompatible
 ## explicit
 github.com/xtaci/kcp-go
-# github.com/xtaci/kcp-go/v5 v5.6.1
-## explicit; go 1.13
+# github.com/xtaci/kcp-go/v5 v5.6.3
+## explicit; go 1.21
 github.com/xtaci/kcp-go/v5
 # github.com/xtaci/smux v1.5.24
 ## explicit; go 1.13
-- 
GitLab