From baee322cd746f460f2f6626cbce4c34a9476250c Mon Sep 17 00:00:00 2001 From: 9seconds Date: Thu, 4 Mar 2021 10:15:34 +0300 Subject: [PATCH] Reset a project --- antireplay/cache.go | 36 -- antireplay/init.go | 30 -- antireplay/nilcache.go | 8 - cli/generate.go | 26 - cli/proxy.go | 101 ---- cli/utils.go | 43 -- config/config.go | 312 ------------ config/global_ips.go | 78 --- config/urls.go | 99 ---- conntypes/acks.go | 6 - conntypes/dc.go | 5 - conntypes/id.go | 24 - conntypes/packet.go | 3 - conntypes/protocol.go | 22 - conntypes/type.go | 29 -- conntypes/wrap_interfaces.go | 14 - conntypes/wrap_packet_ack_interfaces.go | 41 -- conntypes/wrap_packet_interfaces.go | 51 -- conntypes/wrap_stream_interfaces.go | 56 --- faketls/client_protocol.go | 122 ----- faketls/cloak.go | 73 --- faketls/consts.go | 30 -- go.mod | 26 +- go.sum | 472 ------------------ hub/connection.go | 172 ------- hub/connection_list.go | 70 --- hub/hub.go | 40 -- hub/init.go | 24 - hub/interface.go | 7 - hub/mux.go | 90 ---- hub/proxy_conn.go | 79 --- main.go | 178 ------- mtproto/protocol.go | 102 ---- mtproto/rpc/consts.go | 28 -- mtproto/rpc/handshake_request.go | 5 - mtproto/rpc/handshake_response.go | 54 -- mtproto/rpc/nonce_request.go | 50 -- mtproto/rpc/nonce_response.go | 60 --- mtproto/rpc/proxy_flags.go | 66 --- mtproto/rpc/proxy_response.go | 53 -- ntp/ntp.go | 57 --- obfuscated2/client_protocol.go | 114 ----- obfuscated2/frame.go | 54 -- obfuscated2/telegram_protocol.go | 68 --- protocol/interfaces.go | 12 - protocol/request.go | 17 - proxy/direct.go | 49 -- proxy/middle.go | 70 --- proxy/proxy.go | 100 ---- run.sh | 68 --- stats/interfaces.go | 60 --- stats/multi_stats.go | 69 --- stats/stats.go | 41 -- stats/stats_prometheus.go | 156 ------ stats/stats_statsd.go | 204 -------- telegram/api/addresses.go | 109 ---- telegram/api/api.go | 44 -- telegram/api/secret.go | 24 - telegram/base.go | 91 ---- telegram/direct.go | 41 -- telegram/init.go | 48 -- telegram/interfaces.go | 8 - telegram/middle.go | 75 --- tlstypes/client_hello.go | 86 ---- tlstypes/consts.go | 90 ---- tlstypes/handshake.go | 43 -- tlstypes/record.go | 84 ---- tlstypes/server_hello.go | 97 ---- utils/init_tcp.go | 28 -- utils/read_full.go | 21 - utils/reverse_bytes.go | 15 - utils/rlimit.go | 24 - utils/rlimit_windows.go | 7 - utils/signal_context.go | 25 - utils/signal_context_windows.go | 23 - utils/stream_cipher.go | 12 - utils/uint24.go | 11 - wrappers/packet/mtproto_frame.go | 165 ------ wrappers/packetack/client_abridged.go | 130 ----- wrappers/packetack/client_intermediate.go | 89 ---- .../packetack/client_intermediate_secure.go | 63 --- wrappers/packetack/proxy.go | 108 ---- wrappers/rwc/ping.go | 48 -- wrappers/stream/base.go | 21 - wrappers/stream/blockcipher.go | 96 ---- wrappers/stream/buffered_reader.go | 44 -- wrappers/stream/conn.go | 123 ----- wrappers/stream/ctx.go | 93 ---- wrappers/stream/faketls.go | 107 ---- wrappers/stream/mtproto_cipher.go | 117 ----- wrappers/stream/obfuscated2.go | 93 ---- wrappers/stream/rewind.go | 83 --- wrappers/stream/stats_telegram.go | 71 --- wrappers/stream/stats_traffic.go | 66 --- wrappers/stream/timeout.go | 60 --- 95 files changed, 2 insertions(+), 6505 deletions(-) delete mode 100644 antireplay/cache.go delete mode 100644 antireplay/init.go delete mode 100644 antireplay/nilcache.go delete mode 100644 cli/generate.go delete mode 100644 cli/proxy.go delete mode 100644 cli/utils.go delete mode 100644 config/config.go delete mode 100644 config/global_ips.go delete mode 100644 config/urls.go delete mode 100644 conntypes/acks.go delete mode 100644 conntypes/dc.go delete mode 100644 conntypes/id.go delete mode 100644 conntypes/packet.go delete mode 100644 conntypes/protocol.go delete mode 100644 conntypes/type.go delete mode 100644 conntypes/wrap_interfaces.go delete mode 100644 conntypes/wrap_packet_ack_interfaces.go delete mode 100644 conntypes/wrap_packet_interfaces.go delete mode 100644 conntypes/wrap_stream_interfaces.go delete mode 100644 faketls/client_protocol.go delete mode 100644 faketls/cloak.go delete mode 100644 faketls/consts.go delete mode 100644 hub/connection.go delete mode 100644 hub/connection_list.go delete mode 100644 hub/hub.go delete mode 100644 hub/init.go delete mode 100644 hub/interface.go delete mode 100644 hub/mux.go delete mode 100644 hub/proxy_conn.go delete mode 100644 mtproto/protocol.go delete mode 100644 mtproto/rpc/consts.go delete mode 100644 mtproto/rpc/handshake_request.go delete mode 100644 mtproto/rpc/handshake_response.go delete mode 100644 mtproto/rpc/nonce_request.go delete mode 100644 mtproto/rpc/nonce_response.go delete mode 100644 mtproto/rpc/proxy_flags.go delete mode 100644 mtproto/rpc/proxy_response.go delete mode 100644 ntp/ntp.go delete mode 100644 obfuscated2/client_protocol.go delete mode 100644 obfuscated2/frame.go delete mode 100644 obfuscated2/telegram_protocol.go delete mode 100644 protocol/interfaces.go delete mode 100644 protocol/request.go delete mode 100644 proxy/direct.go delete mode 100644 proxy/middle.go delete mode 100644 proxy/proxy.go delete mode 100755 run.sh delete mode 100644 stats/interfaces.go delete mode 100644 stats/multi_stats.go delete mode 100644 stats/stats.go delete mode 100644 stats/stats_prometheus.go delete mode 100644 stats/stats_statsd.go delete mode 100644 telegram/api/addresses.go delete mode 100644 telegram/api/api.go delete mode 100644 telegram/api/secret.go delete mode 100644 telegram/base.go delete mode 100644 telegram/direct.go delete mode 100644 telegram/init.go delete mode 100644 telegram/interfaces.go delete mode 100644 telegram/middle.go delete mode 100644 tlstypes/client_hello.go delete mode 100644 tlstypes/consts.go delete mode 100644 tlstypes/handshake.go delete mode 100644 tlstypes/record.go delete mode 100644 tlstypes/server_hello.go delete mode 100644 utils/init_tcp.go delete mode 100644 utils/read_full.go delete mode 100644 utils/reverse_bytes.go delete mode 100644 utils/rlimit.go delete mode 100644 utils/rlimit_windows.go delete mode 100644 utils/signal_context.go delete mode 100644 utils/signal_context_windows.go delete mode 100644 utils/stream_cipher.go delete mode 100644 utils/uint24.go delete mode 100644 wrappers/packet/mtproto_frame.go delete mode 100644 wrappers/packetack/client_abridged.go delete mode 100644 wrappers/packetack/client_intermediate.go delete mode 100644 wrappers/packetack/client_intermediate_secure.go delete mode 100644 wrappers/packetack/proxy.go delete mode 100644 wrappers/rwc/ping.go delete mode 100644 wrappers/stream/base.go delete mode 100644 wrappers/stream/blockcipher.go delete mode 100644 wrappers/stream/buffered_reader.go delete mode 100644 wrappers/stream/conn.go delete mode 100644 wrappers/stream/ctx.go delete mode 100644 wrappers/stream/faketls.go delete mode 100644 wrappers/stream/mtproto_cipher.go delete mode 100644 wrappers/stream/obfuscated2.go delete mode 100644 wrappers/stream/rewind.go delete mode 100644 wrappers/stream/stats_telegram.go delete mode 100644 wrappers/stream/stats_traffic.go delete mode 100644 wrappers/stream/timeout.go diff --git a/antireplay/cache.go b/antireplay/cache.go deleted file mode 100644 index dab3af4..0000000 --- a/antireplay/cache.go +++ /dev/null @@ -1,36 +0,0 @@ -package antireplay - -import "github.com/VictoriaMetrics/fastcache" - -var ( - prefixObfuscated2 = []byte{0x00} - prefixTLS = []byte{0x01} -) - -type cache struct { - data *fastcache.Cache -} - -func (c cache) AddObfuscated2(data []byte) { - c.data.Set(keyObfuscated2(data), nil) -} - -func (c cache) AddTLS(data []byte) { - c.data.Set(keyTLS(data), nil) -} - -func (c cache) HasObfuscated2(data []byte) bool { - return c.data.Has(keyObfuscated2(data)) -} - -func (c cache) HasTLS(data []byte) bool { - return c.data.Has(keyTLS(data)) -} - -func keyObfuscated2(data []byte) []byte { - return append(prefixObfuscated2, data...) -} - -func keyTLS(data []byte) []byte { - return append(prefixTLS, data...) -} diff --git a/antireplay/init.go b/antireplay/init.go deleted file mode 100644 index 4ad9950..0000000 --- a/antireplay/init.go +++ /dev/null @@ -1,30 +0,0 @@ -package antireplay - -import ( - "sync" - - "github.com/9seconds/mtg/config" - "github.com/VictoriaMetrics/fastcache" -) - -type CacheInterface interface { - AddObfuscated2([]byte) - AddTLS([]byte) - HasObfuscated2([]byte) bool - HasTLS([]byte) bool -} - -var ( - Cache CacheInterface - initOnce sync.Once -) - -func Init() { - initOnce.Do(func() { - if config.C.AntiReplayMaxSize == 0 { - Cache = nilCache{} - } else { - Cache = cache{fastcache.New(config.C.AntiReplayMaxSize)} - } - }) -} diff --git a/antireplay/nilcache.go b/antireplay/nilcache.go deleted file mode 100644 index baa0947..0000000 --- a/antireplay/nilcache.go +++ /dev/null @@ -1,8 +0,0 @@ -package antireplay - -type nilCache struct{} - -func (n nilCache) AddObfuscated2(_ []byte) {} -func (n nilCache) AddTLS(_ []byte) {} -func (n nilCache) HasObfuscated2(_ []byte) bool { return false } -func (n nilCache) HasTLS(_ []byte) bool { return false } diff --git a/cli/generate.go b/cli/generate.go deleted file mode 100644 index 5811798..0000000 --- a/cli/generate.go +++ /dev/null @@ -1,26 +0,0 @@ -package cli - -import ( - "crypto/rand" - "encoding/hex" - - "github.com/9seconds/mtg/config" -) - -func Generate(secretType, hostname string) { - data := make([]byte, config.SimpleSecretLength) - if _, err := rand.Read(data); err != nil { - panic(err) - } - - secret := hex.EncodeToString(data) - - switch secretType { - case "simple": - PrintStdout(secret) - case "secured": - PrintStdout("dd" + secret) - default: - PrintStdout("ee" + secret + hex.EncodeToString([]byte(hostname))) - } -} diff --git a/cli/proxy.go b/cli/proxy.go deleted file mode 100644 index 038239e..0000000 --- a/cli/proxy.go +++ /dev/null @@ -1,101 +0,0 @@ -package cli - -import ( - "net" - "os" - "time" - - "github.com/9seconds/mtg/antireplay" - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/faketls" - "github.com/9seconds/mtg/hub" - "github.com/9seconds/mtg/ntp" - "github.com/9seconds/mtg/obfuscated2" - "github.com/9seconds/mtg/proxy" - "github.com/9seconds/mtg/stats" - "github.com/9seconds/mtg/telegram" - "github.com/9seconds/mtg/utils" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -func Proxy() error { // nolint: funlen,cyclop - ctx := utils.GetSignalContext() - - atom := zap.NewAtomicLevel() - - switch { - case config.C.Debug: - atom.SetLevel(zapcore.DebugLevel) - case config.C.Verbose: - atom.SetLevel(zapcore.InfoLevel) - default: - atom.SetLevel(zapcore.ErrorLevel) - } - - encoderCfg := zap.NewProductionEncoderConfig() - logger := zap.New(zapcore.NewCore( - zapcore.NewJSONEncoder(encoderCfg), - zapcore.Lock(os.Stderr), - atom, - )) - - zap.ReplaceGlobals(logger) - defer logger.Sync() // nolint: errcheck - - if err := config.InitPublicAddress(ctx); err != nil { - Fatal(err) - } - - zap.S().Debugw("Configuration", "config", config.Printable()) - - if config.C.MiddleProxyMode() { - zap.S().Infow("Use middle proxy connection to Telegram") - - diff, err := ntp.Fetch() - if err != nil { - Fatal("Cannot fetch time data from NTP") - } - - if diff > time.Second { - Fatal("Your local time is skewed and drift is bigger than a second. Please sync your time.") - } - - go ntp.AutoUpdate() - } else { - zap.S().Infow("Use direct connection to Telegram") - } - - PrintJSONStdout(config.GetURLs()) - - if err := stats.Init(ctx); err != nil { - Fatal(err) - } - - antireplay.Init() - telegram.Init() - hub.Init(ctx) - - proxyListener, err := net.Listen("tcp", config.C.Bind.String()) - if err != nil { - Fatal(err) - } - - go func() { - <-ctx.Done() - proxyListener.Close() - }() - - app := &proxy.Proxy{ - Logger: zap.S().Named("proxy"), - Context: ctx, - ClientProtocolMaker: obfuscated2.MakeClientProtocol, - } - if config.C.SecretMode == config.SecretModeTLS { - app.ClientProtocolMaker = faketls.MakeClientProtocol - } - - app.Serve(proxyListener) - - return nil -} diff --git a/cli/utils.go b/cli/utils.go deleted file mode 100644 index 948d875..0000000 --- a/cli/utils.go +++ /dev/null @@ -1,43 +0,0 @@ -package cli - -import ( - "encoding/json" - "fmt" - "io" - "os" -) - -func Fatal(arg interface{}) { - if value, ok := arg.(error); ok { - arg = fmt.Errorf("fatal error: %+v", value) // nolint: errorlint - } - - PrintStderr(arg) - os.Exit(1) -} - -func PrintStderr(args ...interface{}) { - fmt.Fprintln(os.Stderr, args...) -} - -func PrintStdout(args ...interface{}) { - fmt.Println(args...) // nolint: forbidigo -} - -func PrintJSONStderr(data interface{}) { - printJSON(os.Stderr, data) -} - -func PrintJSONStdout(data interface{}) { - printJSON(os.Stdout, data) -} - -func printJSON(writer io.Writer, data interface{}) { - encoder := json.NewEncoder(writer) - encoder.SetEscapeHTML(false) - encoder.SetIndent("", " ") - - if err := encoder.Encode(data); err != nil { - panic(err) - } -} diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 5e97f86..0000000 --- a/config/config.go +++ /dev/null @@ -1,312 +0,0 @@ -package config - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "math" - "net" - - "github.com/alecthomas/units" - statsd "github.com/smira/go-statsd" - "go.uber.org/zap" -) - -type SecretMode uint8 - -func (s SecretMode) String() string { - switch s { - case SecretModeSimple: - return "simple" - case SecretModeSecured: - return "secured" - case SecretModeTLS: - return "tls" - } - - return "tls" -} - -const ( - SecretModeSimple SecretMode = iota - SecretModeSecured - SecretModeTLS -) - -type PreferIP uint8 - -const ( - PreferIPv4 PreferIP = iota - PreferIPv6 -) - -const SimpleSecretLength = 16 - -type OptionType uint8 - -const ( - OptionTypeDebug OptionType = iota - OptionTypeVerbose - - OptionTypePreferIP - - OptionTypeBind - OptionTypePublicIPv4 - OptionTypePublicIPv6 - - OptionTypeStatsBind - OptionTypeStatsNamespace - OptionTypeStatsdAddress - OptionTypeStatsdTagsFormat - OptionTypeStatsdTags - - OptionTypeWriteBufferSize - OptionTypeReadBufferSize - - OptionTypeCloakPort - - OptionTypeAntiReplayMaxSize - - OptionTypeMultiplexPerConnection - - OptionTypeNTPServers - - OptionTypeSecret - OptionTypeAdtag -) - -type Config struct { - Bind *net.TCPAddr `json:"bind"` - PublicIPv4 *net.TCPAddr `json:"public_ipv4"` - PublicIPv6 *net.TCPAddr `json:"public_ipv6"` - StatsBind *net.TCPAddr `json:"stats_bind"` - StatsdAddr *net.TCPAddr `json:"stats_addr"` - StatsdTagsFormat *statsd.TagFormat `json:"statsd_tags_format"` - - StatsNamespace string `json:"stats_namespace"` - CloakHost string `json:"cloak_host"` - StatsdTags map[string]string `json:"statsd_tags"` - - WriteBuffer int `json:"write_buffer"` - ReadBuffer int `json:"read_buffer"` - CloakPort int `json:"cloak_port"` - - AntiReplayMaxSize int `json:"anti_replay_max_size"` - - MultiplexPerConnection int `json:"multiplex_per_connection"` - - Debug bool `json:"debug"` - Verbose bool `json:"verbose"` - SecretMode SecretMode `json:"secret_mode"` - PreferIP PreferIP `json:"prefer_ip"` - NTPServers []string `json:"ntp_servers"` - - Secret []byte `json:"secret"` - AdTag []byte `json:"adtag"` -} - -func (c *Config) ClientReadBuffer() int { - return c.ReadBuffer -} - -func (c *Config) ClientWriteBuffer() int { - return c.WriteBuffer -} - -func (c *Config) MiddleProxyMode() bool { - return len(c.AdTag) > 0 -} - -func (c *Config) ProxyReadBuffer() int { - value := c.ReadBuffer - - if c.MiddleProxyMode() { - value = c.adjustProxyValue(value) - } - - return value -} - -func (c *Config) ProxyWriteBuffer() int { - value := c.WriteBuffer - - if c.MiddleProxyMode() { - value = c.adjustProxyValue(value) - } - - return value -} - -func (c *Config) adjustProxyValue(value int) int { - if c.MultiplexPerConnection == 0 { - return value - } - - fvalue := float64(value) - - newValue := fvalue * 2 * math.Log(float64(c.MultiplexPerConnection)) - newValue = math.Ceil(newValue) - newValue = math.Max(fvalue, newValue) - - return int(newValue) -} - -type Opt struct { - Option OptionType - Value interface{} -} - -var C = Config{} - -func Init(options ...Opt) error { // nolint: gocyclo, funlen, cyclop - for _, opt := range options { - switch opt.Option { - case OptionTypeDebug: - C.Debug = opt.Value.(bool) - case OptionTypeVerbose: - C.Verbose = opt.Value.(bool) - case OptionTypePreferIP: - value := opt.Value.(string) - switch value { - case "ipv4": - C.PreferIP = PreferIPv4 - case "ipv6": - C.PreferIP = PreferIPv6 - default: - return fmt.Errorf("incorrect direct IP mode %s", value) - } - case OptionTypeBind: - C.Bind = opt.Value.(*net.TCPAddr) - case OptionTypePublicIPv4: - C.PublicIPv4 = opt.Value.(*net.TCPAddr) - if C.PublicIPv4 == nil { - C.PublicIPv4 = &net.TCPAddr{} - } - case OptionTypePublicIPv6: - C.PublicIPv6 = opt.Value.(*net.TCPAddr) - if C.PublicIPv6 == nil { - C.PublicIPv6 = &net.TCPAddr{} - } - case OptionTypeStatsBind: - C.StatsBind = opt.Value.(*net.TCPAddr) - case OptionTypeStatsNamespace: - C.StatsNamespace = opt.Value.(string) - case OptionTypeStatsdAddress: - C.StatsdAddr = opt.Value.(*net.TCPAddr) - case OptionTypeStatsdTagsFormat: - value := opt.Value.(string) - switch value { - case "datadog": - C.StatsdTagsFormat = statsd.TagFormatDatadog - case "influxdb": - C.StatsdTagsFormat = statsd.TagFormatInfluxDB - default: - return fmt.Errorf("incorrect statsd tag %s", value) - } - case OptionTypeStatsdTags: - C.StatsdTags = opt.Value.(map[string]string) - case OptionTypeWriteBufferSize: - C.WriteBuffer = int(opt.Value.(units.Base2Bytes)) - case OptionTypeReadBufferSize: - C.ReadBuffer = int(opt.Value.(units.Base2Bytes)) - case OptionTypeCloakPort: - C.CloakPort = int(opt.Value.(uint16)) - case OptionTypeAntiReplayMaxSize: - C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes)) - case OptionTypeMultiplexPerConnection: - C.MultiplexPerConnection = int(opt.Value.(uint)) - case OptionTypeNTPServers: - C.NTPServers = opt.Value.([]string) - if len(C.NTPServers) == 0 { - return errors.New("ntp server list is empty") - } - case OptionTypeSecret: - C.Secret = opt.Value.([]byte) - case OptionTypeAdtag: - C.AdTag = opt.Value.([]byte) - default: - return fmt.Errorf("unknown tag %v", opt.Option) - } - } - - switch { - case len(C.Secret) == 1+SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xdd}): - C.SecretMode = SecretModeSecured - C.Secret = bytes.TrimPrefix(C.Secret, []byte{0xdd}) - case len(C.Secret) > SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xee}): - C.SecretMode = SecretModeTLS - secret := bytes.TrimPrefix(C.Secret, []byte{0xee}) - C.Secret = secret[:SimpleSecretLength] - C.CloakHost = string(secret[SimpleSecretLength:]) - case len(C.Secret) == SimpleSecretLength: - C.SecretMode = SecretModeSimple - default: - return errors.New("incorrect secret") - } - - if C.MultiplexPerConnection == 0 { - return errors.New("cannot use 0 clients per connection for multiplexing") - } - - if C.CloakHost != "" { - if _, err := net.LookupHost(C.CloakHost); err != nil { - zap.S().Warnw("Cannot resolve address of host", "hostname", C.CloakHost, "error", err) - } - } - - return nil -} - -func InitPublicAddress(ctx context.Context) error { - if C.PublicIPv4.Port == 0 { - C.PublicIPv4.Port = C.Bind.Port - } - - if C.PublicIPv6.Port == 0 { - C.PublicIPv6.Port = C.Bind.Port - } - - foundAddress := C.PublicIPv4.IP != nil || C.PublicIPv6.IP != nil - - if C.PublicIPv4.IP == nil { - ip, err := getGlobalIPv4(ctx) - if err != nil { - zap.S().Warnw("Cannot resolve public address", "error", err) - } else { - C.PublicIPv4.IP = ip - foundAddress = true - } - } - - if C.PublicIPv6.IP == nil { - ip, err := getGlobalIPv6(ctx) - if err != nil { - zap.S().Warnw("Cannot resolve public address", "error", err) - } else { - C.PublicIPv6.IP = ip - foundAddress = true - } - } - - if !foundAddress { - return errors.New("cannot resolve any public address") - } - - return nil -} - -func Printable() interface{} { - data, err := json.Marshal(C) - if err != nil { - panic(err) - } - - rv := map[string]interface{}{} - if err := json.Unmarshal(data, &rv); err != nil { - panic(err) - } - - return rv -} diff --git a/config/global_ips.go b/config/global_ips.go deleted file mode 100644 index 0dd78da..0000000 --- a/config/global_ips.go +++ /dev/null @@ -1,78 +0,0 @@ -package config - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "strings" - "time" -) - -const ( - ifconfigAddress = "https://ifconfig.co/ip" - ifconfigTimeout = 10 * time.Second -) - -func getGlobalIPv4(ctx context.Context) (net.IP, error) { - ip, err := fetchIP(ctx, "tcp4") - if err != nil || ip.To4() == nil { - return nil, fmt.Errorf("cannot find public ipv4 address: %w", err) - } - - return ip, nil -} - -func getGlobalIPv6(ctx context.Context) (net.IP, error) { - ip, err := fetchIP(ctx, "tcp6") - if err != nil || ip.To4() != nil { - return nil, fmt.Errorf("cannot find public ipv6 address: %w", err) - } - - return ip, nil -} - -func fetchIP(ctx context.Context, network string) (net.IP, error) { - dialer := &net.Dialer{FallbackDelay: -1} - client := &http.Client{ - Jar: nil, - Timeout: ifconfigTimeout, - Transport: &http.Transport{ - DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) { - return dialer.DialContext(ctx, network, addr) - }, - }, - } - - req, err := http.NewRequest("GET", ifconfigAddress, nil) - if err != nil { - return nil, fmt.Errorf("cannot create a request: %w", err) - } - - resp, err := client.Do(req.WithContext(ctx)) - if err != nil { - if resp != nil { - io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck - } - - return nil, fmt.Errorf("cannot perform a request: %w", err) - } - - defer resp.Body.Close() - - respDataBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("cannot read response body: %w", err) - } - - respData := strings.TrimSpace(string(respDataBytes)) - - ip := net.ParseIP(respData) - if ip == nil { - return nil, fmt.Errorf("ifconfig.co returns incorrect IP %s", respData) - } - - return ip, nil -} diff --git a/config/urls.go b/config/urls.go deleted file mode 100644 index f657e82..0000000 --- a/config/urls.go +++ /dev/null @@ -1,99 +0,0 @@ -package config - -import ( - "encoding/hex" - "net" - "net/url" - "strconv" -) - -type URLs struct { - TG string `json:"tg_url"` - TMe string `json:"tme_url"` - TGQRCode string `json:"tg_qrcode"` - TMeQRCode string `json:"tme_qrcode"` -} - -type IPURLs struct { - IPv4 *URLs `json:"ipv4,omitempty"` - IPv6 *URLs `json:"ipv6,omitempty"` - BotSecret string `json:"secret_for_mtproxybot"` -} - -func GetURLs() (urls IPURLs) { - secret := "" - - switch C.SecretMode { - case SecretModeSimple: - secret = hex.EncodeToString(C.Secret) - case SecretModeSecured: - secret = "dd" + hex.EncodeToString(C.Secret) - case SecretModeTLS: - secret = "ee" + hex.EncodeToString(C.Secret) + hex.EncodeToString([]byte(C.CloakHost)) - } - - if C.PublicIPv4.IP != nil { - urls.IPv4 = makeURLs(C.PublicIPv4, secret) - } - - if C.PublicIPv6.IP != nil { - urls.IPv6 = makeURLs(C.PublicIPv6, secret) - } - - urls.BotSecret = hex.EncodeToString(C.Secret) - - return urls -} - -func makeURLs(addr *net.TCPAddr, secret string) *URLs { - urls := &URLs{} - - values := url.Values{} - values.Set("server", addr.IP.String()) - values.Set("port", strconv.Itoa(addr.Port)) - values.Set("secret", secret) - - return &URLs{ - TG: makeTGURL(values), - TMe: makeTMeURL(values), - TGQRCode: makeQRCodeURL(urls.TG), - TMeQRCode: makeQRCodeURL(urls.TMe), - } -} - -func makeTGURL(values url.Values) string { - tgURL := url.URL{ - Scheme: "tg", - Host: "proxy", - RawQuery: values.Encode(), - } - - return tgURL.String() -} - -func makeTMeURL(values url.Values) string { - tMeURL := url.URL{ - Scheme: "https", - Host: "t.me", - Path: "proxy", - RawQuery: values.Encode(), - } - - return tMeURL.String() -} - -func makeQRCodeURL(data string) string { - qr := url.URL{ - Scheme: "https", - Host: "api.qrserver.com", - Path: "v1/create-qr-code", - } - - values := url.Values{} - values.Set("qzone", "4") - values.Set("format", "svg") - values.Set("data", data) - qr.RawQuery = values.Encode() - - return qr.String() -} diff --git a/conntypes/acks.go b/conntypes/acks.go deleted file mode 100644 index d3dbd8d..0000000 --- a/conntypes/acks.go +++ /dev/null @@ -1,6 +0,0 @@ -package conntypes - -type ConnectionAcks struct { - Simple bool - Quick bool -} diff --git a/conntypes/dc.go b/conntypes/dc.go deleted file mode 100644 index 3cf2850..0000000 --- a/conntypes/dc.go +++ /dev/null @@ -1,5 +0,0 @@ -package conntypes - -type DC int16 - -const DCDefaultIdx DC = 1 diff --git a/conntypes/id.go b/conntypes/id.go deleted file mode 100644 index 1aa482c..0000000 --- a/conntypes/id.go +++ /dev/null @@ -1,24 +0,0 @@ -package conntypes - -import ( - "crypto/rand" - "encoding/hex" -) - -const ConnIDLength = 8 - -type ConnID [ConnIDLength]byte - -func (c ConnID) String() string { - return hex.EncodeToString(c[:]) -} - -func NewConnID() ConnID { - var id ConnID - - if _, err := rand.Read(id[:]); err != nil { - panic(err) - } - - return id -} diff --git a/conntypes/packet.go b/conntypes/packet.go deleted file mode 100644 index fa72022..0000000 --- a/conntypes/packet.go +++ /dev/null @@ -1,3 +0,0 @@ -package conntypes - -type Packet []byte diff --git a/conntypes/protocol.go b/conntypes/protocol.go deleted file mode 100644 index b89ac65..0000000 --- a/conntypes/protocol.go +++ /dev/null @@ -1,22 +0,0 @@ -package conntypes - -type ConnectionProtocol uint8 - -func (c ConnectionProtocol) String() string { - switch c { - case ConnectionProtocolAny: - return "any" - case ConnectionProtocolIPv4: - return "ipv4" - case ConnectionProtocolIPv6: - return "ipv6" - } - - return "ipv6" -} - -const ( - ConnectionProtocolIPv4 ConnectionProtocol = 1 - ConnectionProtocolIPv6 = ConnectionProtocolIPv4 << 1 - ConnectionProtocolAny = ConnectionProtocolIPv4 | ConnectionProtocolIPv6 -) diff --git a/conntypes/type.go b/conntypes/type.go deleted file mode 100644 index c41d42f..0000000 --- a/conntypes/type.go +++ /dev/null @@ -1,29 +0,0 @@ -package conntypes - -type ConnectionType uint8 - -const ( - ConnectionTypeUnknown ConnectionType = iota - ConnectionTypeAbridged - ConnectionTypeIntermediate - ConnectionTypeSecure -) - -var ( - ConnectionTagAbridged = []byte{0xef, 0xef, 0xef, 0xef} - ConnectionTagIntermediate = []byte{0xee, 0xee, 0xee, 0xee} - ConnectionTagSecure = []byte{0xdd, 0xdd, 0xdd, 0xdd} -) - -func (t ConnectionType) Tag() []byte { - switch t { - case ConnectionTypeAbridged: - return ConnectionTagAbridged - case ConnectionTypeIntermediate: - return ConnectionTagIntermediate - case ConnectionTypeSecure, ConnectionTypeUnknown: - return ConnectionTagSecure - } - - return ConnectionTagSecure -} diff --git a/conntypes/wrap_interfaces.go b/conntypes/wrap_interfaces.go deleted file mode 100644 index f21eb91..0000000 --- a/conntypes/wrap_interfaces.go +++ /dev/null @@ -1,14 +0,0 @@ -package conntypes - -import ( - "net" - - "go.uber.org/zap" -) - -type Wrap interface { - Conn() net.Conn - Logger() *zap.SugaredLogger - LocalAddr() *net.TCPAddr - RemoteAddr() *net.TCPAddr -} diff --git a/conntypes/wrap_packet_ack_interfaces.go b/conntypes/wrap_packet_ack_interfaces.go deleted file mode 100644 index 6388f0c..0000000 --- a/conntypes/wrap_packet_ack_interfaces.go +++ /dev/null @@ -1,41 +0,0 @@ -package conntypes - -import "io" - -type PacketAckReader interface { - Read(*ConnectionAcks) (Packet, error) -} - -type PacketAckWriter interface { - Write(Packet, *ConnectionAcks) error -} - -type PacketAckCloser interface { - io.Closer -} - -type PacketAckReadCloser interface { - PacketAckReader - PacketAckCloser -} - -type PacketAckWriteCloser interface { - PacketAckWriter - PacketAckCloser -} - -type PacketAckReadWriter interface { - PacketAckReader - PacketAckWriter -} - -type PacketAckReadWriteCloser interface { - PacketAckReader - PacketAckWriter - PacketAckCloser -} - -type PacketAckFullReadWriteCloser interface { - Wrap - PacketAckReadWriteCloser -} diff --git a/conntypes/wrap_packet_interfaces.go b/conntypes/wrap_packet_interfaces.go deleted file mode 100644 index 6c573d4..0000000 --- a/conntypes/wrap_packet_interfaces.go +++ /dev/null @@ -1,51 +0,0 @@ -package conntypes - -import "io" - -type BasePacketReader interface { - Read() (Packet, error) -} - -type BasePacketWriter interface { - Write(Packet) error -} - -type PacketReader interface { - Wrap - BasePacketReader -} - -type PacketWriter interface { - Wrap - BasePacketWriter -} - -type PacketCloser interface { - Wrap - io.Closer -} - -type PacketReadCloser interface { - Wrap - BasePacketReader - io.Closer -} - -type PacketWriteCloser interface { - Wrap - BasePacketWriter - io.Closer -} - -type PacketReadWriter interface { - Wrap - BasePacketWriter - BasePacketReader -} - -type PacketReadWriteCloser interface { - Wrap - BasePacketWriter - BasePacketReader - io.Closer -} diff --git a/conntypes/wrap_stream_interfaces.go b/conntypes/wrap_stream_interfaces.go deleted file mode 100644 index 5924d66..0000000 --- a/conntypes/wrap_stream_interfaces.go +++ /dev/null @@ -1,56 +0,0 @@ -package conntypes - -import ( - "io" - "time" -) - -type BaseStreamReaderWithTimeout interface { - ReadTimeout([]byte, time.Duration) (int, error) -} - -type BaseStreamWriterWithTimeout interface { - WriteTimeout([]byte, time.Duration) (int, error) -} - -type StreamReader interface { - Wrap - io.Reader - BaseStreamReaderWithTimeout -} - -type StreamWriter interface { - Wrap - io.Writer - BaseStreamWriterWithTimeout -} - -type StreamCloser interface { - Wrap - io.Closer -} - -type StreamReadCloser interface { - Wrap - io.ReadCloser - BaseStreamReaderWithTimeout -} - -type StreamWriteCloser interface { - Wrap - io.WriteCloser - BaseStreamWriterWithTimeout -} - -type StreamReadWriter interface { - Wrap - io.ReadWriter - BaseStreamReaderWithTimeout -} - -type StreamReadWriteCloser interface { - Wrap - io.ReadWriteCloser - BaseStreamReaderWithTimeout - BaseStreamWriterWithTimeout -} diff --git a/faketls/client_protocol.go b/faketls/client_protocol.go deleted file mode 100644 index 8208ac0..0000000 --- a/faketls/client_protocol.go +++ /dev/null @@ -1,122 +0,0 @@ -package faketls - -import ( - "bufio" - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "net" - "strconv" - "time" - - "github.com/9seconds/mtg/antireplay" - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/obfuscated2" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/stats" - "github.com/9seconds/mtg/tlstypes" - "github.com/9seconds/mtg/wrappers/stream" -) - -type ClientProtocol struct { - obfuscated2.ClientProtocol -} - -func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) { - rewinded := stream.NewRewind(socket) - bufferedReader := bufio.NewReader(rewinded) - - for _, expected := range faketlsStartBytes { - if actual, err := bufferedReader.ReadByte(); err != nil || actual != expected { - rewinded.Rewind() - c.cloakHost(rewinded) - - return nil, errors.New("failed first bytes of tls handshake") - } - } - - rewinded.Rewind() - rewinded = stream.NewRewind(rewinded) - - if err := c.tlsHandshake(rewinded); err != nil { - rewinded.Rewind() - c.cloakHost(rewinded) - - return nil, fmt.Errorf("failed tls handshake: %w", err) - } - - conn := stream.NewFakeTLS(socket) - - conn, err := c.ClientProtocol.Handshake(conn) - if err != nil { - return nil, err // nolint: wrapcheck - } - - return conn, err // nolint: wrapcheck -} - -func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error { - helloRecord, err := tlstypes.ReadRecord(conn) - if err != nil { - return fmt.Errorf("cannot read initial record: %w", err) - } - - buf := &bytes.Buffer{} - helloRecord.Data.WriteBytes(buf) - - clientHello, err := tlstypes.ParseClientHello(buf.Bytes()) - if err != nil { - return fmt.Errorf("cannot parse client hello: %w", err) - } - - digest := clientHello.Digest() - for i := 0; i < len(digest)-4; i++ { - if digest[i] != 0 { - return errBadDigest - } - } - - timestamp := int64(binary.LittleEndian.Uint32(digest[len(digest)-4:])) - createdAt := time.Unix(timestamp, 0) - timeDiff := time.Since(createdAt) - - if (timeDiff > TimeSkew || timeDiff < -TimeSkew) && timestamp > TimeFromBoot { - return errBadTime - } - - if antireplay.Cache.HasTLS(clientHello.Random[:]) { - stats.Stats.ReplayDetected() - - return errors.New("replay attack is detected") - } - - antireplay.Cache.AddTLS(clientHello.Random[:]) - serverHello := tlstypes.NewServerHello(clientHello) - serverHelloPacket := serverHello.WelcomePacket() - - if _, err := conn.Write(serverHelloPacket); err != nil { - return fmt.Errorf("cannot send welcome packet: %w", err) - } - - return nil -} - -func (c *ClientProtocol) cloakHost(clientConn io.ReadWriteCloser) { - stats.Stats.CloakedRequest() - - addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort)) - - hostConn, err := net.Dial("tcp", addr) - if err != nil { - return - } - - cloak(clientConn, hostConn) -} - -func MakeClientProtocol() protocol.ClientProtocol { - return &ClientProtocol{} -} diff --git a/faketls/cloak.go b/faketls/cloak.go deleted file mode 100644 index b134de8..0000000 --- a/faketls/cloak.go +++ /dev/null @@ -1,73 +0,0 @@ -package faketls - -import ( - "context" - "io" - "sync" - "time" - - "github.com/9seconds/mtg/wrappers/rwc" -) - -const ( - cloakLastActivityTimeout = 5 * time.Second - cloakMaxTimeout = 30 * time.Second -) - -func cloak(one, another io.ReadWriteCloser) { - defer func() { - one.Close() - another.Close() - }() - - channelPing := make(chan struct{}, 1) - ctx, cancel := context.WithCancel(context.Background()) - one = rwc.NewPing(ctx, one, channelPing) - another = rwc.NewPing(ctx, another, channelPing) - wg := &sync.WaitGroup{} - - wg.Add(2) - - go cloakPipe(one, another, wg) - - go cloakPipe(another, one, wg) - - go func() { - wg.Wait() - cancel() - }() - - go func() { - lastActivityTimer := time.NewTimer(cloakLastActivityTimeout) - defer lastActivityTimer.Stop() - - maxTimer := time.NewTimer(cloakMaxTimeout) - defer maxTimer.Stop() - - for { - select { - case <-channelPing: - lastActivityTimer.Stop() - lastActivityTimer = time.NewTimer(cloakLastActivityTimeout) - case <-ctx.Done(): - return - case <-lastActivityTimer.C: - cancel() - - return - case <-maxTimer.C: - cancel() - - return - } - } - }() - - <-ctx.Done() -} - -func cloakPipe(one io.Writer, another io.Reader, wg *sync.WaitGroup) { - defer wg.Done() - - io.Copy(one, another) // nolint: errcheck -} diff --git a/faketls/consts.go b/faketls/consts.go deleted file mode 100644 index 9bd2353..0000000 --- a/faketls/consts.go +++ /dev/null @@ -1,30 +0,0 @@ -package faketls - -import ( - "errors" - "time" -) - -const ( - TimeSkew = 5 * time.Second - TimeFromBoot = 24 * 60 * 60 -) - -var ( - errBadDigest = errors.New("bad digest") - errBadTime = errors.New("bad time") - - faketlsStartBytes = [...]byte{ - 0x16, - 0x03, - 0x01, - 0x02, - 0x00, - 0x01, - 0x00, - 0x01, - 0xfc, - 0x03, - 0x03, - } -) diff --git a/go.mod b/go.mod index a2c7190..2b87317 100644 --- a/go.mod +++ b/go.mod @@ -1,25 +1,3 @@ -module github.com/9seconds/mtg +module github.com/9seconds/mtg/v2 -go 1.13 - -require ( - github.com/VictoriaMetrics/fastcache v1.5.7 - github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 - github.com/beevik/ntp v0.3.0 - github.com/golang/snappy v0.0.3 // indirect - github.com/prometheus/client_golang v1.9.0 - github.com/prometheus/common v0.18.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/smira/go-statsd v1.3.2 - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.16.0 - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 - golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect - golang.org/x/mod v0.4.1 // indirect - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 - golang.org/x/tools v0.1.0 // indirect - google.golang.org/protobuf v1.25.0 // indirect - gopkg.in/alecthomas/kingpin.v2 v2.2.6 - honnef.co/go/tools v0.0.1-2020.1.3 // indirect -) +go 1.16 diff --git a/go.sum b/go.sum index 2433d93..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,472 +0,0 @@ -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= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= -github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4= -github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= -github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -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/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= -github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smira/go-statsd v1.3.2 h1:1EeuzxNZ/TD9apbTOFSM9nulqfcsQFmT4u1A2DREabI= -github.com/smira/go-statsd v1.3.2/go.mod h1:1srXJ9/pbnN04G8f4F1jUzsGOnwkPKXciyqpewGlkC4= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/hub/connection.go b/hub/connection.go deleted file mode 100644 index e96cae9..0000000 --- a/hub/connection.go +++ /dev/null @@ -1,172 +0,0 @@ -package hub - -import ( - "fmt" - "math/rand" - "sync" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/mtproto" - "github.com/9seconds/mtg/mtproto/rpc" - "github.com/9seconds/mtg/protocol" - "go.uber.org/zap" -) - -const connectionTTL = time.Hour - -type connection struct { - conn conntypes.PacketReadWriteCloser - proxyConns map[string]*ProxyConn - closeOnce sync.Once - proxyConnsMutex sync.RWMutex - id int - logger *zap.SugaredLogger - - channelDone chan struct{} - channelWrite chan conntypes.Packet - channelRead chan *rpc.ProxyResponse - channelConnAttach chan *ProxyConn - channelConnDetach chan conntypes.ConnID -} - -func (c *connection) run() { // nolint: cyclop - defer c.Close() - - ttl := time.NewTimer(connectionTTL) - defer ttl.Stop() - - for { - select { - case <-c.channelDone: - for _, v := range c.proxyConns { - v.Close() - } - - return - case <-ttl.C: - c.logger.Debugw("Closing connection by TTL") - c.Close() - case resp := <-c.channelRead: - if channel, ok := c.proxyConns[string(resp.ConnID[:])]; ok { - if resp.Type == rpc.ProxyResponseTypeCloseExt { - channel.Close() - } else { - channel.put(resp) - } - } - case packet := <-c.channelWrite: - if err := c.conn.Write(packet); err != nil { - c.logger.Debugw("Cannot write packet", "error", err) - c.Close() - } - case conn := <-c.channelConnAttach: - c.proxyConnsMutex.Lock() - c.proxyConns[string(conn.req.ConnID[:])] = conn - c.proxyConnsMutex.Unlock() - conn.channelWrite = c.channelWrite - case connID := <-c.channelConnDetach: - if conn, ok := c.proxyConns[string(connID[:])]; ok { - c.proxyConnsMutex.Lock() - delete(c.proxyConns, string(connID[:])) - c.proxyConnsMutex.Unlock() - conn.Close() - } - } - } -} - -func (c *connection) readLoop() { - for { - packet, err := c.conn.Read() - if err != nil { - c.logger.Debugw("Cannot read packet", "error", err) - c.Close() - - return - } - - response, err := rpc.ParseProxyResponse(packet) - if err != nil { - c.logger.Debugw("Failed response", "error", err) - - continue - } - - select { - case <-c.channelDone: - return - case c.channelRead <- response: - } - } -} - -func (c *connection) Close() { - c.closeOnce.Do(func() { - c.logger.Debugw("Closing connection") - - close(c.channelDone) - c.conn.Close() - }) -} - -func (c *connection) Done() bool { - select { - case <-c.channelDone: - return true - default: - return c.Len() == 0 - } -} - -func (c *connection) Len() int { - c.proxyConnsMutex.RLock() - defer c.proxyConnsMutex.RUnlock() - - return len(c.proxyConns) -} - -func (c *connection) Attach(conn *ProxyConn) error { - select { - case <-c.channelDone: - return ErrClosed - case c.channelConnAttach <- conn: - return nil - } -} - -func (c *connection) Detach(connID conntypes.ConnID) { - select { - case <-c.channelDone: - case c.channelConnDetach <- connID: - } -} - -func newConnection(req *protocol.TelegramRequest) (*connection, error) { - conn, err := mtproto.TelegramProtocol(req) - if err != nil { - return nil, fmt.Errorf("cannot create a new connection: %w", err) - } - - id := rand.Int() // nolint: gosec - rv := &connection{ - conn: conn, - id: id, - logger: zap.S().Named("hub-connection").With("id", id, - "dc", req.ClientProtocol.DC(), - "protocol", req.ClientProtocol.ConnectionProtocol()), - proxyConns: make(map[string]*ProxyConn), - - channelRead: make(chan *rpc.ProxyResponse, 1), - channelDone: make(chan struct{}), - channelWrite: make(chan conntypes.Packet), - channelConnAttach: make(chan *ProxyConn), - channelConnDetach: make(chan conntypes.ConnID), - } - - go rv.readLoop() - - go rv.run() - - return rv, nil -} diff --git a/hub/connection_list.go b/hub/connection_list.go deleted file mode 100644 index d1d6a61..0000000 --- a/hub/connection_list.go +++ /dev/null @@ -1,70 +0,0 @@ -package hub - -import ( - "fmt" - "sort" - - "github.com/9seconds/mtg/config" -) - -type connectionList struct { - connections []*connection -} - -func (c *connectionList) get(conn *ProxyConn) (*connection, error) { - if len(c.connections) > 0 && c.connections[0].Len() < config.C.MultiplexPerConnection { - if err := c.connections[0].Attach(conn); err == nil { - return c.connections[0], nil - } - } - - newConn, err := newConnection(conn.req) - if err != nil { - return nil, fmt.Errorf("cannot allocate a new connection: %w", err) - } - - if err = newConn.Attach(conn); err != nil { - newConn.Close() - - return nil, fmt.Errorf("cannot attach to the newly created connection: %w", err) - } - - c.connections = append(c.connections, newConn) - lastIndex := len(c.connections) - 1 - c.connections[0], c.connections[lastIndex] = c.connections[lastIndex], c.connections[0] - - return newConn, nil -} - -func (c *connectionList) gc() { - prevLen := len(c.connections) - if prevLen == 0 { - return - } - - for i := len(c.connections) - 1; i >= 0; i-- { - lastIndex := len(c.connections) - 1 - - if c.connections[i].Done() { - c.connections[i].Close() - - if len(c.connections)-1 == i { - c.connections = c.connections[:lastIndex] - } else { - c.connections[i], c.connections[lastIndex] = c.connections[lastIndex], c.connections[i] - } - } - } - - if prevLen != len(c.connections) { - c.sort() - } -} - -func (c *connectionList) sort() { - if len(c.connections) > 1 { - sort.Slice(c.connections, func(i, j int) bool { - return c.connections[i].Len() < c.connections[j].Len() - }) - } -} diff --git a/hub/hub.go b/hub/hub.go deleted file mode 100644 index edfc442..0000000 --- a/hub/hub.go +++ /dev/null @@ -1,40 +0,0 @@ -package hub - -import ( - "context" - "sync" - - "github.com/9seconds/mtg/protocol" -) - -type hub struct { - muxes map[int32]*mux - mutex sync.RWMutex - ctx context.Context -} - -func (h *hub) Register(req *protocol.TelegramRequest) (*ProxyConn, error) { - return h.getMux(req).Get(req) -} - -func (h *hub) getMux(req *protocol.TelegramRequest) *mux { - var key int32 = 32767 + int32(req.ClientProtocol.DC()) + 100000*int32(req.ClientProtocol.ConnectionProtocol()) - - h.mutex.RLock() - m, ok := h.muxes[key] - h.mutex.RUnlock() - - if !ok { - h.mutex.Lock() - m, ok = h.muxes[key] - - if !ok { - m = newMux(h.ctx) - h.muxes[key] = m - } - - h.mutex.Unlock() - } - - return m -} diff --git a/hub/init.go b/hub/init.go deleted file mode 100644 index 19f5289..0000000 --- a/hub/init.go +++ /dev/null @@ -1,24 +0,0 @@ -package hub - -import ( - "context" - "errors" - "sync" -) - -var ( - ErrTimeout = errors.New("timeout") - ErrClosed = errors.New("context is closed") - - Hub Interface - initOnce sync.Once -) - -func Init(ctx context.Context) { - initOnce.Do(func() { - Hub = &hub{ - muxes: make(map[int32]*mux), - ctx: ctx, - } - }) -} diff --git a/hub/interface.go b/hub/interface.go deleted file mode 100644 index a1efcdc..0000000 --- a/hub/interface.go +++ /dev/null @@ -1,7 +0,0 @@ -package hub - -import "github.com/9seconds/mtg/protocol" - -type Interface interface { - Register(*protocol.TelegramRequest) (*ProxyConn, error) -} diff --git a/hub/mux.go b/hub/mux.go deleted file mode 100644 index f812b07..0000000 --- a/hub/mux.go +++ /dev/null @@ -1,90 +0,0 @@ -package hub - -import ( - "context" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/protocol" -) - -const muxGCEvery = time.Minute - -type muxNewRequest struct { - req *protocol.TelegramRequest - resp chan<- muxNewResponse -} - -type muxNewResponse struct { - conn *ProxyConn - err error -} - -type mux struct { - connections connectionList - clients map[string]*connection - ctx context.Context - channelClosed chan conntypes.ConnID - channelNew chan muxNewRequest -} - -func (m *mux) run() { - gcTicker := time.NewTicker(muxGCEvery) - defer gcTicker.Stop() - - for { - select { - case <-m.ctx.Done(): - for _, v := range m.clients { - v.Close() - } - - return - case <-gcTicker.C: - m.connections.gc() - case req := <-m.channelNew: - m.connections.gc() - proxyConn := newProxyConn(req.req, m.channelClosed) - conn, err := m.connections.get(proxyConn) - - if err == nil { - m.clients[string(req.req.ConnID[:])] = conn - } - - req.resp <- muxNewResponse{ - conn: proxyConn, - err: err, - } - close(req.resp) - case connID := <-m.channelClosed: - if conn, ok := m.clients[string(connID[:])]; ok { - conn.Detach(connID) - delete(m.clients, string(connID[:])) - } - } - } -} - -func (m *mux) Get(req *protocol.TelegramRequest) (*ProxyConn, error) { - resp := make(chan muxNewResponse) - m.channelNew <- muxNewRequest{ - req: req, - resp: resp, - } - - rv := <-resp - - return rv.conn, rv.err -} - -func newMux(ctx context.Context) *mux { - m := &mux{ - ctx: ctx, - clients: make(map[string]*connection), - channelClosed: make(chan conntypes.ConnID, 1), - channelNew: make(chan muxNewRequest), - } - go m.run() - - return m -} diff --git a/hub/proxy_conn.go b/hub/proxy_conn.go deleted file mode 100644 index 331d4c8..0000000 --- a/hub/proxy_conn.go +++ /dev/null @@ -1,79 +0,0 @@ -package hub - -import ( - "sync" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/mtproto/rpc" - "github.com/9seconds/mtg/protocol" -) - -const ( - proxyConnWriteTimeout = 2 * time.Minute - proxyConnReadTimeout = 2 * time.Minute - - proxyConnBackpressureAfter = 10 -) - -type ProxyConn struct { - closeOnce sync.Once - req *protocol.TelegramRequest - channelResponse chan *rpc.ProxyResponse - channelClosed chan<- conntypes.ConnID - channelWrite chan<- conntypes.Packet - channelDone chan struct{} -} - -func (p *ProxyConn) Read() (*rpc.ProxyResponse, error) { - timer := time.NewTimer(proxyConnReadTimeout) - defer timer.Stop() - - select { - case <-timer.C: - return nil, ErrTimeout - case <-p.channelDone: - return nil, ErrClosed - case packet := <-p.channelResponse: - return packet, nil - } -} - -func (p *ProxyConn) Write(packet conntypes.Packet) error { - timer := time.NewTimer(proxyConnWriteTimeout) - defer timer.Stop() - - select { - case <-timer.C: - return ErrTimeout - case <-p.channelDone: - return ErrClosed - case p.channelWrite <- packet: - return nil - } -} - -func (p *ProxyConn) put(response *rpc.ProxyResponse) { - select { - case <-p.channelDone: - case p.channelResponse <- response: - } -} - -func (p *ProxyConn) Close() { - p.closeOnce.Do(func() { - close(p.channelDone) - go func() { - p.channelClosed <- p.req.ConnID - }() - }) -} - -func newProxyConn(req *protocol.TelegramRequest, channelClosed chan<- conntypes.ConnID) *ProxyConn { - return &ProxyConn{ - channelResponse: make(chan *rpc.ProxyResponse, proxyConnBackpressureAfter), - channelDone: make(chan struct{}), - channelClosed: channelClosed, - req: req, - } -} diff --git a/main.go b/main.go index b16f040..8c4cef3 100644 --- a/main.go +++ b/main.go @@ -2,189 +2,11 @@ package main import ( "math/rand" - "os" - "runtime/debug" - "strings" "time" - - "github.com/9seconds/mtg/cli" - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/utils" - kingpin "gopkg.in/alecthomas/kingpin.v2" ) var version = "dev" // has to be set by ldflags -var ( - app = kingpin.New("mtg", "Simple MTPROTO proxy.") - - generateSecretCommand = app.Command("generate-secret", - "Generate new secret") - generateCloakHost = generateSecretCommand.Flag("cloak-host", - "A host to use for TLS cloaking."). - Short('c'). - Default("storage.googleapis.com"). - String() - generateSecretType = generateSecretCommand.Arg("type", - "A type of secret to generate. Valid options are 'simple', 'secured' and 'tls'"). - Required(). - Enum("simple", "secured", "tls") - - runCommand = app.Command("run", - "Run new proxy instance") - runDebug = runCommand.Flag("debug", - "Run in debug mode."). - Short('d'). - Envar("MTG_DEBUG"). - Bool() - runVerbose = runCommand.Flag("verbose", - "Run in verbose mode."). - Short('v'). - Envar("MTG_VERBOSE"). - Bool() - runPreferIP = runCommand.Flag("prefer-ip", - "Prefer this IP protocol if possible. Valid options are 'ipv4' and 'ipv6'"). - Envar("MTG_PREFER_DIRECT_IP"). - Default("ipv6"). - Enum("ipv4", "ipv6") - runBind = runCommand.Flag("bind", - "Host:Port to bind proxy to."). - Short('b'). - Envar("MTG_BIND"). - Default("0.0.0.0:3128"). - TCP() - runPublicIPv4 = runCommand.Flag("public-ipv4", - "Which IPv4 host:port to use."). - Short('4'). - Envar("MTG_IPV4"). - TCP() - runPublicIPv6 = runCommand.Flag("public-ipv6", - "Which IPv6 host:port to use."). - Short('6'). - Envar("MTG_IPV6"). - TCP() - runStatsBind = runCommand.Flag("stats-bind", - "Which Host:Port to bind stats server to."). - Short('t'). - Envar("MTG_STATS_BIND"). - Default("127.0.0.1:3129"). - TCP() - runStatsNamespace = runCommand.Flag("stats-namespace", - "Which namespace to use for Prometheus."). - Envar("MTG_STATS_NAMESPACE"). - Default("mtg"). - String() - runStatsdAddress = runCommand.Flag("statsd-addr", - "Host:port of statsd server"). - Envar("MTG_STATSD_ADDR"). - TCP() - runStatsdTagsFormat = runCommand.Flag("statsd-tags-format", - "Which tag format should we use to send stats metrics. Valid options are 'datadog' and 'influxdb'."). - Envar("MTG_STATSD_TAGS_FORMAT"). - Default("influxdb"). - Enum("datadog", "influxdb") - runStatsdTags = runCommand.Flag("statsd-tags", - "Tags to use for working with statsd (specified as 'key=value')."). - Envar("MTG_STATSD_TAGS"). - StringMap() - runWriteBufferSize = runCommand.Flag("write-buffer", - "Write buffer size. You can think about it as a buffer from client to Telegram."). - Short('w'). - Envar("MTG_BUFFER_WRITE"). - Default("32KB"). - Bytes() - runReadBufferSize = runCommand.Flag("read-buffer", - "Read buffer size. You can think about it as a buffer from Telegram to client."). - Short('r'). - Envar("MTG_BUFFER_READ"). - Default("32KB"). - Bytes() - runTLSCloakPort = runCommand.Flag("cloak-port", - "Port which should be used for host cloaking."). - Envar("MTG_CLOAK_PORT"). - Default("443"). - Uint16() - runAntiReplayMaxSize = runCommand.Flag("anti-replay-max-size", - "Max size of antireplay cache."). - Envar("MTG_ANTIREPLAY_MAXSIZE"). - Default("128MB"). - Bytes() - runMultiplexPerConnection = runCommand.Flag("multiplex-per-connection", - "How many clients can share a single connection to Telegram."). - Envar("MTG_MULTIPLEX_PERCONNECTION"). - Default("50"). - Uint() - runNTPServers = runCommand.Flag("ntp-server", - "A list of NTP servers to use."). - Envar("MTG_NTP_SERVERS"). - Default("0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org"). - Strings() - runSecret = runCommand.Arg("secret", "Secret of this proxy.").Required().HexBytes() - runAdtag = runCommand.Arg("adtag", "ADTag of the proxy.").HexBytes() -) - func main() { rand.Seed(time.Now().UTC().UnixNano()) - app.Version(getVersion()) - app.HelpFlag.Short('h') - - if err := utils.SetLimits(); err != nil { - cli.Fatal(err) - } - - switch kingpin.MustParse(app.Parse(os.Args[1:])) { - case generateSecretCommand.FullCommand(): - cli.Generate(*generateSecretType, *generateCloakHost) - case runCommand.FullCommand(): - err := config.Init( - config.Opt{Option: config.OptionTypeDebug, Value: *runDebug}, - config.Opt{Option: config.OptionTypeVerbose, Value: *runVerbose}, - config.Opt{Option: config.OptionTypePreferIP, Value: *runPreferIP}, - config.Opt{Option: config.OptionTypeBind, Value: *runBind}, - config.Opt{Option: config.OptionTypePublicIPv4, Value: *runPublicIPv4}, - config.Opt{Option: config.OptionTypePublicIPv6, Value: *runPublicIPv6}, - config.Opt{Option: config.OptionTypeStatsBind, Value: *runStatsBind}, - config.Opt{Option: config.OptionTypeStatsNamespace, Value: *runStatsNamespace}, - config.Opt{Option: config.OptionTypeStatsdAddress, Value: *runStatsdAddress}, - config.Opt{Option: config.OptionTypeStatsdTagsFormat, Value: *runStatsdTagsFormat}, - config.Opt{Option: config.OptionTypeStatsdTags, Value: *runStatsdTags}, - config.Opt{Option: config.OptionTypeWriteBufferSize, Value: *runWriteBufferSize}, - config.Opt{Option: config.OptionTypeReadBufferSize, Value: *runReadBufferSize}, - config.Opt{Option: config.OptionTypeCloakPort, Value: *runTLSCloakPort}, - config.Opt{Option: config.OptionTypeAntiReplayMaxSize, Value: *runAntiReplayMaxSize}, - config.Opt{Option: config.OptionTypeMultiplexPerConnection, Value: *runMultiplexPerConnection}, - config.Opt{Option: config.OptionTypeNTPServers, Value: *runNTPServers}, - config.Opt{Option: config.OptionTypeSecret, Value: *runSecret}, - config.Opt{Option: config.OptionTypeAdtag, Value: *runAdtag}, - ) - if err != nil { - cli.Fatal(err) - } - - if err := cli.Proxy(); err != nil { - cli.Fatal(err) - } - } -} - -func getVersion() string { - if version != "dev" { - return version - } - - info, ok := debug.ReadBuildInfo() - if !ok { - return version - } - - builder := strings.Builder{} - builder.WriteString(info.Main.Version) - - if info.Main.Sum != "" { - builder.WriteString(" (checksum: ") - builder.WriteString(info.Main.Sum) - builder.WriteRune(')') - } - - return builder.String() } diff --git a/mtproto/protocol.go b/mtproto/protocol.go deleted file mode 100644 index a880d10..0000000 --- a/mtproto/protocol.go +++ /dev/null @@ -1,102 +0,0 @@ -package mtproto - -import ( - "fmt" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/mtproto/rpc" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/telegram" - "github.com/9seconds/mtg/wrappers/packet" - "github.com/9seconds/mtg/wrappers/stream" -) - -func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteCloser, error) { - conn, err := telegram.Middle.Dial(req.ClientProtocol.DC(), - req.ClientProtocol.ConnectionProtocol()) - if err != nil { - return nil, fmt.Errorf("cannot connect to telegram: %w", err) - } - - rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce) - - rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn) - if err != nil { - return nil, fmt.Errorf("cannot do nonce request: %w", err) - } - - rpcNonceResp, err := getRPCNonceResponse(rpcNonceConn, rpcNonceReq) - if err != nil { - return nil, fmt.Errorf("cannot get nonce response: %w", err) - } - - secureConn := stream.NewMiddleProxyCipher(conn, rpcNonceReq, rpcNonceResp, telegram.Middle.Secret()) - frameConn := packet.NewMtprotoFrame(secureConn, rpc.SeqNoHandshake) - - if err := doRPCHandshakeRequest(frameConn); err != nil { - return nil, fmt.Errorf("cannot do handshake request: %w", err) - } - - if err := getRPCHandshakeResponse(frameConn); err != nil { - return nil, fmt.Errorf("cannot get handshake response: %w", err) - } - - return frameConn, nil -} - -func doRPCNonceRequest(conn conntypes.BasePacketWriter) (*rpc.NonceRequest, error) { - rpcNonceReq, err := rpc.NewNonceRequest(telegram.Middle.Secret()) - if err != nil { - panic(err) - } - - if err := conn.Write(rpcNonceReq.Bytes()); err != nil { - return nil, err // nolint: wrapcheck - } - - return rpcNonceReq, nil -} - -func getRPCNonceResponse(conn conntypes.BasePacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) { - packet, err := conn.Read() - if err != nil { - return nil, fmt.Errorf("cannot read from connection: %w", err) - } - - resp, err := rpc.NewNonceResponse(packet) - if err != nil { - return nil, fmt.Errorf("cannot build rpc nonce response: %w", err) - } - - if err = resp.Valid(req); err != nil { - return nil, fmt.Errorf("invalid nonce response: %w", err) - } - - return resp, nil -} - -func doRPCHandshakeRequest(conn conntypes.BasePacketWriter) error { - if err := conn.Write(rpc.HandshakeRequest); err != nil { - return fmt.Errorf("cannot make a request: %w", err) - } - - return nil -} - -func getRPCHandshakeResponse(conn conntypes.BasePacketReader) error { - packet, err := conn.Read() - if err != nil { - return fmt.Errorf("cannot read a response: %w", err) - } - - resp, err := rpc.NewHandshakeResponse(packet) - if err != nil { - return fmt.Errorf("cannot build a handshake response: %w", err) - } - - if err := resp.Valid(); err != nil { - return fmt.Errorf("invalid handshake response: %w", err) - } - - return nil -} diff --git a/mtproto/rpc/consts.go b/mtproto/rpc/consts.go deleted file mode 100644 index 9cb7ed4..0000000 --- a/mtproto/rpc/consts.go +++ /dev/null @@ -1,28 +0,0 @@ -package rpc - -// SeqNo* is the number of the sequence which have special meaning for -// the Telegram. -const ( - SeqNoNonce = -2 - SeqNoHandshake = -1 -) - -// Different constants for RPC protocol. -var ( - TagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e} - TagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44} - TagSimpleAck = []byte{0x9b, 0x40, 0xac, 0x3b} - TagHandshake = []byte{0xf5, 0xee, 0x82, 0x76} - TagNonce = []byte{0xaa, 0x87, 0xcb, 0x7a} - TagProxyRequest = []byte{0xee, 0xf1, 0xce, 0x36} - - NonceCryptoAES = []byte{0x01, 0x00, 0x00, 0x00} - - HandshakeFlags = []byte{0x00, 0x00, 0x00, 0x00} - - ProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00} - ProxyRequestProxyTag = []byte{0xae, 0x26, 0x1e, 0xdb} - - HandshakeSenderPID = []byte("IPIPPRPDTIME") - HandshakePeerPID = []byte("IPIPPRPDTIME") -) diff --git a/mtproto/rpc/handshake_request.go b/mtproto/rpc/handshake_request.go deleted file mode 100644 index e0971cc..0000000 --- a/mtproto/rpc/handshake_request.go +++ /dev/null @@ -1,5 +0,0 @@ -package rpc - -var HandshakeRequest = append(TagHandshake, - append(HandshakeFlags, - append(HandshakeSenderPID, HandshakePeerPID...)...)...) diff --git a/mtproto/rpc/handshake_response.go b/mtproto/rpc/handshake_response.go deleted file mode 100644 index dc25109..0000000 --- a/mtproto/rpc/handshake_response.go +++ /dev/null @@ -1,54 +0,0 @@ -package rpc - -import ( - "bytes" - "errors" - "fmt" -) - -type HandshakeResponse struct { - Type []byte - Flags []byte - SenderPID []byte - PeerPID []byte -} - -// Bytes returns a serialized handshake response. -func (r *HandshakeResponse) Bytes() []byte { - buf := &bytes.Buffer{} - - buf.Write(r.Type) - buf.Write(r.Flags) - buf.Write(r.SenderPID) - buf.Write(r.PeerPID) - - return buf.Bytes() -} - -// Valid checks that handshake response compliments request. -func (r *HandshakeResponse) Valid() error { - if !bytes.Equal(r.Type, TagHandshake) { - return errors.New("unexpected handshake tag") - } - - if !bytes.Equal(r.PeerPID, HandshakeSenderPID) { - return errors.New("incorrect sender PID") - } - - return nil -} - -// NewHandshakeResponse constructs new handshake response from the given -// data. -func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) { - if len(data) != 32 { - return nil, fmt.Errorf("incorrect handshake response length %d", len(data)) - } - - return &HandshakeResponse{ - Type: data[:4], - Flags: data[4:8], - SenderPID: data[8:20], - PeerPID: data[20:], - }, nil -} diff --git a/mtproto/rpc/nonce_request.go b/mtproto/rpc/nonce_request.go deleted file mode 100644 index 8a06c26..0000000 --- a/mtproto/rpc/nonce_request.go +++ /dev/null @@ -1,50 +0,0 @@ -package rpc - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "fmt" - "time" -) - -type NonceRequest struct { - KeySelector []byte - CryptoTS []byte - Nonce []byte -} - -// Bytes returns serialized nonce request. -func (r *NonceRequest) Bytes() []byte { - buf := &bytes.Buffer{} - - buf.Write(TagNonce) - buf.Write(r.KeySelector) - buf.Write(NonceCryptoAES) - buf.Write(r.CryptoTS) - buf.Write(r.Nonce) - - return buf.Bytes() -} - -// NewNonceRequest builds new none request based on proxy secret. -func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) { - nonce := make([]byte, 16) - keySelector := make([]byte, 4) - cryptoTS := make([]byte, 4) - - if _, err := rand.Read(nonce); err != nil { - return nil, fmt.Errorf("cannot generate nonce: %w", err) - } - - copy(keySelector, proxySecret) - - timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // 256 ^ 4 - do not know how to name - binary.LittleEndian.PutUint32(cryptoTS, uint32(timestamp)) - - return &NonceRequest{ - KeySelector: keySelector, - CryptoTS: cryptoTS, - Nonce: nonce, - }, nil -} diff --git a/mtproto/rpc/nonce_response.go b/mtproto/rpc/nonce_response.go deleted file mode 100644 index a6d831e..0000000 --- a/mtproto/rpc/nonce_response.go +++ /dev/null @@ -1,60 +0,0 @@ -package rpc - -import ( - "bytes" - "errors" - "fmt" -) - -type NonceResponse struct { - NonceRequest - - Type []byte - Crypto []byte -} - -// Bytes returns serialized form of the nonce response. -func (r *NonceResponse) Bytes() []byte { - buf := bytes.Buffer{} - - buf.Write(r.Type) - buf.Write(r.KeySelector) - buf.Write(r.Crypto) - buf.Write(r.CryptoTS) - buf.Write(r.Nonce) - - return buf.Bytes() -} - -func (r *NonceResponse) Valid(req *NonceRequest) error { - if !bytes.Equal(r.Type, TagNonce) { - return errors.New("unexpected RPC type") - } - - if !bytes.Equal(r.Crypto, NonceCryptoAES) { - return errors.New("unexpected crypto type") - } - - if !bytes.Equal(r.KeySelector, req.KeySelector) { - return errors.New("unexpected key selector") - } - - return nil -} - -// NewNonceResponse build new nonce response based on the given data. -func NewNonceResponse(data []byte) (*NonceResponse, error) { - if len(data) != 32 { - return nil, fmt.Errorf("unexpected message length %d", len(data)) - } - - return &NonceResponse{ - NonceRequest: NonceRequest{ - KeySelector: data[4:8], - CryptoTS: data[12:16], - Nonce: data[16:], - }, - Type: data[:4], - Crypto: data[8:12], - }, nil -} diff --git a/mtproto/rpc/proxy_flags.go b/mtproto/rpc/proxy_flags.go deleted file mode 100644 index 2179c66..0000000 --- a/mtproto/rpc/proxy_flags.go +++ /dev/null @@ -1,66 +0,0 @@ -package rpc - -import ( - "encoding/binary" - "strings" -) - -type ProxyRequestFlags uint32 - -const ( - ProxyRequestFlagsHasAdTag ProxyRequestFlags = 0x8 - ProxyRequestFlagsEncrypted ProxyRequestFlags = 0x2 - ProxyRequestFlagsMagic ProxyRequestFlags = 0x1000 - ProxyRequestFlagsExtMode2 ProxyRequestFlags = 0x20000 - ProxyRequestFlagsIntermediate ProxyRequestFlags = 0x20000000 - ProxyRequestFlagsAbdridged ProxyRequestFlags = 0x40000000 - ProxyRequestFlagsQuickAck ProxyRequestFlags = 0x80000000 - ProxyRequestFlagsPad ProxyRequestFlags = 0x8000000 -) - -var ProxyRequestFlagsEncryptedPrefix [8]byte - -func (r ProxyRequestFlags) Bytes() []byte { - converted := make([]byte, 4) - binary.LittleEndian.PutUint32(converted, uint32(r)) - - return converted -} - -func (r ProxyRequestFlags) String() string { - flags := make([]string, 0, 7) - - if r&ProxyRequestFlagsHasAdTag != 0 { - flags = append(flags, "HAS_AD_TAG") - } - - if r&ProxyRequestFlagsEncrypted != 0 { - flags = append(flags, "ENCRYPTED") - } - - if r&ProxyRequestFlagsMagic != 0 { - flags = append(flags, "MAGIC") - } - - if r&ProxyRequestFlagsExtMode2 != 0 { - flags = append(flags, "EXT_MODE_2") - } - - if r&ProxyRequestFlagsIntermediate != 0 { - flags = append(flags, "INTERMEDIATE") - } - - if r&ProxyRequestFlagsAbdridged != 0 { - flags = append(flags, "ABRIDGED") - } - - if r&ProxyRequestFlagsQuickAck != 0 { - flags = append(flags, "QUICK_ACK") - } - - if r&ProxyRequestFlagsPad != 0 { - flags = append(flags, "PAD") - } - - return strings.Join(flags, " | ") -} diff --git a/mtproto/rpc/proxy_response.go b/mtproto/rpc/proxy_response.go deleted file mode 100644 index 5366f34..0000000 --- a/mtproto/rpc/proxy_response.go +++ /dev/null @@ -1,53 +0,0 @@ -package rpc - -import ( - "bytes" - "fmt" - - "github.com/9seconds/mtg/conntypes" -) - -type ProxyResponseType uint8 - -const ( - ProxyResponseTypeAns ProxyResponseType = iota - ProxyResponseTypeSimpleAck - ProxyResponseTypeCloseExt -) - -type ProxyResponse struct { - Type ProxyResponseType - ConnID conntypes.ConnID - Payload conntypes.Packet -} - -func ParseProxyResponse(packet conntypes.Packet) (*ProxyResponse, error) { - var response ProxyResponse - - if len(packet) < 4 { - return nil, fmt.Errorf("incorrect packet length: %d", len(packet)) - } - - tag := packet[:4] - - switch { - case bytes.Equal(tag, TagProxyAns): - response.Type = ProxyResponseTypeAns - copy(response.ConnID[:], packet[8:16]) - response.Payload = packet[16:] - - return &response, nil - case bytes.Equal(tag, TagSimpleAck): - response.Type = ProxyResponseTypeSimpleAck - copy(response.ConnID[:], packet[4:12]) - response.Payload = packet[12:] - - return &response, nil - case bytes.Equal(tag, TagCloseExt): - response.Type = ProxyResponseTypeCloseExt - - return &response, nil - } - - return nil, fmt.Errorf("unknown response type %x", tag) -} diff --git a/ntp/ntp.go b/ntp/ntp.go deleted file mode 100644 index 97d5d63..0000000 --- a/ntp/ntp.go +++ /dev/null @@ -1,57 +0,0 @@ -package ntp - -import ( - "fmt" - "math/rand" - "time" - - "github.com/9seconds/mtg/config" - "github.com/beevik/ntp" - "go.uber.org/zap" -) - -const autoUpdatePeriod = time.Minute - -// Fetch fetches the data on time drift. -func Fetch() (time.Duration, error) { - url := config.C.NTPServers[rand.Intn(len(config.C.NTPServers))] // nolint: gosec - - resp, err := ntp.Query(url) - if err != nil { - return 0, fmt.Errorf("cannot fetch NTP server %s: %w", url, err) - } - - offsetInt := int64(resp.ClockOffset) - if offsetInt < 0 { - offsetInt = -offsetInt - } - - offset := time.Duration(offsetInt) - - return offset, nil -} - -// AutoUpdate runs periodic check of current time .drift state. -func AutoUpdate() { - logger := zap.S().Named("ntp") - - for range time.Tick(autoUpdatePeriod) { - diff, err := Fetch() - if err != nil { - logger.Debugw("Cannot fetch time from NTP", "error", err) - - continue - } - - switch { - case diff < 400*time.Millisecond: - logger.Debugw("NTP time drift", "value", diff.String()) - case diff < 600*time.Millisecond: - logger.Infow("NTP time drift", "value", diff.String()) - case diff < 800*time.Millisecond: - logger.Warnw("NTP time drift", "value", diff.String()) - default: - logger.Errorw("NTP time drift", "value", diff.String()) - } - } -} diff --git a/obfuscated2/client_protocol.go b/obfuscated2/client_protocol.go deleted file mode 100644 index 955ae9e..0000000 --- a/obfuscated2/client_protocol.go +++ /dev/null @@ -1,114 +0,0 @@ -package obfuscated2 - -import ( - "bytes" - "crypto/sha256" - "encoding/binary" - "errors" - "fmt" - "io" - "time" - - "github.com/9seconds/mtg/antireplay" - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/stats" - "github.com/9seconds/mtg/utils" - "github.com/9seconds/mtg/wrappers/stream" -) - -const clientProtocolHandshakeTimeout = 10 * time.Second - -type ClientProtocol struct { - connectionType conntypes.ConnectionType - connectionProtocol conntypes.ConnectionProtocol - dc conntypes.DC -} - -func (c *ClientProtocol) ConnectionType() conntypes.ConnectionType { - return c.connectionType -} - -func (c *ClientProtocol) ConnectionProtocol() conntypes.ConnectionProtocol { - return c.connectionProtocol -} - -func (c *ClientProtocol) DC() conntypes.DC { - return c.dc -} - -func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) { - fm, err := c.ReadFrame(socket) - if err != nil { - return nil, fmt.Errorf("cannot make a client handshake: %w", err) - } - - decHasher := sha256.New() - decHasher.Write(fm.Key()) // nolint: errcheck - decHasher.Write(config.C.Secret) // nolint: errcheck - decryptor := utils.MakeStreamCipher(decHasher.Sum(nil), fm.IV()) - - invertedFrame := fm.Invert() - encHasher := sha256.New() - encHasher.Write(invertedFrame.Key()) // nolint: errcheck - encHasher.Write(config.C.Secret) // nolint: errcheck - encryptor := utils.MakeStreamCipher(encHasher.Sum(nil), invertedFrame.IV()) - - decryptedFrame := Frame{} - decryptor.XORKeyStream(decryptedFrame.Bytes(), fm.Bytes()) - - magic := decryptedFrame.Magic() - - switch { - case bytes.Equal(magic, conntypes.ConnectionTagAbridged): - c.connectionType = conntypes.ConnectionTypeAbridged - case bytes.Equal(magic, conntypes.ConnectionTagIntermediate): - c.connectionType = conntypes.ConnectionTypeIntermediate - case bytes.Equal(magic, conntypes.ConnectionTagSecure): - c.connectionType = conntypes.ConnectionTypeSecure - default: - return nil, errors.New("unknown connection type") - } - - c.connectionProtocol = conntypes.ConnectionProtocolIPv4 - if socket.LocalAddr().IP.To4() == nil { - c.connectionProtocol = conntypes.ConnectionProtocolIPv6 - } - - buf := bytes.NewReader(decryptedFrame.DC()) - if err := binary.Read(buf, binary.LittleEndian, &c.dc); err != nil { - c.dc = conntypes.DCDefaultIdx - } - - replayKey := decryptedFrame.Unique() - if antireplay.Cache.HasObfuscated2(replayKey) { - stats.Stats.ReplayDetected() - - return nil, errors.New("replay attack is detected") - } - - antireplay.Cache.AddObfuscated2(replayKey) - - return stream.NewObfuscated2(socket, encryptor, decryptor), nil -} - -func (c *ClientProtocol) ReadFrame(socket conntypes.StreamReader) (fm Frame, err error) { - if _, err = io.ReadFull(handshakeReader{socket}, fm.Bytes()); err != nil { - err = fmt.Errorf("cannot extract obfuscated2 frame: %w", err) - } - - return -} - -type handshakeReader struct { - parent conntypes.StreamReader -} - -func (h handshakeReader) Read(p []byte) (int, error) { - return h.parent.ReadTimeout(p, clientProtocolHandshakeTimeout) -} - -func MakeClientProtocol() protocol.ClientProtocol { - return &ClientProtocol{} -} diff --git a/obfuscated2/frame.go b/obfuscated2/frame.go deleted file mode 100644 index e05cbd0..0000000 --- a/obfuscated2/frame.go +++ /dev/null @@ -1,54 +0,0 @@ -package obfuscated2 - -const ( - frameLenKey = 32 - frameLenIV = 16 - frameLenMagic = 4 - frameLenDC = 2 - - frameOffsetFirst = 8 - frameOffsetKey = frameOffsetFirst + frameLenKey - frameOffsetIV = frameOffsetKey + frameLenIV - frameOffsetMagic = frameOffsetIV + frameLenMagic - frameOffsetDC = frameOffsetMagic + frameLenDC - - frameLen = 64 -) - -// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd]. -type Frame struct { - data [frameLen]byte -} - -func (f *Frame) Bytes() []byte { - return f.data[:] -} - -func (f *Frame) Key() []byte { - return f.data[frameOffsetFirst:frameOffsetKey] -} - -func (f *Frame) IV() []byte { - return f.data[frameOffsetKey:frameOffsetIV] -} - -func (f *Frame) Magic() []byte { - return f.data[frameOffsetIV:frameOffsetMagic] -} - -func (f *Frame) DC() []byte { - return f.data[frameOffsetMagic:frameOffsetDC] -} - -func (f *Frame) Unique() []byte { - return f.data[frameOffsetFirst:frameOffsetDC] -} - -func (f *Frame) Invert() (nf Frame) { - nf = *f - for i := 0; i < frameLenKey+frameLenIV; i++ { - nf.data[frameOffsetFirst+i] = f.data[frameOffsetIV-1-i] - } - - return -} diff --git a/obfuscated2/telegram_protocol.go b/obfuscated2/telegram_protocol.go deleted file mode 100644 index cf17099..0000000 --- a/obfuscated2/telegram_protocol.go +++ /dev/null @@ -1,68 +0,0 @@ -package obfuscated2 - -import ( - "crypto/rand" - "fmt" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/telegram" - "github.com/9seconds/mtg/utils" - "github.com/9seconds/mtg/wrappers/stream" -) - -func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteCloser, error) { - conn, err := telegram.Direct.Dial(req.ClientProtocol.DC(), - req.ClientProtocol.ConnectionProtocol()) - if err != nil { - return nil, fmt.Errorf("cannot dial to telegram: %w", err) - } - - conn = stream.NewTimeout(conn) - conn = stream.NewCtx(req.Ctx, req.Cancel, conn) - fm := generateFrame(req.ClientProtocol) - data := fm.Bytes() - - encryptor := utils.MakeStreamCipher(fm.Key(), fm.IV()) - decryptedFrame := fm.Invert() - decryptor := utils.MakeStreamCipher(decryptedFrame.Key(), decryptedFrame.IV()) - - copyFrame := make([]byte, frameLen) - copy(copyFrame[:frameOffsetIV], data[:frameOffsetIV]) - encryptor.XORKeyStream(data, data) - copy(data[:frameOffsetIV], copyFrame[:frameOffsetIV]) - - if _, err := conn.Write(data); err != nil { - return nil, fmt.Errorf("cannot write handshake frame to telegram: %w", err) - } - - return stream.NewObfuscated2(conn, encryptor, decryptor), nil -} - -func generateFrame(cp protocol.ClientProtocol) (fm Frame) { - data := fm.Bytes() - - for { - if _, err := rand.Read(data); err != nil { - continue - } - - if data[0] == 0xef { - continue - } - - val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) - if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { - continue - } - - val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) - if val == 0x00000000 { - continue - } - - copy(fm.Magic(), cp.ConnectionType().Tag()) - - return - } -} diff --git a/protocol/interfaces.go b/protocol/interfaces.go deleted file mode 100644 index 2e27fc3..0000000 --- a/protocol/interfaces.go +++ /dev/null @@ -1,12 +0,0 @@ -package protocol - -import "github.com/9seconds/mtg/conntypes" - -type ClientProtocol interface { - Handshake(conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) - ConnectionType() conntypes.ConnectionType - ConnectionProtocol() conntypes.ConnectionProtocol - DC() conntypes.DC -} - -type ClientProtocolMaker func() ClientProtocol diff --git a/protocol/request.go b/protocol/request.go deleted file mode 100644 index 5f5d98d..0000000 --- a/protocol/request.go +++ /dev/null @@ -1,17 +0,0 @@ -package protocol - -import ( - "context" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type TelegramRequest struct { - Logger *zap.SugaredLogger - ClientConn conntypes.StreamReadWriteCloser - ConnID conntypes.ConnID - Ctx context.Context - Cancel context.CancelFunc - ClientProtocol ClientProtocol -} diff --git a/proxy/direct.go b/proxy/direct.go deleted file mode 100644 index 03fd9af..0000000 --- a/proxy/direct.go +++ /dev/null @@ -1,49 +0,0 @@ -package proxy - -import ( - "io" - "sync" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/obfuscated2" - "github.com/9seconds/mtg/protocol" - "go.uber.org/zap" -) - -const directPipeBufferSize = 1024 - -func directConnection(request *protocol.TelegramRequest) error { - telegramConnRaw, err := obfuscated2.TelegramProtocol(request) - if err != nil { - return err // nolint: wrapcheck - } - - telegramConn := telegramConnRaw.(conntypes.StreamReadWriteCloser) - - defer telegramConn.Close() - - wg := &sync.WaitGroup{} - wg.Add(2) - - go directPipe(telegramConn, request.ClientConn, wg, request.Logger) - - go directPipe(request.ClientConn, telegramConn, wg, request.Logger) - - wg.Wait() - - return nil -} - -func directPipe(dst io.WriteCloser, src io.ReadCloser, wg *sync.WaitGroup, logger *zap.SugaredLogger) { - defer func() { - dst.Close() - src.Close() - wg.Done() - }() - - buf := [directPipeBufferSize]byte{} - - if _, err := io.CopyBuffer(dst, src, buf[:]); err != nil { - logger.Debugw("Cannot pump sockets", "error", err) - } -} diff --git a/proxy/middle.go b/proxy/middle.go deleted file mode 100644 index 7f56991..0000000 --- a/proxy/middle.go +++ /dev/null @@ -1,70 +0,0 @@ -package proxy - -import ( - "sync" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/wrappers/packetack" - "go.uber.org/zap" -) - -func middleConnection(request *protocol.TelegramRequest) { - telegramConn, err := packetack.NewProxy(request) - if err != nil { - request.Logger.Debugw("Cannot dial to Telegram", "error", err) - - return - } - defer telegramConn.Close() - - var clientConn conntypes.PacketAckFullReadWriteCloser - - switch request.ClientProtocol.ConnectionType() { - case conntypes.ConnectionTypeAbridged: - clientConn = packetack.NewClientAbridged(request.ClientConn) - case conntypes.ConnectionTypeIntermediate: - clientConn = packetack.NewClientIntermediate(request.ClientConn) - case conntypes.ConnectionTypeSecure: - clientConn = packetack.NewClientIntermediateSecure(request.ClientConn) - case conntypes.ConnectionTypeUnknown: - panic("unknown connection type") - } - - wg := &sync.WaitGroup{} - wg.Add(2) - - go middlePipe(telegramConn, clientConn, wg, request.Logger) - - go middlePipe(clientConn, telegramConn, wg, request.Logger) - - wg.Wait() -} - -func middlePipe(dst conntypes.PacketAckWriteCloser, - src conntypes.PacketAckReadCloser, - wg *sync.WaitGroup, - logger *zap.SugaredLogger) { - defer func() { - dst.Close() - src.Close() - wg.Done() - }() - - for { - acks := conntypes.ConnectionAcks{} - - packet, err := src.Read(&acks) - if err != nil { - logger.Debugw("Cannot read packet", "error", err) - - return - } - - if err = dst.Write(packet, &acks); err != nil { - logger.Debugw("Cannot send packet", "error", err) - - return - } - } -} diff --git a/proxy/proxy.go b/proxy/proxy.go deleted file mode 100644 index 7be2a19..0000000 --- a/proxy/proxy.go +++ /dev/null @@ -1,100 +0,0 @@ -package proxy - -import ( - "context" - "net" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/protocol" - "github.com/9seconds/mtg/stats" - "github.com/9seconds/mtg/utils" - "github.com/9seconds/mtg/wrappers/stream" - "go.uber.org/zap" -) - -type Proxy struct { - Logger *zap.SugaredLogger - Context context.Context - ClientProtocolMaker protocol.ClientProtocolMaker -} - -func (p *Proxy) Serve(listener net.Listener) { - doneChan := p.Context.Done() - - for { - conn, err := listener.Accept() - if err != nil { - select { - case <-doneChan: - return - default: - p.Logger.Fatalw("Cannot allocate incoming connection", "error", err) - } - } - - go p.accept(conn) - } -} - -func (p *Proxy) accept(conn net.Conn) { - defer func() { - conn.Close() - - if err := recover(); err != nil { - stats.Stats.Crash() - p.Logger.Errorw("Crash of accept handler", "error", err) - } - }() - - connID := conntypes.NewConnID() - logger := p.Logger.With("connection_id", connID) - - if err := utils.InitTCP(conn, config.C.ClientReadBuffer(), config.C.ClientWriteBuffer()); err != nil { - logger.Errorw("Cannot initialize client TCP connection", "error", err) - - return - } - - ctx, cancel := context.WithCancel(p.Context) - defer cancel() - - clientConn := stream.NewClientConn(conn, connID) - clientConn = stream.NewCtx(ctx, cancel, clientConn) - clientConn = stream.NewTimeout(clientConn) - - defer clientConn.Close() - - clientProtocol := p.ClientProtocolMaker() - - clientConn, err := clientProtocol.Handshake(clientConn) - if err != nil { - stats.Stats.AuthenticationFailed() - logger.Warnw("Cannot perform client handshake", "error", err) - - return - } - - stats.Stats.ClientConnected(clientProtocol.ConnectionType(), clientConn.RemoteAddr()) - defer stats.Stats.ClientDisconnected(clientProtocol.ConnectionType(), clientConn.RemoteAddr()) - logger.Infow("Client connected", "addr", conn.RemoteAddr()) - - req := &protocol.TelegramRequest{ - Logger: logger, - ClientConn: clientConn, - ConnID: connID, - Ctx: ctx, - Cancel: cancel, - ClientProtocol: clientProtocol, - } - - err = nil - - if config.C.MiddleProxyMode() { - middleConnection(req) - } else { - err = directConnection(req) - } - - logger.Infow("Client disconnected", "error", err, "addr", conn.RemoteAddr()) -} diff --git a/run.sh b/run.sh deleted file mode 100755 index 338a4c8..0000000 --- a/run.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -# -# Configuration options (set by environment variables during script execution) -# - MTG_CONFIG - directory where mtg stores its configuration -# - MTG_IMAGENAME - a name of the docker image to use -# - MTG_PORT - which port of the host system should be used -# - MTG_CONTAINER - a name of the container to use -# -# Example: -# export MTG_CONFIG="$HOME/mtg_config" -# export MTG_IMAGENAME="nineseconds/mtg:latest" -# curl -sfL --compressed https://raw.githubusercontent.com/9seconds/mtg/master/run.sh | bash - -set -eu - -export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" -export MTG_CONFIG="${MTG_CONFIG:-$XDG_CONFIG_HOME/mtg}" - -if ! [ -x "$(command -v docker)" ]; then - echo 'Error: docker is not installed.' >&2 - exit 1 -fi - -id -Gn "$USER" | grep -qw 'docker' > /dev/null -if [ $? -eq 0 ] || [ "$(id -u)" -eq '0' ]; then - DOCKER_CMD="$(command -v docker)" -else - DOCKER_CMD="sudo $(command -v docker)" -fi - -mkdir -p "$MTG_CONFIG" || true - -MTG_SECRET="$MTG_CONFIG/secret" -MTG_ENV="$MTG_CONFIG/env" - -if [ ! -f "$MTG_ENV" ]; then - MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:stable}" - MTG_PORT="${MTG_PORT:-3128}" - MTG_CONTAINER="${MTG_CONTAINER:-mtg}" - - echo "MTG_IMAGENAME=$MTG_IMAGENAME" > "$MTG_ENV" - echo "MTG_PORT=$MTG_PORT" >> "$MTG_ENV" - echo "MTG_CONTAINER=$MTG_CONTAINER" >> "$MTG_ENV" -fi - -set -a -source "$MTG_ENV" -set +a - -$DOCKER_CMD pull "$MTG_IMAGENAME" > /dev/null -if [ ! -f "$MTG_SECRET" ]; then - $DOCKER_CMD run \ - --rm \ - "$MTG_IMAGENAME" \ - generate-secret tls -c "$(openssl rand -hex 16).com" \ - > "$MTG_SECRET" -fi - -echo "Proxy secret is $(cat "$MTG_SECRET"). Port is $MTG_PORT." - -$DOCKER_CMD ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r $DOCKER_CMD rm -fv > /dev/null -$DOCKER_CMD run \ - -d \ - --restart=unless-stopped \ - --name "$MTG_CONTAINER" \ - --ulimit nofile=51200:51200 \ - -p "$MTG_PORT:3128" \ - "$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")" > /dev/null diff --git a/stats/interfaces.go b/stats/interfaces.go deleted file mode 100644 index 083a8ea..0000000 --- a/stats/interfaces.go +++ /dev/null @@ -1,60 +0,0 @@ -package stats - -import ( - "net" - - "github.com/9seconds/mtg/conntypes" -) - -type IngressTrafficInterface interface { - IngressTraffic(int) -} - -type EgressTrafficInterface interface { - EgressTraffic(int) -} - -type ClientConnectedInterface interface { - ClientConnected(conntypes.ConnectionType, *net.TCPAddr) -} - -type ClientDisconnectedInterface interface { - ClientDisconnected(conntypes.ConnectionType, *net.TCPAddr) -} - -type TelegramConnectedInterface interface { - TelegramConnected(conntypes.DC, *net.TCPAddr) -} - -type TelegramDisconnectedInterface interface { - TelegramDisconnected(conntypes.DC, *net.TCPAddr) -} - -type CrashInterface interface { - Crash() -} - -type ReplayDetectedInterface interface { - ReplayDetected() -} - -type AuthenticationFailedInterface interface { - AuthenticationFailed() -} - -type CloakedRequestInterface interface { - CloakedRequest() -} - -type Interface interface { - IngressTrafficInterface - EgressTrafficInterface - ClientConnectedInterface - ClientDisconnectedInterface - TelegramConnectedInterface - TelegramDisconnectedInterface - CrashInterface - ReplayDetectedInterface - AuthenticationFailedInterface - CloakedRequestInterface -} diff --git a/stats/multi_stats.go b/stats/multi_stats.go deleted file mode 100644 index 569c93c..0000000 --- a/stats/multi_stats.go +++ /dev/null @@ -1,69 +0,0 @@ -package stats - -import ( - "net" - - "github.com/9seconds/mtg/conntypes" -) - -type multiStats []Interface - -func (m multiStats) IngressTraffic(traffic int) { - for i := range m { - go m[i].IngressTraffic(traffic) - } -} - -func (m multiStats) EgressTraffic(traffic int) { - for i := range m { - go m[i].EgressTraffic(traffic) - } -} - -func (m multiStats) ClientConnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - for i := range m { - go m[i].ClientConnected(connectionType, addr) - } -} - -func (m multiStats) ClientDisconnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - for i := range m { - go m[i].ClientDisconnected(connectionType, addr) - } -} - -func (m multiStats) TelegramConnected(dc conntypes.DC, addr *net.TCPAddr) { - for i := range m { - go m[i].TelegramConnected(dc, addr) - } -} - -func (m multiStats) TelegramDisconnected(dc conntypes.DC, addr *net.TCPAddr) { - for i := range m { - go m[i].TelegramDisconnected(dc, addr) - } -} - -func (m multiStats) Crash() { - for i := range m { - go m[i].Crash() - } -} - -func (m multiStats) ReplayDetected() { - for i := range m { - go m[i].ReplayDetected() - } -} - -func (m multiStats) AuthenticationFailed() { - for i := range m { - go m[i].AuthenticationFailed() - } -} - -func (m multiStats) CloakedRequest() { - for i := range m { - go m[i].CloakedRequest() - } -} diff --git a/stats/stats.go b/stats/stats.go deleted file mode 100644 index 80a3250..0000000 --- a/stats/stats.go +++ /dev/null @@ -1,41 +0,0 @@ -package stats - -import ( - "context" - "fmt" - "net" - "net/http" - - "github.com/9seconds/mtg/config" -) - -var Stats Interface - -func Init(ctx context.Context) error { - mux := http.NewServeMux() - - stats := []Interface{newStatsPrometheus(mux)} - if config.C.StatsdAddr != nil { - stats = append(stats, newStatsStatsd()) - } - - listener, err := net.Listen("tcp", config.C.StatsBind.String()) - if err != nil { - return fmt.Errorf("cannot initialize stats server: %w", err) - } - - srv := http.Server{ - Handler: mux, - } - - go srv.Serve(listener) // nolint: errcheck - - go func() { - <-ctx.Done() - srv.Shutdown(context.Background()) // nolint: errcheck - }() - - Stats = multiStats(stats) - - return nil -} diff --git a/stats/stats_prometheus.go b/stats/stats_prometheus.go deleted file mode 100644 index 687c635..0000000 --- a/stats/stats_prometheus.go +++ /dev/null @@ -1,156 +0,0 @@ -package stats - -import ( - "net" - "net/http" - "strconv" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -type statsPrometheus struct { - connections *prometheus.GaugeVec - telegramConnections *prometheus.GaugeVec - traffic *prometheus.GaugeVec - crashes prometheus.Counter - replayAttacks prometheus.Counter - authenticationFailed prometheus.Counter - cloakedRequests prometheus.Counter -} - -func (s *statsPrometheus) IngressTraffic(traffic int) { - s.traffic.WithLabelValues("ingress").Add(float64(traffic)) -} - -func (s *statsPrometheus) EgressTraffic(traffic int) { - s.traffic.WithLabelValues("egress").Add(float64(traffic)) -} - -func (s *statsPrometheus) ClientConnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - s.changeConnections(connectionType, addr, 1.0) -} - -func (s *statsPrometheus) ClientDisconnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - s.changeConnections(connectionType, addr, -1.0) -} - -func (s *statsPrometheus) changeConnections(connectionType conntypes.ConnectionType, - addr *net.TCPAddr, - increment float64) { - labels := [...]string{ - "intermediate", - "ipv4", - } - - switch connectionType { - case conntypes.ConnectionTypeAbridged: - labels[0] = "abridged" - case conntypes.ConnectionTypeSecure: - labels[0] = "secured" - case conntypes.ConnectionTypeIntermediate: - labels[0] = "intermediate" - case conntypes.ConnectionTypeUnknown: - panic("unknown connection type") - } - - if addr.IP.To4() == nil { - labels[1] = "ipv6" - } - - s.connections.WithLabelValues(labels[:]...).Add(increment) -} - -func (s *statsPrometheus) TelegramConnected(dc conntypes.DC, addr *net.TCPAddr) { - s.changeTelegramConnections(dc, addr, 1.0) -} - -func (s *statsPrometheus) TelegramDisconnected(dc conntypes.DC, addr *net.TCPAddr) { - s.changeTelegramConnections(dc, addr, -1.0) -} - -func (s *statsPrometheus) changeTelegramConnections(dc conntypes.DC, addr *net.TCPAddr, increment float64) { - labels := [...]string{ - strconv.Itoa(int(dc)), - "ipv4", - } - - if addr.IP.To4() == nil { - labels[1] = "ipv6" - } - - s.telegramConnections.WithLabelValues(labels[:]...).Add(increment) -} - -func (s *statsPrometheus) Crash() { - s.crashes.Inc() -} - -func (s *statsPrometheus) ReplayDetected() { - s.replayAttacks.Inc() -} - -func (s *statsPrometheus) AuthenticationFailed() { - s.authenticationFailed.Inc() -} - -func (s *statsPrometheus) CloakedRequest() { - s.cloakedRequests.Inc() -} - -func newStatsPrometheus(mux *http.ServeMux) Interface { - registry := prometheus.NewPedanticRegistry() - - instance := &statsPrometheus{ - connections: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: config.C.StatsNamespace, - Name: "connections", - Help: "Current number of client connections to the proxy.", - }, []string{"type", "protocol"}), - telegramConnections: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: config.C.StatsNamespace, - Name: "telegram_connections", - Help: "Current number of telegram connections established by this proxy.", - }, []string{"dc", "protocol"}), - traffic: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: config.C.StatsNamespace, - Name: "traffic", - Help: "Traffic passed through the proxy in bytes.", - }, []string{"direction"}), - crashes: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: config.C.StatsNamespace, - Name: "crashes", - Help: "How many crashes happened.", - }), - replayAttacks: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: config.C.StatsNamespace, - Name: "replay_attacks", - Help: "How many replay attacks were prevented.", - }), - authenticationFailed: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: config.C.StatsNamespace, - Name: "authentication_failed", - Help: "How many authentication failed events we've seen.", - }), - cloakedRequests: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: config.C.StatsNamespace, - Name: "cloaked_requests", - Help: "How many requests were proxified during cloaking.", - }), - } - - registry.MustRegister(instance.connections) - registry.MustRegister(instance.telegramConnections) - registry.MustRegister(instance.traffic) - registry.MustRegister(instance.crashes) - registry.MustRegister(instance.replayAttacks) - registry.MustRegister(instance.authenticationFailed) - registry.MustRegister(instance.cloakedRequests) - - handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{}) - mux.Handle("/", handler) - - return instance -} diff --git a/stats/stats_statsd.go b/stats/stats_statsd.go deleted file mode 100644 index 26fce1c..0000000 --- a/stats/stats_statsd.go +++ /dev/null @@ -1,204 +0,0 @@ -package stats - -import ( - "fmt" - "net" - "strconv" - "strings" - "sync" - "time" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - statsd "github.com/smira/go-statsd" - "go.uber.org/zap" -) - -var ( - tagTrafficIngress = &statsStatsdTag{ - name: "ingress", - tag: statsd.StringTag("type", "ingress"), - } - tagTrafficEgress = &statsStatsdTag{ - name: "egress", - tag: statsd.StringTag("type", "egress"), - } - - tagConnectionTypeAbridged = &statsStatsdTag{ - name: "abridged", - tag: statsd.StringTag("type", "abridged"), - } - tagConnectionTypeIntermediate = &statsStatsdTag{ - name: "intermediate", - tag: statsd.StringTag("type", "intermediate"), - } - tagConnectionTypeSecured = &statsStatsdTag{ - name: "secured", - tag: statsd.StringTag("type", "secured"), - } - - tagConnectionProtocol4 = &statsStatsdTag{ - name: "ipv4", - tag: statsd.StringTag("protocol", "ipv4"), - } - tagConnectionProtocol6 = &statsStatsdTag{ - name: "ipv6", - tag: statsd.StringTag("protocol", "ipv6"), - } -) - -type statsStatsdTag struct { - tag statsd.Tag - name string -} - -type statsStatsdLogger struct { - log *zap.SugaredLogger -} - -func (s statsStatsdLogger) Printf(msg string, args ...interface{}) { - s.log.Debugw(fmt.Sprintf(msg, args...)) -} - -type statsStatsd struct { - seen map[string]struct{} - seenMutex sync.RWMutex - client *statsd.Client -} - -func (s *statsStatsd) IngressTraffic(traffic int) { - s.gauge("traffic", int64(traffic), tagTrafficIngress) -} - -func (s *statsStatsd) EgressTraffic(traffic int) { - s.gauge("traffic", int64(traffic), tagTrafficEgress) -} - -func (s *statsStatsd) ClientConnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - s.changeConnections(connectionType, addr, 1) -} - -func (s *statsStatsd) ClientDisconnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) { - s.changeConnections(connectionType, addr, -1) -} - -func (s *statsStatsd) changeConnections(connectionType conntypes.ConnectionType, addr *net.TCPAddr, increment int64) { - tags := make([]*statsStatsdTag, 0, 2) - - switch connectionType { - case conntypes.ConnectionTypeAbridged: - tags = append(tags, tagConnectionTypeAbridged) - case conntypes.ConnectionTypeIntermediate: - tags = append(tags, tagConnectionTypeIntermediate) - case conntypes.ConnectionTypeSecure: - tags = append(tags, tagConnectionTypeSecured) - case conntypes.ConnectionTypeUnknown: - panic("Unknown connection type") - } - - if addr.IP.To4() == nil { - tags = append(tags, tagConnectionProtocol6) - } else { - tags = append(tags, tagConnectionProtocol4) - } - - s.gauge("connections", increment, tags...) -} - -func (s *statsStatsd) TelegramConnected(dc conntypes.DC, addr *net.TCPAddr) { - s.changeTelegramConnections(dc, addr, 1) -} - -func (s *statsStatsd) TelegramDisconnected(dc conntypes.DC, addr *net.TCPAddr) { - s.changeTelegramConnections(dc, addr, -1) -} - -func (s *statsStatsd) changeTelegramConnections(dc conntypes.DC, addr *net.TCPAddr, increment int64) { - tags := []*statsStatsdTag{ - { - name: "dc" + strconv.Itoa(int(dc)), - tag: statsd.IntTag("dc", int(dc)), - }, - } - - if addr.IP.To4() == nil { - tags = append(tags, tagConnectionProtocol6) - } else { - tags = append(tags, tagConnectionProtocol4) - } - - s.gauge("telegram_connections", increment, tags...) -} - -func (s *statsStatsd) Crash() { - s.gauge("crashes", 1) -} - -func (s *statsStatsd) ReplayDetected() { - s.gauge("replay_attacks", 1) -} - -func (s *statsStatsd) AuthenticationFailed() { - s.gauge("authentication_failed", 1) -} - -func (s *statsStatsd) CloakedRequest() { - s.gauge("cloaked_requests", 1) -} - -func (s *statsStatsd) gauge(metric string, value int64, tags ...*statsStatsdTag) { - key, tagList := s.prepareVals(metric, tags) - s.initGauge(metric, key, tagList) - s.client.GaugeDelta(metric, value, tagList...) -} - -func (s *statsStatsd) prepareVals(metric string, tags []*statsStatsdTag) (string, []statsd.Tag) { - tagList := make([]statsd.Tag, len(tags)) - builder := strings.Builder{} - builder.WriteString(metric) - - for i, v := range tags { - builder.WriteRune('.') - builder.WriteString(v.name) - tagList[i] = v.tag - } - - return builder.String(), tagList -} - -func (s *statsStatsd) initGauge(metric, key string, tags []statsd.Tag) { - s.seenMutex.RLock() - if _, ok := s.seen[key]; ok { - s.seenMutex.RUnlock() - - return - } else { // nolint: golint,revive - s.seenMutex.RUnlock() - } - - s.seenMutex.Lock() - defer s.seenMutex.Unlock() - - if _, ok := s.seen[key]; !ok { - s.seen[key] = struct{}{} - s.client.Gauge(metric, 0, tags...) - } -} - -func newStatsStatsd() Interface { - prefix := strings.TrimSuffix(config.C.StatsNamespace, ".") + "." - logger := statsStatsdLogger{ - log: zap.S().Named("stats").Named("statsd"), - } - - return &statsStatsd{ - seen: make(map[string]struct{}), - client: statsd.NewClient(config.C.StatsdAddr.String(), - statsd.SendLoopCount(2), - statsd.ReconnectInterval(10*time.Second), - statsd.Logger(logger), - statsd.MetricPrefix(prefix), - statsd.TagStyle(config.C.StatsdTagsFormat), - ), - } -} diff --git a/telegram/api/addresses.go b/telegram/api/addresses.go deleted file mode 100644 index c7573e4..0000000 --- a/telegram/api/addresses.go +++ /dev/null @@ -1,109 +0,0 @@ -package api - -import ( - "bufio" - "fmt" - "net" - "regexp" - "strconv" - "strings" - - "github.com/9seconds/mtg/conntypes" -) - -const ( - addressesURLV4 = "https://core.telegram.org/getProxyConfig" // nolint: gas - addressesURLV6 = "https://core.telegram.org/getProxyConfigV6" // nolint: gas -) - -var addressesProxyForSplitter = regexp.MustCompile(`\s+`) - -func AddressesV4() (map[conntypes.DC][]string, conntypes.DC, error) { - return getAddresses(addressesURLV4) -} - -func AddressesV6() (map[conntypes.DC][]string, conntypes.DC, error) { - return getAddresses(addressesURLV6) -} - -func getAddresses(url string) (map[conntypes.DC][]string, conntypes.DC, error) { - resp, err := request(url) - if err != nil { - return nil, 0, fmt.Errorf("cannot get http response: %w", err) - } - - defer resp.Close() - - scanner := bufio.NewScanner(resp) - data := map[conntypes.DC][]string{} - defaultDC := conntypes.DCDefaultIdx - - for scanner.Scan() { - text := strings.TrimSpace(scanner.Text()) - - switch { - case strings.HasPrefix(text, "#"): - continue - case strings.HasPrefix(text, "proxy_for"): - addr, idx, err := addressesParseProxyFor(text) - if err != nil { - return nil, 0, fmt.Errorf("cannot parse 'proxy_for' section: %w", err) - } - - if addresses, ok := data[idx]; ok { - data[idx] = append(addresses, addr) - } else { - data[idx] = []string{addr} - } - case strings.HasPrefix(text, "default"): - idx, err := addressesParseDefault(text) - if err != nil { - return nil, 0, fmt.Errorf("cannot parse 'default' section: %w", err) - } - - defaultDC = idx - } - } - - err = scanner.Err() - if err != nil { - return nil, 0, fmt.Errorf("cannot parse http response: %w", err) - } - - return data, defaultDC, nil -} - -func addressesParseProxyFor(text string) (string, conntypes.DC, error) { - chunks := addressesProxyForSplitter.Split(text, 3) - if len(chunks) != 3 || chunks[0] != "proxy_for" { - return "", 0, fmt.Errorf("incorrect config %s", text) - } - - dc, err := strconv.ParseInt(chunks[1], 10, 16) - if err != nil { - return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err) - } - - addr := strings.TrimRight(chunks[2], ";") - if _, _, err = net.SplitHostPort(addr); err != nil { - return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err) - } - - return addr, conntypes.DC(dc), nil -} - -func addressesParseDefault(text string) (conntypes.DC, error) { - chunks := addressesProxyForSplitter.Split(text, 2) - if len(chunks) != 2 || chunks[0] != "default" { - return 0, fmt.Errorf("incorrect config '%s'", text) - } - - dcString := strings.TrimRight(chunks[1], ";") - - dc, err := strconv.ParseInt(dcString, 10, 16) - if err != nil { - return 0, fmt.Errorf("incorrect config '%s': %w", text, err) - } - - return conntypes.DC(dc), nil -} diff --git a/telegram/api/api.go b/telegram/api/api.go deleted file mode 100644 index 7cdef71..0000000 --- a/telegram/api/api.go +++ /dev/null @@ -1,44 +0,0 @@ -package api - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "net/http" - "time" -) - -const ( - apiUserAgent = "github.com/9seconds/mtg" - apiHTTPTimeout = 30 * time.Second -) - -var httpClient = http.Client{ - Timeout: apiHTTPTimeout, -} - -func request(url string) (io.ReadCloser, error) { - ctx, cancel := context.WithTimeout(context.Background(), apiHTTPTimeout) - defer cancel() - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - panic(err) - } - - req.Header.Set("Accept", "text/plan") - req.Header.Set("User-Agent", apiUserAgent) - - resp, err := httpClient.Do(req) - if err != nil { - if resp != nil { - io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck - resp.Body.Close() - } - - return nil, fmt.Errorf("cannot perform a request: %w", err) - } - - return resp.Body, err // nolint: wrapcheck -} diff --git a/telegram/api/secret.go b/telegram/api/secret.go deleted file mode 100644 index c5a1137..0000000 --- a/telegram/api/secret.go +++ /dev/null @@ -1,24 +0,0 @@ -package api - -import ( - "fmt" - "io/ioutil" -) - -const secretURL = "https://core.telegram.org/getProxySecret" // nolint: gas - -func Secret() ([]byte, error) { - resp, err := request(secretURL) - if err != nil { - return nil, fmt.Errorf("cannot access telegram server: %w", err) - } - - defer resp.Close() - - secret, err := ioutil.ReadAll(resp) - if err != nil { - return nil, fmt.Errorf("cannot read response: %w", err) - } - - return secret, nil -} diff --git a/telegram/base.go b/telegram/base.go deleted file mode 100644 index 4a6c383..0000000 --- a/telegram/base.go +++ /dev/null @@ -1,91 +0,0 @@ -package telegram - -import ( - "errors" - "math/rand" - "net" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/utils" - "github.com/9seconds/mtg/wrappers/stream" - "go.uber.org/zap" -) - -type baseTelegram struct { - dialer net.Dialer - logger *zap.SugaredLogger - - secret []byte - v4DefaultDC conntypes.DC - v6DefaultDC conntypes.DC - v4Addresses map[conntypes.DC][]string - v6Addresses map[conntypes.DC][]string -} - -func (b *baseTelegram) Secret() []byte { - return b.secret -} - -func (b *baseTelegram) dial(dc conntypes.DC, - protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { - for _, addr := range b.getAddresses(dc, protocol) { - conn, err := b.dialer.Dial("tcp", addr) - if err != nil { - b.logger.Infow("Cannot dial to Telegram", "address", addr, "error", err) - - continue - } - - if err := utils.InitTCP(conn, config.C.ProxyReadBuffer(), config.C.ProxyWriteBuffer()); err != nil { - b.logger.Infow("Cannot initialize TCP socket", "address", addr, "error", err) - - continue - } - - return stream.NewTelegramConn(dc, conn), nil - } - - return nil, errors.New("cannot dial to the chosen DC") -} - -func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.ConnectionProtocol) []string { - addresses := make([]string, 0, 2) - protos := []conntypes.ConnectionProtocol{ - conntypes.ConnectionProtocolIPv6, - conntypes.ConnectionProtocolIPv4, - } - - if config.C.PreferIP == config.PreferIPv4 { - protos[0], protos[1] = protos[1], protos[0] - } - - for _, proto := range protos { - switch { - case proto&protocol == 0: - case proto&conntypes.ConnectionProtocolIPv6 != 0: - addresses = append(addresses, b.chooseAddress(b.v6Addresses, dc, b.v6DefaultDC)) - case proto&conntypes.ConnectionProtocolIPv4 != 0: - addresses = append(addresses, b.chooseAddress(b.v4Addresses, dc, b.v4DefaultDC)) - } - } - - return addresses -} - -func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string, - dc, defaultDC conntypes.DC) string { - addrs, ok := addresses[dc] - if !ok { - addrs = addresses[defaultDC] - } - - switch { - case len(addrs) == 1: - return addrs[0] - case len(addrs) > 1: - return addrs[rand.Intn(len(addrs))] // nolint: gosec - } - - return "" -} diff --git a/telegram/direct.go b/telegram/direct.go deleted file mode 100644 index 5a7183c..0000000 --- a/telegram/direct.go +++ /dev/null @@ -1,41 +0,0 @@ -package telegram - -import "github.com/9seconds/mtg/conntypes" - -const ( - directV4DefaultIdx conntypes.DC = 1 - directV6DefaultIdx conntypes.DC = 1 -) - -var ( - directV4Addresses = map[conntypes.DC][]string{ - 0: {"149.154.175.50:443"}, - 1: {"149.154.167.51:443"}, - 2: {"149.154.175.100:443"}, - 3: {"149.154.167.91:443"}, - 4: {"149.154.171.5:443"}, - } - directV6Addresses = map[conntypes.DC][]string{ - 0: {"[2001:b28:f23d:f001::a]:443"}, - 1: {"[2001:67c:04e8:f002::a]:443"}, - 2: {"[2001:b28:f23d:f003::a]:443"}, - 3: {"[2001:67c:04e8:f004::a]:443"}, - 4: {"[2001:b28:f23f:f005::a]:443"}, - } -) - -type directTelegram struct { - baseTelegram -} - -func (d *directTelegram) Dial(dc conntypes.DC, - protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { - switch { - case dc < 0: - dc = -dc - case dc == 0: - dc = conntypes.DCDefaultIdx - } - - return d.baseTelegram.dial(dc-1, conntypes.ConnectionProtocolAny) -} diff --git a/telegram/init.go b/telegram/init.go deleted file mode 100644 index 72da84e..0000000 --- a/telegram/init.go +++ /dev/null @@ -1,48 +0,0 @@ -package telegram - -import ( - "net" - "sync" - "time" - - "go.uber.org/zap" -) - -const telegramDialTimeout = 10 * time.Second - -var ( - Direct Telegram - Middle Telegram - - initOnce sync.Once -) - -func Init() { - initOnce.Do(func() { - logger := zap.S().Named("telegram") - - Direct = &directTelegram{ - baseTelegram: baseTelegram{ - dialer: net.Dialer{Timeout: telegramDialTimeout}, - logger: logger.Named("direct"), - v4DefaultDC: directV4DefaultIdx, - v6DefaultDC: directV6DefaultIdx, - v4Addresses: directV4Addresses, - v6Addresses: directV6Addresses, - }, - } - - tg := &middleTelegram{ - baseTelegram: baseTelegram{ - dialer: net.Dialer{Timeout: telegramDialTimeout}, - logger: logger.Named("middle"), - }, - } - if err := tg.update(); err != nil { - panic(err) - } - go tg.backgroundUpdate() - - Middle = tg - }) -} diff --git a/telegram/interfaces.go b/telegram/interfaces.go deleted file mode 100644 index e419b8b..0000000 --- a/telegram/interfaces.go +++ /dev/null @@ -1,8 +0,0 @@ -package telegram - -import "github.com/9seconds/mtg/conntypes" - -type Telegram interface { - Dial(conntypes.DC, conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) - Secret() []byte -} diff --git a/telegram/middle.go b/telegram/middle.go deleted file mode 100644 index 3683f4d..0000000 --- a/telegram/middle.go +++ /dev/null @@ -1,75 +0,0 @@ -package telegram - -import ( - "fmt" - "sync" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/telegram/api" - "go.uber.org/zap" -) - -const middleTelegramBackgroundUpdateEvery = time.Hour - -type middleTelegram struct { - baseTelegram - - mutex sync.RWMutex -} - -func (m *middleTelegram) Secret() []byte { - m.mutex.RLock() - defer m.mutex.RUnlock() - - return m.baseTelegram.Secret() -} - -func (m *middleTelegram) update() error { - secret, err := api.Secret() - if err != nil { - return fmt.Errorf("cannot fetch secret: %w", err) - } - - v4Addresses, v4DefaultDC, err := api.AddressesV4() - if err != nil { - return fmt.Errorf("cannot fetch addresses for ipv4: %w", err) - } - - v6Addresses, v6DefaultDC, err := api.AddressesV6() - if err != nil { - return fmt.Errorf("cannot fetch addresses for ipv6: %w", err) - } - - m.mutex.Lock() - m.secret = secret - m.v4DefaultDC = v4DefaultDC - m.v6DefaultDC = v6DefaultDC - m.v4Addresses = v4Addresses - m.v6Addresses = v6Addresses - m.mutex.Unlock() - - return nil -} - -func (m *middleTelegram) backgroundUpdate() { - logger := zap.S().Named("telegram") - - for range time.Tick(middleTelegramBackgroundUpdateEvery) { - if err := m.update(); err != nil { - logger.Warnw("Cannot update Telegram proxies", "error", err) - } - } -} - -func (m *middleTelegram) Dial(dc conntypes.DC, - protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { - if dc == 0 { - dc = conntypes.DCDefaultIdx - } - - m.mutex.RLock() - defer m.mutex.RUnlock() - - return m.baseTelegram.dial(dc, protocol) -} diff --git a/tlstypes/client_hello.go b/tlstypes/client_hello.go deleted file mode 100644 index ffb6e87..0000000 --- a/tlstypes/client_hello.go +++ /dev/null @@ -1,86 +0,0 @@ -package tlstypes - -import ( - "bytes" - "crypto/hmac" - "crypto/sha256" - "fmt" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/utils" -) - -type ClientHello struct { - Handshake -} - -func (c ClientHello) Digest() []byte { - dirtyDigest := c.Random - c.Random = [32]byte{} - - rec := Record{ - Type: RecordTypeHandshake, - Version: Version10, - Data: &c, - } - - mac := hmac.New(sha256.New, config.C.Secret) - rec.WriteBytes(mac) - computedDigest := mac.Sum(nil) - - for i := range computedDigest { - computedDigest[i] ^= dirtyDigest[i] - } - - return computedDigest -} - -func ParseClientHello(raw []byte) (*ClientHello, error) { - rv := &ClientHello{} - - rv.Type = HandshakeType(raw[0]) - if rv.Type != HandshakeTypeClient { - return nil, fmt.Errorf("incorrect handshake type %v", rv.Type) - } - - raw = raw[1:] - sizeUint24 := utils.Uint24{} - copy(sizeUint24[:], utils.ReverseBytes(raw[:3])) - size := int(utils.FromUint24(sizeUint24)) - - raw = raw[3:] - if len(raw) != size { - return nil, fmt.Errorf("payload size mismatch (%d != %d)", len(raw), size) - } - - versionRaw := raw[:2] - - switch { - case bytes.Equal(versionRaw, Version13Bytes): - rv.Version = Version13 - case bytes.Equal(versionRaw, Version12Bytes): - rv.Version = Version12 - case bytes.Equal(versionRaw, Version11Bytes): - rv.Version = Version11 - case bytes.Equal(versionRaw, Version10Bytes): - rv.Version = Version10 - default: - return nil, fmt.Errorf("unknown protocol version %v", versionRaw) - } - - raw = raw[2:] - copy(rv.Random[:], raw[:32]) - raw = raw[32:] - - sessionIDLength := int(raw[0]) - raw = raw[1:] - rv.SessionID = make([]byte, sessionIDLength) - copy(rv.SessionID, raw) - raw = raw[sessionIDLength:] - - tail := make([]byte, len(raw)) - copy(tail, raw) - rv.Tail = RawBytes(tail) - - return rv, nil -} diff --git a/tlstypes/consts.go b/tlstypes/consts.go deleted file mode 100644 index 79d5a10..0000000 --- a/tlstypes/consts.go +++ /dev/null @@ -1,90 +0,0 @@ -package tlstypes - -import "io" - -type RecordType uint8 - -const ( - RecordTypeHandshake RecordType = 0x16 - RecordTypeApplicationData RecordType = 0x17 - RecordTypeChangeCipherSpec RecordType = 0x14 -) - -type HandshakeType uint8 - -const ( - HandshakeTypeClient HandshakeType = 0x01 - HandshakeTypeServer HandshakeType = 0x02 -) - -type CipherSuiteType uint8 - -const ( - CipherSuiteType_TLS_AES_128_GCM_SHA256 CipherSuiteType = iota // nolint: stylecheck,golint,revive - CipherSuiteType_TLS_AES_256_GCM_SHA384 // nolint: stylecheck,golint,revive - CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256 // nolint: stylecheck,golint,revive -) - -func (c CipherSuiteType) Bytes() []byte { - switch c { - case CipherSuiteType_TLS_AES_128_GCM_SHA256: - return CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes - case CipherSuiteType_TLS_AES_256_GCM_SHA384: - return CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes - case CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256: - return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes - } - - return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes -} - -type Version uint8 - -func (v Version) Bytes() []byte { - switch v { - case Version13: - return Version13Bytes - case Version12: - return Version12Bytes - case Version11: - return Version11Bytes - case Version10, VersionUnknown: - return Version10Bytes - } - - return Version10Bytes -} - -const ( - VersionUnknown Version = iota - Version10 - Version11 - Version12 - Version13 -) - -var ( - Version10Bytes = []byte{0x03, 0x01} - Version11Bytes = []byte{0x03, 0x02} - Version12Bytes = []byte{0x03, 0x03} - Version13Bytes = []byte{0x03, 0x04} - - CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes = []byte{0x13, 0x01} // nolint: stylecheck,golint,revive - CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes = []byte{0x13, 0x02} // nolint: stylecheck,golint,revive - CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes = []byte{0x13, 0x03} // nolint: stylecheck,golint,revive -) - -type Byter interface { - WriteBytes(io.Writer) - Len() int -} - -type RawBytes []byte - -func (r RawBytes) WriteBytes(writer io.Writer) { - writer.Write(r) // nolint: errcheck -} - -func (r RawBytes) Len() int { - return len(r) -} diff --git a/tlstypes/handshake.go b/tlstypes/handshake.go deleted file mode 100644 index 3775b45..0000000 --- a/tlstypes/handshake.go +++ /dev/null @@ -1,43 +0,0 @@ -package tlstypes - -import ( - "bytes" - "io" - - "github.com/9seconds/mtg/utils" -) - -type Handshake struct { - Type HandshakeType - Version Version - Random [32]byte - SessionID []byte - Tail Byter -} - -func (h *Handshake) WriteBytes(writer io.Writer) { - packetBuf := bytes.Buffer{} - - writer.Write([]byte{byte(h.Type)}) // nolint: errcheck - - packetBuf.Write(h.Version.Bytes()) - packetBuf.Write(h.Random[:]) - packetBuf.WriteByte(byte(len(h.SessionID))) - packetBuf.Write(h.SessionID) - h.Tail.WriteBytes(&packetBuf) - - sizeUint24 := utils.ToUint24(uint32(packetBuf.Len())) - sizeUint24Bytes := sizeUint24[:] - sizeUint24Bytes[0], sizeUint24Bytes[2] = sizeUint24Bytes[2], sizeUint24Bytes[0] - - writer.Write(sizeUint24Bytes) // nolint: errcheck - packetBuf.WriteTo(writer) // nolint: errcheck -} - -func (h *Handshake) Len() int { - buf := bytes.Buffer{} - - h.WriteBytes(&buf) - - return buf.Len() -} diff --git a/tlstypes/record.go b/tlstypes/record.go deleted file mode 100644 index 5dae77e..0000000 --- a/tlstypes/record.go +++ /dev/null @@ -1,84 +0,0 @@ -package tlstypes - -import ( - "bytes" - "encoding/binary" - "fmt" - "io" -) - -const recordMaxChunkSize = 16384 + 24 - -type Record struct { - Type RecordType - Version Version - Data Byter -} - -func (r Record) WriteBytes(writer io.Writer) { - writer.Write([]byte{byte(r.Type)}) // nolint: errcheck - writer.Write(r.Version.Bytes()) // nolint: errcheck - binary.Write(writer, binary.BigEndian, uint16(r.Data.Len())) // nolint: errcheck - r.Data.WriteBytes(writer) -} - -func (r Record) Len() int { - return 1 + 2 + 2 + r.Data.Len() -} - -func ReadRecord(reader io.Reader) (Record, error) { - buf := [2]byte{} - rec := Record{} - - if _, err := io.ReadFull(reader, buf[:1]); err != nil { - return rec, fmt.Errorf("cannot read record type: %w", err) - } - - rec.Type = RecordType(buf[0]) - - if _, err := io.ReadFull(reader, buf[:]); err != nil { - return rec, fmt.Errorf("cannot read version: %w", err) - } - - switch { - case bytes.Equal(buf[:], Version13Bytes): - rec.Version = Version13 - case bytes.Equal(buf[:], Version12Bytes): - rec.Version = Version12 - case bytes.Equal(buf[:], Version11Bytes): - rec.Version = Version11 - case bytes.Equal(buf[:], Version10Bytes): - rec.Version = Version10 - } - - if _, err := io.ReadFull(reader, buf[:]); err != nil { - return rec, fmt.Errorf("cannot read data length: %w", err) - } - - data := make([]byte, binary.BigEndian.Uint16(buf[:])) - if _, err := io.ReadFull(reader, data); err != nil { - return rec, fmt.Errorf("cannot read data: %w", err) - } - - rec.Data = RawBytes(data) - - return rec, nil -} - -func MakeRecords(raw []byte) (arr []Record) { - for len(raw) > 0 { - chunkSize := recordMaxChunkSize - if chunkSize > len(raw) { - chunkSize = len(raw) - } - - arr = append(arr, Record{ - Type: RecordTypeApplicationData, - Version: Version12, - Data: RawBytes(raw[:chunkSize]), - }) - raw = raw[chunkSize:] - } - - return -} diff --git a/tlstypes/server_hello.go b/tlstypes/server_hello.go deleted file mode 100644 index efd624c..0000000 --- a/tlstypes/server_hello.go +++ /dev/null @@ -1,97 +0,0 @@ -package tlstypes - -import ( - "bytes" - "crypto/hmac" - "crypto/rand" - "crypto/sha256" - "io" - mrand "math/rand" - - "github.com/9seconds/mtg/config" - "golang.org/x/crypto/curve25519" -) - -type ServerHello struct { - Handshake - - clientHello *ClientHello -} - -func (s ServerHello) WelcomePacket() []byte { - buf := &bytes.Buffer{} - - s.Random = [32]byte{} - rec := Record{ - Type: RecordTypeHandshake, - Version: Version12, - Data: &s, - } - rec.WriteBytes(buf) - - recChangeCipher := Record{ - Type: RecordTypeChangeCipherSpec, - Version: Version12, - Data: RawBytes([]byte{0x01}), - } - recChangeCipher.WriteBytes(buf) - - hostCert := make([]byte, 1024+mrand.Intn(3092)) // nolint: gosec - rand.Read(hostCert) // nolint: errcheck - - recData := Record{ - Type: RecordTypeApplicationData, - Version: Version12, - Data: RawBytes(hostCert), - } - recData.WriteBytes(buf) - - packet := buf.Bytes() - - mac := hmac.New(sha256.New, config.C.Secret) - mac.Write(s.clientHello.Random[:]) // nolint: errcheck - mac.Write(packet) // nolint: errcheck - copy(packet[11:], mac.Sum(nil)) - - return packet -} - -func NewServerHello(clientHello *ClientHello) *ServerHello { - rv := &ServerHello{ - clientHello: clientHello, - } - - rv.Type = HandshakeTypeServer - rv.Version = Version12 - rv.SessionID = make([]byte, len(clientHello.SessionID)) - copy(rv.SessionID, clientHello.SessionID) - - tail := bytes.NewBuffer(CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes) - tail.WriteByte(0x00) // no compression - makeTLSExtensions(tail) - rv.Tail = RawBytes(tail.Bytes()) - - return rv -} - -func makeTLSExtensions(buf io.Writer) { - buf.Write([]byte{ // nolint: errcheck - 0x00, 0x2e, // 46 bytes of data - 0x00, 0x33, // Extension - Key Share - 0x00, 0x24, // 36 bytes - 0x00, 0x1d, // x25519 curve - 0x00, 0x20, // 32 bytes of key - }) - - var scalar [32]byte - - rand.Read(scalar[:]) // nolint: errcheck - curve, _ := curve25519.X25519(scalar[:], curve25519.Basepoint) - buf.Write(curve) // nolint: errcheck - - buf.Write([]byte{ // nolint: errcheck - 0x00, 0x2b, // Extension - Supported Versions - 0x00, 0x02, // 2 bytes are following - 0x03, 0x04, // TLS 1.3 - }) -} diff --git a/utils/init_tcp.go b/utils/init_tcp.go deleted file mode 100644 index d491472..0000000 --- a/utils/init_tcp.go +++ /dev/null @@ -1,28 +0,0 @@ -package utils - -import ( - "fmt" - "net" -) - -func InitTCP(conn net.Conn, readBufferSize int, writeBufferSize int) error { - tcpConn := conn.(*net.TCPConn) - - if err := tcpConn.SetNoDelay(true); err != nil { - return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err) - } - - if err := tcpConn.SetReadBuffer(readBufferSize); err != nil { - return fmt.Errorf("cannot set read buffer size: %w", err) - } - - if err := tcpConn.SetWriteBuffer(writeBufferSize); err != nil { - return fmt.Errorf("cannot set write buffer size: %w", err) - } - - if err := tcpConn.SetKeepAlive(true); err != nil { - return fmt.Errorf("cannot enable keep-alive: %w", err) - } - - return nil -} diff --git a/utils/read_full.go b/utils/read_full.go deleted file mode 100644 index 1a86ab1..0000000 --- a/utils/read_full.go +++ /dev/null @@ -1,21 +0,0 @@ -package utils - -import "io" - -const readFullBufferSize = 1024 + 1 // +1 because telegram opreates with blocks mod 4 - -func ReadFull(src io.Reader) (rv []byte, err error) { - buf := make([]byte, readFullBufferSize) - n := readFullBufferSize - - for n == len(buf) { - n, err = src.Read(buf) - if err != nil { - return nil, err // nolint: wrapcheck - } - - rv = append(rv, buf[:n]...) - } - - return rv, nil -} diff --git a/utils/reverse_bytes.go b/utils/reverse_bytes.go deleted file mode 100644 index 87ad8f6..0000000 --- a/utils/reverse_bytes.go +++ /dev/null @@ -1,15 +0,0 @@ -package utils - -// ReverseBytes is a common slice reverser. -func ReverseBytes(data []byte) []byte { - dataLen := len(data) - rv := make([]byte, dataLen) - rv[dataLen/2] = data[dataLen/2] - - for i := dataLen/2 - 1; i >= 0; i-- { - opp := dataLen - i - 1 - rv[i], rv[opp] = data[opp], data[i] - } - - return rv -} diff --git a/utils/rlimit.go b/utils/rlimit.go deleted file mode 100644 index b474076..0000000 --- a/utils/rlimit.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !windows - -package utils - -import ( - "fmt" - - "golang.org/x/sys/unix" -) - -func SetLimits() error { - rLimit := unix.Rlimit{} - if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rLimit); err != nil { - return fmt.Errorf("cannot get rlimit: %w", err) - } - - rLimit.Cur = rLimit.Max - - if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit); err != nil { - return fmt.Errorf("cannot set rlimit: %w", err) - } - - return nil -} diff --git a/utils/rlimit_windows.go b/utils/rlimit_windows.go deleted file mode 100644 index 58bdf39..0000000 --- a/utils/rlimit_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build windows - -package utils - -func SetLimits() error { - return nil -} diff --git a/utils/signal_context.go b/utils/signal_context.go deleted file mode 100644 index 6d3951f..0000000 --- a/utils/signal_context.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build !windows - -package utils - -import ( - "context" - "os" - "os/signal" - "syscall" -) - -func GetSignalContext() context.Context { - ctx, cancel := context.WithCancel(context.Background()) - sigChan := make(chan os.Signal, 1) - - signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) - - go func() { - for range sigChan { - cancel() - } - }() - - return ctx -} diff --git a/utils/signal_context_windows.go b/utils/signal_context_windows.go deleted file mode 100644 index d18ce71..0000000 --- a/utils/signal_context_windows.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build windows - -package utils - -import ( - "context" - "os" - "os/signal" -) - -func GetSignalContext() context.Context { - ctx, cancel := context.WithCancel(context.Background()) - sigChan := make(chan os.Signal, 1) - - signal.Notify(sigChan, os.Interrupt) - go func() { - for range sigChan { - cancel() - } - }() - - return ctx -} diff --git a/utils/stream_cipher.go b/utils/stream_cipher.go deleted file mode 100644 index 44f0b27..0000000 --- a/utils/stream_cipher.go +++ /dev/null @@ -1,12 +0,0 @@ -package utils - -import ( - "crypto/aes" - "crypto/cipher" -) - -func MakeStreamCipher(key, iv []byte) cipher.Stream { - block, _ := aes.NewCipher(key) - - return cipher.NewCTR(block, iv) -} diff --git a/utils/uint24.go b/utils/uint24.go deleted file mode 100644 index 350f3d5..0000000 --- a/utils/uint24.go +++ /dev/null @@ -1,11 +0,0 @@ -package utils - -type Uint24 [3]byte - -func ToUint24(number uint32) Uint24 { - return Uint24{byte(number), byte(number >> 8), byte(number >> 16)} -} - -func FromUint24(number Uint24) uint32 { - return uint32(number[0]) + (uint32(number[1]) << 8) + (uint32(number[2]) << 16) -} diff --git a/wrappers/packet/mtproto_frame.go b/wrappers/packet/mtproto_frame.go deleted file mode 100644 index 805f361..0000000 --- a/wrappers/packet/mtproto_frame.go +++ /dev/null @@ -1,165 +0,0 @@ -package packet - -import ( - "bytes" - "crypto/aes" - "encoding/binary" - "fmt" - "hash/crc32" - "io" - "io/ioutil" - "net" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -const ( - mtprotoFrameMinMessageLength = 12 - mtprotoFrameMaxMessageLength = 16777216 -) - -var mtprotoFramePadding = []byte{0x04, 0x00, 0x00, 0x00} - -// MTProtoFrame is a wrapper which converts written data to the MTProtoFrame. -// The format of the frame: -// -// [ MSGLEN(4) | SEQNO(4) | MSG(...) | CRC32(4) | PADDING(4*x) ] -// -// MSGLEN is the length of the message + len of seqno and msglen. -// SEQNO is the number of frame in the receive/send sequence. If client -// sends a message with SeqNo 18, it has to receive message with SeqNo 18. -// MSG is the data which has to be written -// CRC32 is the CRC32 checksum of MSGLEN + SEQNO + MSG -// PADDING is custom padding schema to complete frame length to such that -// len(frame) % 16 == 0 -type wrapperMtprotoFrame struct { - parent conntypes.StreamReadWriteCloser - logger *zap.SugaredLogger - readSeqNo int32 - writeSeqNo int32 -} - -func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen, cyclop - buf := &bytes.Buffer{} - - sum := crc32.NewIEEE() - writer := io.MultiWriter(buf, sum) - - for { - buf.Reset() - sum.Reset() - - if _, err := io.CopyN(writer, w.parent, 4); err != nil { - return nil, fmt.Errorf("cannot read frame padding: %w", err) - } - - if !bytes.Equal(buf.Bytes(), mtprotoFramePadding) { - break - } - } - - messageLength := binary.LittleEndian.Uint32(buf.Bytes()) - w.logger.Debugw("Read MTProto frame", - "messageLength", messageLength, - "sequence_number", w.readSeqNo, - ) - - if messageLength%4 != 0 || messageLength < mtprotoFrameMinMessageLength || - messageLength > mtprotoFrameMaxMessageLength { - return nil, fmt.Errorf("incorrect frame message length %d", messageLength) - } - - buf.Reset() - - if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil { - return nil, fmt.Errorf("cannot read the message frame: %w", err) - } - - var seqNo int32 - - binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck - - if seqNo != w.readSeqNo { - return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo) - } - - data, _ := ioutil.ReadAll(buf) - buf.Reset() - // write to buf, not to writer. This is because we are going to fetch - // crc32 checksum. - if _, err := io.CopyN(buf, w.parent, 4); err != nil { - return nil, fmt.Errorf("cannot read checksum: %w", err) - } - - checksum := binary.LittleEndian.Uint32(buf.Bytes()) - if checksum != sum.Sum32() { - return nil, fmt.Errorf("CRC32 checksum mismatch. wait for %d, got %d", sum.Sum32(), checksum) - } - - w.logger.Debugw("Read MTProto frame", - "messageLength", messageLength, - "sequence_number", w.readSeqNo, - "dataLength", len(data), - "checksum", checksum, - ) - w.readSeqNo++ - - return data, nil -} - -func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error { - messageLength := 4 + 4 + len(p) + 4 - paddingLength := (aes.BlockSize - messageLength%aes.BlockSize) % aes.BlockSize - - buf := &bytes.Buffer{} - - binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck - binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck - buf.Write(p) - - checksum := crc32.ChecksumIEEE(buf.Bytes()) - binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck - buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) - - w.logger.Debugw("Write MTProto frame", - "length", len(p), - "sequence_number", w.writeSeqNo, - "crc32", checksum, - "frame_length", buf.Len(), - ) - w.writeSeqNo++ - - _, err := w.parent.Write(buf.Bytes()) - - return err // nolint: wrapcheck -} - -func (w *wrapperMtprotoFrame) Close() error { - return w.parent.Close() -} - -func (w *wrapperMtprotoFrame) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperMtprotoFrame) Logger() *zap.SugaredLogger { - return w.logger -} - -func (w *wrapperMtprotoFrame) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperMtprotoFrame) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func NewMtprotoFrame(parent conntypes.StreamReadWriteCloser, seqNo int32) conntypes.PacketReadWriteCloser { - return &wrapperMtprotoFrame{ - parent: parent, - logger: parent.Logger().Named("mtproto-frame"), - readSeqNo: seqNo, - writeSeqNo: seqNo, - } -} diff --git a/wrappers/packetack/client_abridged.go b/wrappers/packetack/client_abridged.go deleted file mode 100644 index 2952de0..0000000 --- a/wrappers/packetack/client_abridged.go +++ /dev/null @@ -1,130 +0,0 @@ -package packetack - -import ( - "bytes" - "fmt" - "io" - "net" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/utils" - "go.uber.org/zap" -) - -const ( - clientAbridgedSmallPacketLength = 0x7f - clientAbridgedQuickAckLength = 0x80 - clientAbridgedLargePacketLength = 16777216 // 256 ^ 3 -) - -type wrapperClientAbridged struct { - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperClientAbridged) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { - buf := bytes.Buffer{} - - buf.Grow(1) - - if _, err := io.CopyN(&buf, w.parent, 1); err != nil { - return nil, fmt.Errorf("cannot read message length: %w", err) - } - - msgLength := uint32(buf.Bytes()[0]) - buf.Reset() - - if msgLength >= clientAbridgedQuickAckLength { - acks.Quick = true - msgLength -= clientAbridgedQuickAckLength - } - - if msgLength == clientAbridgedSmallPacketLength { - buf.Grow(3) - - if _, err := io.CopyN(&buf, w.parent, 3); err != nil { - return nil, fmt.Errorf("cannot read correct message length: %w", err) - } - - number := utils.Uint24{} - copy(number[:], buf.Bytes()) - msgLength = utils.FromUint24(number) - } - - msgLength *= 4 - - buf.Reset() - buf.Grow(int(msgLength)) - - if _, err := io.CopyN(&buf, w.parent, int64(msgLength)); err != nil { - return nil, fmt.Errorf("cannot read message: %w", err) - } - - return conntypes.Packet(buf.Bytes()), nil -} - -func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error { - if len(packet)%4 != 0 { - return fmt.Errorf("incorrect packet length %d", len(packet)) - } - - if acks.Simple { - if _, err := w.parent.Write(utils.ReverseBytes(packet)); err != nil { - return fmt.Errorf("cannot send a simpleacked packet: %w", err) - } - - return nil - } - - packetLength := len(packet) / 4 - - switch { - case packetLength < clientAbridgedSmallPacketLength: - data := append([]byte{byte(packetLength)}, packet...) - if _, err := w.parent.Write(data); err != nil { - return fmt.Errorf("cannot send small packet: %w", err) - } - - return nil - case packetLength < clientAbridgedLargePacketLength: - length24 := utils.ToUint24(uint32(packetLength)) - buf := bytes.Buffer{} - - buf.WriteByte(byte(clientAbridgedSmallPacketLength)) - buf.Write(length24[:]) - buf.Write(packet) - - if _, err := w.parent.Write(buf.Bytes()); err != nil { - return fmt.Errorf("cannot send large packet: %w", err) - } - - return nil - } - - return fmt.Errorf("packet is too big: %d", len(packet)) -} - -func (w *wrapperClientAbridged) Close() error { - return w.parent.Close() -} - -func (w *wrapperClientAbridged) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperClientAbridged) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperClientAbridged) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperClientAbridged) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("client-abridged") -} - -func NewClientAbridged(parent conntypes.StreamReadWriteCloser) conntypes.PacketAckFullReadWriteCloser { - return &wrapperClientAbridged{ - parent: parent, - } -} diff --git a/wrappers/packetack/client_intermediate.go b/wrappers/packetack/client_intermediate.go deleted file mode 100644 index ac60fb4..0000000 --- a/wrappers/packetack/client_intermediate.go +++ /dev/null @@ -1,89 +0,0 @@ -package packetack - -import ( - "bytes" - "encoding/binary" - "fmt" - "io" - "net" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -const clientIntermediateQuickAckLength = 0x80000000 - -type wrapperClientIntermediate struct { - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperClientIntermediate) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { - buf := bytes.Buffer{} - - buf.Grow(4) - - if _, err := io.CopyN(&buf, w.parent, 4); err != nil { - return nil, fmt.Errorf("cannot read message length: %w", err) - } - - length := binary.LittleEndian.Uint32(buf.Bytes()) - - if length > clientIntermediateQuickAckLength { - acks.Quick = true - length -= clientIntermediateQuickAckLength - } - - buf.Reset() - buf.Grow(int(length)) - - if _, err := io.CopyN(&buf, w.parent, int64(length)); err != nil { - return nil, fmt.Errorf("cannot read the message: %w", err) - } - - return buf.Bytes(), nil -} - -func (w *wrapperClientIntermediate) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error { - if acks.Simple { - if _, err := w.parent.Write(packet); err != nil { - return fmt.Errorf("cannot send simpleacked packet: %w", err) - } - - return nil - } - - length := [4]byte{} - binary.LittleEndian.PutUint32(length[:], uint32(len(packet))) - - if _, err := w.parent.Write(append(length[:], packet...)); err != nil { - return fmt.Errorf("cannot send packet: %w", err) - } - - return nil -} - -func (w *wrapperClientIntermediate) Close() error { - return w.parent.Close() -} - -func (w *wrapperClientIntermediate) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperClientIntermediate) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperClientIntermediate) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperClientIntermediate) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("client-intermediate") -} - -func NewClientIntermediate(parent conntypes.StreamReadWriteCloser) conntypes.PacketAckFullReadWriteCloser { - return &wrapperClientIntermediate{ - parent: parent, - } -} diff --git a/wrappers/packetack/client_intermediate_secure.go b/wrappers/packetack/client_intermediate_secure.go deleted file mode 100644 index 1151a37..0000000 --- a/wrappers/packetack/client_intermediate_secure.go +++ /dev/null @@ -1,63 +0,0 @@ -package packetack - -import ( - "bytes" - "encoding/binary" - "fmt" - "math/rand" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type wrapperClientIntermediateSecure struct { - wrapperClientIntermediate -} - -func (w *wrapperClientIntermediateSecure) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { - data, err := w.wrapperClientIntermediate.Read(acks) - if err != nil { - return nil, err - } - - length := len(data) - (len(data) % 4) - - return data[:length], nil -} - -func (w *wrapperClientIntermediateSecure) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error { - if acks.Simple { - if _, err := w.parent.Write(packet); err != nil { - return fmt.Errorf("cannot send simpleacked packet: %w", err) - } - - return nil - } - - buf := &bytes.Buffer{} - paddingLength := rand.Intn(4) // nolint: gosec - - buf.Grow(4 + len(packet) + paddingLength) - - binary.Write(buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck - buf.Write(packet) - buf.Write(make([]byte, paddingLength)) - - if _, err := w.parent.Write(buf.Bytes()); err != nil { - return fmt.Errorf("cannot send packet: %w", err) - } - - return nil -} - -func (w *wrapperClientIntermediateSecure) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("client-intermediate-secure") -} - -func NewClientIntermediateSecure(parent conntypes.StreamReadWriteCloser) conntypes.PacketAckFullReadWriteCloser { - return &wrapperClientIntermediateSecure{ - wrapperClientIntermediate: wrapperClientIntermediate{ - parent: parent, - }, - } -} diff --git a/wrappers/packetack/proxy.go b/wrappers/packetack/proxy.go deleted file mode 100644 index facbaa4..0000000 --- a/wrappers/packetack/proxy.go +++ /dev/null @@ -1,108 +0,0 @@ -package packetack - -import ( - "bytes" - "encoding/binary" - "fmt" - "net" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/hub" - "github.com/9seconds/mtg/mtproto/rpc" - "github.com/9seconds/mtg/protocol" -) - -type wrapperProxy struct { - request *protocol.TelegramRequest - proxy *hub.ProxyConn - clientIPPort []byte - ourIPPort []byte - flags rpc.ProxyRequestFlags -} - -func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error { - buf := bytes.Buffer{} - flags := w.flags - - if acks.Quick { - flags |= rpc.ProxyRequestFlagsQuickAck - } - - if bytes.HasPrefix(packet, rpc.ProxyRequestFlagsEncryptedPrefix[:]) { - flags |= rpc.ProxyRequestFlagsEncrypted - } - - buf.Write(rpc.TagProxyRequest) - buf.Write(flags.Bytes()) - buf.Write(w.request.ConnID[:]) - buf.Write(w.clientIPPort) - buf.Write(w.ourIPPort) - buf.Write(rpc.ProxyRequestExtraSize) - buf.Write(rpc.ProxyRequestProxyTag) - buf.WriteByte(byte(len(config.C.AdTag))) - buf.Write(config.C.AdTag) - buf.Write(make([]byte, (4-buf.Len()%4)%4)) - buf.Grow(len(packet)) - buf.Write(packet) - - return w.proxy.Write(buf.Bytes()) -} - -func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { - resp, err := w.proxy.Read() - if err != nil { - return nil, fmt.Errorf("cannot read a response: %w", err) - } - - if resp.Type == rpc.ProxyResponseTypeSimpleAck { - acks.Simple = true - } - - return resp.Payload, nil -} - -func (w *wrapperProxy) Close() error { - w.proxy.Close() - - return nil -} - -func NewProxy(request *protocol.TelegramRequest) (conntypes.PacketAckReadWriteCloser, error) { - flags := rpc.ProxyRequestFlagsHasAdTag | rpc.ProxyRequestFlagsMagic | rpc.ProxyRequestFlagsExtMode2 - - switch request.ClientProtocol.ConnectionType() { - case conntypes.ConnectionTypeAbridged: - flags |= rpc.ProxyRequestFlagsAbdridged - case conntypes.ConnectionTypeIntermediate: - flags |= rpc.ProxyRequestFlagsIntermediate - case conntypes.ConnectionTypeSecure: - flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad - case conntypes.ConnectionTypeUnknown: - panic("unknown connection type") - } - - proxy, err := hub.Hub.Register(request) - if err != nil { - return nil, fmt.Errorf("cannot make a new proxy wrapper: %w", err) - } - - return &wrapperProxy{ - flags: flags, - request: request, - proxy: proxy, - clientIPPort: proxyGetIPPort(request.ClientConn.RemoteAddr()), - ourIPPort: proxyGetIPPort(request.ClientConn.LocalAddr()), - }, nil -} - -func proxyGetIPPort(addr *net.TCPAddr) []byte { - rv := [16 + 4]byte{} - port := [4]byte{} - - copy(rv[:16], addr.IP.To16()) - binary.LittleEndian.PutUint32(port[:], uint32(addr.Port)) - copy(rv[16:], port[:]) - - return rv[:] -} diff --git a/wrappers/rwc/ping.go b/wrappers/rwc/ping.go deleted file mode 100644 index 548bef8..0000000 --- a/wrappers/rwc/ping.go +++ /dev/null @@ -1,48 +0,0 @@ -package rwc - -import ( - "context" - "io" -) - -type wrapperPing struct { - parent io.ReadWriteCloser - ctx context.Context - channelPing chan<- struct{} -} - -func (w *wrapperPing) Read(p []byte) (int, error) { - n, err := w.parent.Read(p) - if err == nil { - select { - case <-w.ctx.Done(): - case w.channelPing <- struct{}{}: - } - } - - return n, err // nolint: wrapcheck -} - -func (w *wrapperPing) Write(p []byte) (int, error) { - n, err := w.parent.Write(p) - if err == nil { - select { - case <-w.ctx.Done(): - case w.channelPing <- struct{}{}: - } - } - - return n, err // nolint: wrapcheck -} - -func (w *wrapperPing) Close() error { - return w.parent.Close() -} - -func NewPing(ctx context.Context, parent io.ReadWriteCloser, channelPing chan<- struct{}) io.ReadWriteCloser { - return &wrapperPing{ - parent: parent, - ctx: ctx, - channelPing: channelPing, - } -} diff --git a/wrappers/stream/base.go b/wrappers/stream/base.go deleted file mode 100644 index 0fd50ca..0000000 --- a/wrappers/stream/base.go +++ /dev/null @@ -1,21 +0,0 @@ -package stream - -import ( - "net" - - "github.com/9seconds/mtg/conntypes" -) - -func NewClientConn(parent net.Conn, connID conntypes.ConnID) conntypes.StreamReadWriteCloser { - conn := newConn(parent, connID, connPurposeClient) - conn = NewTrafficStats(conn) - - return conn -} - -func NewTelegramConn(dc conntypes.DC, parent net.Conn) conntypes.StreamReadWriteCloser { - conn := newConn(parent, conntypes.ConnID{}, connPurposeTelegram) - conn = NewTelegramStats(dc, conn) - - return conn -} diff --git a/wrappers/stream/blockcipher.go b/wrappers/stream/blockcipher.go deleted file mode 100644 index 6503e4f..0000000 --- a/wrappers/stream/blockcipher.go +++ /dev/null @@ -1,96 +0,0 @@ -package stream - -import ( - "crypto/aes" - "crypto/cipher" - "fmt" - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/utils" - "go.uber.org/zap" -) - -type wrapperBlockCipher struct { - bufferedReader - - parent conntypes.StreamReadWriteCloser - encryptor cipher.BlockMode - decryptor cipher.BlockMode -} - -func (w *wrapperBlockCipher) Write(p []byte) (int, error) { - encrypted, err := w.encrypt(p) - if err != nil { - return 0, err - } - - return w.parent.Write(encrypted) -} - -func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - encrypted, err := w.encrypt(p) - if err != nil { - return 0, err - } - - return w.parent.WriteTimeout(encrypted, timeout) -} - -func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) { - if len(p)%aes.BlockSize > 0 { - return nil, fmt.Errorf("incorrect block size %d", len(p)) - } - - encrypted := make([]byte, len(p)) - w.encryptor.CryptBlocks(encrypted, p) - - return encrypted, nil -} - -func (w *wrapperBlockCipher) Close() error { - return w.parent.Close() -} - -func (w *wrapperBlockCipher) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperBlockCipher) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("block-cipher") -} - -func (w *wrapperBlockCipher) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperBlockCipher) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func newBlockCipher(parent conntypes.StreamReadWriteCloser, - encryptor, decryptor cipher.BlockMode) conntypes.StreamReadWriteCloser { - cipher := &wrapperBlockCipher{ - parent: parent, - encryptor: encryptor, - decryptor: decryptor, - } - - cipher.readFunc = func() ([]byte, error) { - var currentBuffer []byte - for len(currentBuffer) == 0 || len(currentBuffer)%aes.BlockSize != 0 { - rv, err := utils.ReadFull(cipher.parent) - if err != nil { - return nil, fmt.Errorf("cannot read data: %w", err) - } - - currentBuffer = append(currentBuffer, rv...) - } - cipher.decryptor.CryptBlocks(currentBuffer, currentBuffer) - - return currentBuffer, nil - } - - return cipher -} diff --git a/wrappers/stream/buffered_reader.go b/wrappers/stream/buffered_reader.go deleted file mode 100644 index 6a551f7..0000000 --- a/wrappers/stream/buffered_reader.go +++ /dev/null @@ -1,44 +0,0 @@ -package stream - -import ( - "bytes" - "time" -) - -type bufferedReaderReadFunc func() ([]byte, error) - -type bufferedReader struct { - buf bytes.Buffer - readFunc bufferedReaderReadFunc -} - -func (b *bufferedReader) Read(p []byte) (int, error) { - if b.buf.Len() > 0 { - return b.flush(p) - } - - res, err := b.readFunc() - if err != nil { - return 0, err - } - - b.buf.Write(res) - - return b.flush(p) -} - -func (b *bufferedReader) ReadTimeout(p []byte, _ time.Duration) (int, error) { - return b.Read(p) -} - -func (b *bufferedReader) flush(p []byte) (int, error) { - if b.buf.Len() > len(p) { - return b.buf.Read(p) - } - - sizeToReturn := b.buf.Len() - copy(p, b.buf.Bytes()) - b.buf.Reset() - - return sizeToReturn, nil -} diff --git a/wrappers/stream/conn.go b/wrappers/stream/conn.go deleted file mode 100644 index d55c55c..0000000 --- a/wrappers/stream/conn.go +++ /dev/null @@ -1,123 +0,0 @@ -package stream - -import ( - "fmt" - "net" - "time" - - "github.com/9seconds/mtg/config" - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type connPurpose uint8 - -const ( - connPurposeClient connPurpose = 1 << iota - connPurposeTelegram -) - -type wrapperConn struct { - parent net.Conn - connID conntypes.ConnID - logger *zap.SugaredLogger - localAddr *net.TCPAddr - remoteAddr *net.TCPAddr -} - -func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - if err := w.parent.SetWriteDeadline(time.Now().Add(timeout)); err != nil { - w.Close() - - return 0, fmt.Errorf("cannot set write deadline to the socket: %w", err) - } - - return w.Write(p) -} - -func (w *wrapperConn) Write(p []byte) (int, error) { - n, err := w.parent.Write(p) - w.logger.Debugw("write to stream", "bytes", n, "error", err) - - if err != nil { - w.Close() - } - - return n, err // nolint: wrapcheck -} - -func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - if err := w.parent.SetReadDeadline(time.Now().Add(timeout)); err != nil { - w.Close() - - return 0, fmt.Errorf("cannot set read deadline to the socket: %w", err) - } - - return w.Read(p) -} - -func (w *wrapperConn) Read(p []byte) (int, error) { - n, err := w.parent.Read(p) - w.logger.Debugw("Read from stream", "bytes", n, "error", err) - - if err != nil { - w.Close() - } - - return n, err // nolint: wrapcheck -} - -func (w *wrapperConn) Close() error { - w.logger.Debugw("Close connection") - - return w.parent.Close() -} - -func (w *wrapperConn) Conn() net.Conn { - return w.parent -} - -func (w *wrapperConn) Logger() *zap.SugaredLogger { - return w.logger -} - -func (w *wrapperConn) LocalAddr() *net.TCPAddr { - return w.localAddr -} - -func (w *wrapperConn) RemoteAddr() *net.TCPAddr { - return w.remoteAddr -} - -func newConn(parent net.Conn, - connID conntypes.ConnID, - purpose connPurpose) conntypes.StreamReadWriteCloser { - localAddr := *parent.LocalAddr().(*net.TCPAddr) - - if parent.RemoteAddr().(*net.TCPAddr).IP.To4() != nil { - if config.C.PublicIPv4.IP != nil { - localAddr.IP = config.C.PublicIPv4.IP - } - } else if config.C.PublicIPv6.IP != nil { - localAddr.IP = config.C.PublicIPv6.IP - } - - logger := zap.S().With( - "local_address", localAddr, - "remote_address", parent.RemoteAddr(), - ).Named("conn") - - if purpose == connPurposeClient { - logger = logger.Named("client").With("connection_id", connID.String()) - } else { - logger = logger.Named("telegram") - } - - return &wrapperConn{ - parent: parent, - connID: connID, - logger: logger, - remoteAddr: parent.RemoteAddr().(*net.TCPAddr), - localAddr: &localAddr, - } -} diff --git a/wrappers/stream/ctx.go b/wrappers/stream/ctx.go deleted file mode 100644 index 86e7359..0000000 --- a/wrappers/stream/ctx.go +++ /dev/null @@ -1,93 +0,0 @@ -package stream - -import ( - "context" - "fmt" - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type wrapperCtx struct { - parent conntypes.StreamReadWriteCloser - ctx context.Context - cancel context.CancelFunc -} - -func (w *wrapperCtx) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - select { - case <-w.ctx.Done(): - w.Close() - - return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) - default: - return w.parent.WriteTimeout(p, timeout) - } -} - -func (w *wrapperCtx) Write(p []byte) (int, error) { - select { - case <-w.ctx.Done(): - w.Close() - - return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) - default: - return w.parent.Write(p) - } -} - -func (w *wrapperCtx) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - select { - case <-w.ctx.Done(): - w.Close() - - return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) - default: - return w.parent.ReadTimeout(p, timeout) - } -} - -func (w *wrapperCtx) Read(p []byte) (int, error) { - select { - case <-w.ctx.Done(): - w.Close() - - return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) - default: - return w.parent.Read(p) - } -} - -func (w *wrapperCtx) Close() error { - w.cancel() - - return w.parent.Close() -} - -func (w *wrapperCtx) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperCtx) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("ctx") -} - -func (w *wrapperCtx) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperCtx) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func NewCtx(ctx context.Context, - cancel context.CancelFunc, - parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { - return &wrapperCtx{ - parent: parent, - ctx: ctx, - cancel: cancel, - } -} diff --git a/wrappers/stream/faketls.go b/wrappers/stream/faketls.go deleted file mode 100644 index 17a1fe6..0000000 --- a/wrappers/stream/faketls.go +++ /dev/null @@ -1,107 +0,0 @@ -package stream - -import ( - "bytes" - "errors" - "fmt" - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/tlstypes" - "go.uber.org/zap" -) - -type wrapperFakeTLS struct { - bufferedReader - - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperFakeTLS) Write(p []byte) (int, error) { - return w.write(p, func(b []byte) (int, error) { - return w.parent.Write(b) - }) -} - -func (w *wrapperFakeTLS) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - startTime := time.Now() - - return w.write(p, func(b []byte) (int, error) { - elapsed := time.Since(startTime) - if elapsed > timeout { - return w.parent.WriteTimeout(b, timeout-elapsed) - } - - return 0, errors.New("timeout") - }) -} - -func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) { - sum := 0 - buf := bytes.Buffer{} - - for _, v := range tlstypes.MakeRecords(p) { - buf.Reset() - v.WriteBytes(&buf) - - _, err := writeFunc(buf.Bytes()) - if err != nil { - return sum, err - } - - sum += v.Data.Len() - } - - return sum, nil -} - -func (w *wrapperFakeTLS) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperFakeTLS) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("faketls") -} - -func (w *wrapperFakeTLS) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperFakeTLS) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperFakeTLS) Close() error { - return w.parent.Close() -} - -func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { - faketls := &wrapperFakeTLS{ - parent: socket, - } - - faketls.readFunc = func() ([]byte, error) { - for { - rec, err := tlstypes.ReadRecord(faketls.parent) - if err != nil { - return nil, err // nolint: wrapcheck - } - - switch rec.Type { - case tlstypes.RecordTypeChangeCipherSpec: - case tlstypes.RecordTypeApplicationData: - buf := &bytes.Buffer{} - rec.Data.WriteBytes(buf) - - return buf.Bytes(), nil - case tlstypes.RecordTypeHandshake: - return nil, errors.New("unsupported record type handshake") - default: - return nil, fmt.Errorf("unsupported record type %v", rec.Type) - } - } - } - - return faketls -} diff --git a/wrappers/stream/mtproto_cipher.go b/wrappers/stream/mtproto_cipher.go deleted file mode 100644 index 5a59f7c..0000000 --- a/wrappers/stream/mtproto_cipher.go +++ /dev/null @@ -1,117 +0,0 @@ -package stream - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/md5" - "crypto/sha1" - "encoding/binary" - "net" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/mtproto/rpc" - "github.com/9seconds/mtg/utils" -) - -type mtprotoCipherPurpose uint8 - -const ( - mtprotoCipherPurposeClient mtprotoCipherPurpose = iota - mtprotoCipherPurposeServer -) - -var mtprotoEmptyIP = [4]byte{0x00, 0x00, 0x00, 0x00} - -func NewMiddleProxyCipher(parent conntypes.StreamReadWriteCloser, - req *rpc.NonceRequest, - resp *rpc.NonceResponse, - secret []byte) conntypes.StreamReadWriteCloser { - localAddr := parent.LocalAddr() - remoteAddr := parent.RemoteAddr() - - encKey, encIV := mtprotoDeriveKeys(mtprotoCipherPurposeClient, - req, - resp, - localAddr, - remoteAddr, - secret) - decKey, decIV := mtprotoDeriveKeys(mtprotoCipherPurposeServer, - req, - resp, - localAddr, - remoteAddr, - secret) - - enc, _ := mtprotoMakeEncrypterDecrypter(encKey, encIV) - _, dec := mtprotoMakeEncrypterDecrypter(decKey, decIV) - - return newBlockCipher(parent, enc, dec) -} - -func mtprotoDeriveKeys(purpose mtprotoCipherPurpose, - req *rpc.NonceRequest, - resp *rpc.NonceResponse, - client, remote *net.TCPAddr, - secret []byte) ([]byte, []byte) { - message := bytes.Buffer{} - - message.Write(resp.Nonce) - message.Write(req.Nonce) - message.Write(req.CryptoTS) - - clientIPv4 := mtprotoEmptyIP[:] - serverIPv4 := mtprotoEmptyIP[:] - - if client.IP.To4() != nil { - clientIPv4 = utils.ReverseBytes(client.IP.To4()) - serverIPv4 = utils.ReverseBytes(remote.IP.To4()) - } - - message.Write(serverIPv4) - - var port [2]byte - - binary.LittleEndian.PutUint16(port[:], uint16(client.Port)) - message.Write(port[:]) - - switch purpose { - case mtprotoCipherPurposeClient: - message.WriteString("CLIENT") - case mtprotoCipherPurposeServer: - message.WriteString("SERVER") - default: - panic("Unexpected cipher purpose") - } - - message.Write(clientIPv4) - binary.LittleEndian.PutUint16(port[:], uint16(remote.Port)) - message.Write(port[:]) - message.Write(secret) - message.Write(resp.Nonce) - - if client.IP.To4() == nil { - message.Write(client.IP.To16()) - message.Write(remote.IP.To16()) - } - - message.Write(req.Nonce) - - data := message.Bytes() - md5sum := md5.Sum(data[1:]) // nolint: gas - sha1sum := sha1.Sum(data) // nolint: gosec - - key := append(md5sum[:12], sha1sum[:]...) - iv := md5.Sum(data[2:]) // nolint: gas - - return key, iv[:] -} - -func mtprotoMakeEncrypterDecrypter(key, iv []byte) (cipher.BlockMode, cipher.BlockMode) { - block, err := aes.NewCipher(key) - if err != nil { - panic(err) - } - - return cipher.NewCBCEncrypter(block, iv), cipher.NewCBCDecrypter(block, iv) -} diff --git a/wrappers/stream/obfuscated2.go b/wrappers/stream/obfuscated2.go deleted file mode 100644 index da2199a..0000000 --- a/wrappers/stream/obfuscated2.go +++ /dev/null @@ -1,93 +0,0 @@ -package stream - -import ( - "bytes" - "crypto/cipher" - "fmt" - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type wrapperObfuscated2 struct { - encryptor cipher.Stream - decryptor cipher.Stream - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperObfuscated2) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - n, err := w.parent.ReadTimeout(p, timeout) - if err != nil { - return 0, fmt.Errorf("cannot read stream ciphered data: %w", err) - } - - w.decryptor.XORKeyStream(p, p[:n]) - - return n, nil -} - -func (w *wrapperObfuscated2) Read(p []byte) (int, error) { - n, err := w.parent.Read(p) - if err != nil { - return n, err // nolint: wrapcheck - } - - w.decryptor.XORKeyStream(p, p[:n]) - - return n, nil -} - -func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - buffer := bytes.Buffer{} - - buffer.Write(p) - - buf := buffer.Bytes() - - w.encryptor.XORKeyStream(buf, buf) - - return w.parent.WriteTimeout(buf, timeout) -} - -func (w *wrapperObfuscated2) Write(p []byte) (int, error) { - buffer := bytes.Buffer{} - - buffer.Write(p) - - buf := buffer.Bytes() - - w.encryptor.XORKeyStream(buf, buf) - - return w.parent.Write(buf) -} - -func (w *wrapperObfuscated2) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperObfuscated2) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("obfuscated2") -} - -func (w *wrapperObfuscated2) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperObfuscated2) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperObfuscated2) Close() error { - return w.parent.Close() -} - -func NewObfuscated2(socket conntypes.StreamReadWriteCloser, - encryptor, decryptor cipher.Stream) conntypes.StreamReadWriteCloser { - return &wrapperObfuscated2{ - parent: socket, - encryptor: encryptor, - decryptor: decryptor, - } -} diff --git a/wrappers/stream/rewind.go b/wrappers/stream/rewind.go deleted file mode 100644 index d8d7425..0000000 --- a/wrappers/stream/rewind.go +++ /dev/null @@ -1,83 +0,0 @@ -package stream - -import ( - "bytes" - "io" - "net" - "sync" - "time" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -type ReadWriteCloseRewinder interface { - conntypes.StreamReadWriteCloser - Rewind() -} - -type wrapperRewind struct { - parent conntypes.StreamReadWriteCloser - activeReader io.Reader - buf bytes.Buffer - mutex sync.Mutex -} - -func (w *wrapperRewind) Write(p []byte) (int, error) { - return w.parent.Write(p) -} - -func (w *wrapperRewind) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - return w.parent.WriteTimeout(p, timeout) -} - -func (w *wrapperRewind) Read(p []byte) (int, error) { - w.mutex.Lock() - defer w.mutex.Unlock() - - return w.activeReader.Read(p) -} - -func (w *wrapperRewind) ReadTimeout(p []byte, _ time.Duration) (int, error) { - w.mutex.Lock() - defer w.mutex.Unlock() - - return w.activeReader.Read(p) -} - -func (w *wrapperRewind) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperRewind) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("rewinded") -} - -func (w *wrapperRewind) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperRewind) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperRewind) Close() error { - w.buf.Reset() - - return w.parent.Close() -} - -func (w *wrapperRewind) Rewind() { - w.mutex.Lock() - w.activeReader = io.MultiReader(&w.buf, w.parent) - w.mutex.Unlock() -} - -func NewRewind(parent conntypes.StreamReadWriteCloser) ReadWriteCloseRewinder { - rv := &wrapperRewind{ - parent: parent, - } - rv.activeReader = io.TeeReader(parent, &rv.buf) - - return rv -} diff --git a/wrappers/stream/stats_telegram.go b/wrappers/stream/stats_telegram.go deleted file mode 100644 index 9fe6d9e..0000000 --- a/wrappers/stream/stats_telegram.go +++ /dev/null @@ -1,71 +0,0 @@ -package stream - -import ( - "net" - "sync" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/stats" - "go.uber.org/zap" -) - -type wrapperTelegramStats struct { - parent conntypes.StreamReadWriteCloser - dc conntypes.DC - once sync.Once -} - -func (w *wrapperTelegramStats) Write(p []byte) (int, error) { - return w.parent.Write(p) -} - -func (w *wrapperTelegramStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - return w.parent.WriteTimeout(p, timeout) -} - -func (w *wrapperTelegramStats) Read(p []byte) (int, error) { - return w.parent.Read(p) -} - -func (w *wrapperTelegramStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - return w.parent.ReadTimeout(p, timeout) -} - -func (w *wrapperTelegramStats) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperTelegramStats) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("stats-telegram") -} - -func (w *wrapperTelegramStats) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperTelegramStats) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperTelegramStats) Close() error { - var err error - - w.once.Do(func() { - err = w.parent.Close() - stats.Stats.TelegramDisconnected(w.dc, w.RemoteAddr()) - }) - - return err // nolint: wrapcheck -} - -func NewTelegramStats(dc conntypes.DC, parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { - conn := &wrapperTelegramStats{ - parent: parent, - dc: dc, - } - - stats.Stats.TelegramConnected(dc, parent.RemoteAddr()) - - return conn -} diff --git a/wrappers/stream/stats_traffic.go b/wrappers/stream/stats_traffic.go deleted file mode 100644 index cc7d224..0000000 --- a/wrappers/stream/stats_traffic.go +++ /dev/null @@ -1,66 +0,0 @@ -package stream - -import ( - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "github.com/9seconds/mtg/stats" - "go.uber.org/zap" -) - -type wrapperTrafficStats struct { - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperTrafficStats) Write(p []byte) (int, error) { - n, err := w.parent.Write(p) - stats.Stats.EgressTraffic(n) - - return n, err // nolint: wrapcheck -} - -func (w *wrapperTrafficStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - n, err := w.parent.WriteTimeout(p, timeout) - stats.Stats.EgressTraffic(n) - - return n, err // nolint: wrapcheck -} - -func (w *wrapperTrafficStats) Read(p []byte) (int, error) { - n, err := w.parent.Read(p) - stats.Stats.IngressTraffic(n) - - return n, err // nolint: wrapcheck -} - -func (w *wrapperTrafficStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - n, err := w.parent.ReadTimeout(p, timeout) - stats.Stats.IngressTraffic(n) - - return n, err // nolint: wrapcheck -} - -func (w *wrapperTrafficStats) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperTrafficStats) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("stats-traffic") -} - -func (w *wrapperTrafficStats) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperTrafficStats) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func (w *wrapperTrafficStats) Close() error { - return w.parent.Close() -} - -func NewTrafficStats(parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { - return &wrapperTrafficStats{parent} -} diff --git a/wrappers/stream/timeout.go b/wrappers/stream/timeout.go deleted file mode 100644 index 2447fe2..0000000 --- a/wrappers/stream/timeout.go +++ /dev/null @@ -1,60 +0,0 @@ -package stream - -import ( - "net" - "time" - - "github.com/9seconds/mtg/conntypes" - "go.uber.org/zap" -) - -const ( - timeoutRead = 2 * time.Minute - timeoutWrite = 2 * time.Minute -) - -type wrapperTimeout struct { - parent conntypes.StreamReadWriteCloser -} - -func (w *wrapperTimeout) WriteTimeout(p []byte, timeout time.Duration) (int, error) { - return w.parent.WriteTimeout(p, timeout) -} - -func (w *wrapperTimeout) Write(p []byte) (int, error) { - return w.parent.WriteTimeout(p, timeoutWrite) -} - -func (w *wrapperTimeout) ReadTimeout(p []byte, timeout time.Duration) (int, error) { - return w.parent.ReadTimeout(p, timeout) -} - -func (w *wrapperTimeout) Read(p []byte) (int, error) { - return w.parent.ReadTimeout(p, timeoutRead) -} - -func (w *wrapperTimeout) Close() error { - return w.parent.Close() -} - -func (w *wrapperTimeout) Conn() net.Conn { - return w.parent.Conn() -} - -func (w *wrapperTimeout) Logger() *zap.SugaredLogger { - return w.parent.Logger().Named("timeout") -} - -func (w *wrapperTimeout) LocalAddr() *net.TCPAddr { - return w.parent.LocalAddr() -} - -func (w *wrapperTimeout) RemoteAddr() *net.TCPAddr { - return w.parent.RemoteAddr() -} - -func NewTimeout(parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { - return &wrapperTimeout{ - parent: parent, - } -}