mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 02:54:03 +03:00
REPOSITORY / ScuroNeko/mtg
Compare commits
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8c4d0a9c4 | ||
|
|
bfeded67ee | ||
|
|
dde0d25b77 | ||
|
|
296a34cd6e | ||
|
|
44cea68e83 | ||
|
|
790bf21166 | ||
|
|
5d17e264e6 | ||
|
|
7ef1e99f66 | ||
|
|
3acbacbdb3 | ||
|
|
5fd7062972 | ||
|
|
7a6695f6c4 | ||
|
|
8ac786581b | ||
|
|
86a8f69273 | ||
|
|
95b16cd805 | ||
|
|
3996b9a6b8 | ||
|
|
e286dea650 | ||
|
|
5e27e48129 | ||
|
|
95abb54dc8 | ||
|
|
dbd3d3c266 | ||
|
|
e5b9c841cd | ||
|
|
ad7acee64d | ||
|
|
9ce6674070 | ||
|
|
25edb60f2c | ||
|
|
b5a8d8b804 | ||
|
|
8ccf61c23e | ||
|
|
35f0fca3c5 | ||
|
|
cd46a734ea | ||
|
|
cd92a343aa | ||
|
|
289e8f5945 | ||
|
|
850bed0dfc | ||
|
|
8977d77a13 | ||
|
|
91726d461f | ||
|
|
be1a47287a | ||
|
|
426483d27b | ||
|
|
bc72717582 | ||
|
|
391d901402 | ||
|
|
837d96dc43 | ||
|
|
9125a29e79 | ||
|
|
6449109b2b | ||
|
|
829669eefd | ||
|
|
2d9f2345dc | ||
|
|
6a9069ca72 | ||
|
|
d72ed03a43 | ||
|
|
f0d2cd494a | ||
|
|
b5810c955d | ||
|
|
4ebae693e0 | ||
|
|
0e033b59b3 | ||
|
|
1a619e3090 | ||
|
|
8e29ff78ba | ||
|
|
efdac2c0d8 | ||
|
|
e559388802 | ||
|
|
cb691453f0 | ||
|
|
020065f389 | ||
|
|
cf5197cee0 | ||
|
|
720158f15c | ||
|
|
07f00a363e | ||
|
|
d32ab34e60 | ||
|
|
cdd93bd25f | ||
|
|
5a52418394 | ||
|
|
cf43ae780b | ||
|
|
2407748ab0 | ||
|
|
a47edf08d0 | ||
|
|
566955b8b7 | ||
|
|
5cc07a54a2 | ||
|
|
ba2143a6ae | ||
|
|
acb02baa2e | ||
|
|
422ed5b071 | ||
|
|
19efcc93fc | ||
|
|
b4c47ff4e1 | ||
|
|
8a783d6b4e | ||
|
|
c5029c706c | ||
|
|
d7e565e0f5 | ||
|
|
93686377d5 | ||
|
|
87de28636a | ||
|
|
7788b169b6 | ||
|
|
6b9601fc2c | ||
|
|
a65cb05d20 | ||
|
|
31866d5f64 | ||
|
|
0db83a0cc8 | ||
|
|
40bb59faf5 |
@@ -9,3 +9,4 @@ mtg
|
|||||||
vendor/
|
vendor/
|
||||||
version.go
|
version.go
|
||||||
ccbuilds/
|
ccbuilds/
|
||||||
|
.bin/
|
||||||
|
|||||||
+1
-1
@@ -10,4 +10,4 @@ format = "colored-line-number"
|
|||||||
|
|
||||||
[linters]
|
[linters]
|
||||||
enable-all = true
|
enable-all = true
|
||||||
disable = ["gochecknoglobals"]
|
disable = ["gochecknoglobals", "gas", "gomnd", "goerr113"]
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ sudo: false
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
go:
|
go:
|
||||||
|
- 1.15.x
|
||||||
|
- 1.14.x
|
||||||
- 1.13.x
|
- 1.13.x
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
|||||||
+6
-8
@@ -1,7 +1,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# BUILD STAGE
|
# BUILD STAGE
|
||||||
|
|
||||||
FROM golang:1.13-alpine
|
FROM golang:1.15-alpine AS build
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& apk --no-cache --update add \
|
&& apk --no-cache --update add \
|
||||||
@@ -13,9 +13,9 @@ RUN set -x \
|
|||||||
upx
|
upx
|
||||||
|
|
||||||
COPY . /go/src/github.com/9seconds/mtg/
|
COPY . /go/src/github.com/9seconds/mtg/
|
||||||
|
WORKDIR /go/src/github.com/9seconds/mtg
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& cd /go/src/github.com/9seconds/mtg \
|
|
||||||
&& make -j 4 static \
|
&& make -j 4 static \
|
||||||
&& upx --ultra-brute -qq ./mtg
|
&& upx --ultra-brute -qq ./mtg
|
||||||
|
|
||||||
@@ -26,11 +26,9 @@ RUN set -x \
|
|||||||
FROM scratch
|
FROM scratch
|
||||||
|
|
||||||
ENTRYPOINT ["/mtg"]
|
ENTRYPOINT ["/mtg"]
|
||||||
ENV MTG_IP=0.0.0.0 \
|
ENV MTG_BIND=0.0.0.0:3128 \
|
||||||
MTG_PORT=3128 \
|
MTG_STATS_BIND=0.0.0.0:3129
|
||||||
MTG_STATS_IP=0.0.0.0 \
|
|
||||||
MTG_STATS_PORT=3129
|
|
||||||
EXPOSE 3128 3129
|
EXPOSE 3128 3129
|
||||||
|
|
||||||
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
COPY --from=0 /go/src/github.com/9seconds/mtg/mtg /mtg
|
COPY --from=build /go/src/github.com/9seconds/mtg/mtg /mtg
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ APP_NAME := $(IMAGE_NAME)
|
|||||||
|
|
||||||
CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}")
|
CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}")
|
||||||
|
|
||||||
GOLANGCI_LINT_VERSION := v1.21.0
|
GOLANGCI_LINT_VERSION := v1.31.0
|
||||||
|
|
||||||
VERSION_GO := $(shell go version)
|
VERSION_GO := $(shell go version)
|
||||||
VERSION_DATE := $(shell date -Ru)
|
VERSION_DATE := $(shell date -Ru)
|
||||||
@@ -53,7 +53,7 @@ crosscompile-dir:
|
|||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: vendor
|
lint: vendor
|
||||||
@$(MOD_OFF) golangci-lint run
|
@$(MOD_OFF) "$(ROOT_DIR)/.bin/golangci-lint" run
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@@ -70,5 +70,6 @@ prepare: install-lint
|
|||||||
|
|
||||||
.PHONY: install-lint
|
.PHONY: install-lint
|
||||||
install-lint:
|
install-lint:
|
||||||
@curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \
|
@mkdir -p ./bin || true && \
|
||||||
| $(MOD_OFF) bash -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \
|
||||||
|
| $(MOD_OFF) bash -s -- -b "$(ROOT_DIR)/.bin" $(GOLANGCI_LINT_VERSION)
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ by design and we have the negligible possibility of duplication
|
|||||||
(probability is 1/(2^64)) but it could be quite effective to prevent
|
(probability is 1/(2^64)) but it could be quite effective to prevent
|
||||||
replays.
|
replays.
|
||||||
|
|
||||||
|
It is possible to disable this cache. To do that, please explicitly set
|
||||||
|
its size to 0.
|
||||||
|
|
||||||
|
|
||||||
## FakeTLS
|
## FakeTLS
|
||||||
|
|
||||||
@@ -191,11 +194,14 @@ supported environment variables:
|
|||||||
| `MTG_STATSD_PREFIX` | `--statsd-prefix` | `mtg` | Which bucket prefix we should use. For example, if you set `mtg`, then metric `traffic.ingress` would be send as `mtg.traffic.ingress`. |
|
| `MTG_STATSD_PREFIX` | `--statsd-prefix` | `mtg` | Which bucket prefix we should use. For example, if you set `mtg`, then metric `traffic.ingress` would be send as `mtg.traffic.ingress`. |
|
||||||
| `MTG_STATSD_TAGS_FORMAT` | `--statsd-tags-format` | | Which tags format we should use. By default, we are using default vanilla statsd tags format but if you want to send directly to InfluxDB or Datadog, please specify it there. Possible options are `influxdb` and `datadog`. |
|
| `MTG_STATSD_TAGS_FORMAT` | `--statsd-tags-format` | | Which tags format we should use. By default, we are using default vanilla statsd tags format but if you want to send directly to InfluxDB or Datadog, please specify it there. Possible options are `influxdb` and `datadog`. |
|
||||||
| `MTG_STATSD_TAGS` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. |
|
| `MTG_STATSD_TAGS` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. |
|
||||||
| `MTG_BUFFER_WRITE` | `-w`, `--write-buffer` | `65536` | The size of TCP write buffer in bytes. Write buffer is the buffer for messages which are going from client to Telegram. |
|
| `MTG_BUFFER_WRITE` | `-w`, `--write-buffer` | `32KB` | The size of TCP write buffer in bytes. Write buffer is the buffer for messages which are going from client to Telegram. |
|
||||||
| `MTG_BUFFER_READ` | `-r`, `--read-buffer` | `131072` | The size of TCP read buffer in bytes. Read buffer is the buffer for messages from Telegram to client. |
|
| `MTG_BUFFER_READ` | `-r`, `--read-buffer` | `32KB` | The size of TCP read buffer in bytes. Read buffer is the buffer for messages from Telegram to client. |
|
||||||
| `MTG_ANTIREPLAY_MAXSIZE` | `--anti-replay-max-size` | `128MB` | Max size of antireplay cache. |
|
| `MTG_ANTIREPLAY_MAXSIZE` | `--anti-replay-max-size` | `128MB` | Max size of antireplay cache. |
|
||||||
| `MTG_CLOAK_PORT` | `--cloak-port` | `443` | Which port we should use to connect to cloaked host in FakeTLS mode. |
|
| `MTG_CLOAK_PORT` | `--cloak-port` | `443` | Which port we should use to connect to cloaked host in FakeTLS mode. |
|
||||||
| `MTG_MULTIPLEX_PERCONNECTION` | `--multiplex-per-connection` | `50` | How many client connections can share a single Telegram connection in adtag mode |
|
| `MTG_MULTIPLEX_PERCONNECTION` | `--multiplex-per-connection` | `50` | How many client connections can share a single Telegram connection in adtag mode |
|
||||||
|
| `MTG_NTP_SERVERS` | `--ntp-server` | default pool | A list of NTP servers to use. |
|
||||||
|
| `MTG_PREFER_DIRECT_IP` | `--prefer-ip` | `ipv6` | Which IP protocol to prefer if possible. Works mostly in direct mode. |
|
||||||
|
|
||||||
|
|
||||||
Usually you want to modify only read/write buffer sizes. If you feel
|
Usually you want to modify only read/write buffer sizes. If you feel
|
||||||
that proxy is slow, try to increase both sizes giving more priority to
|
that proxy is slow, try to increase both sizes giving more priority to
|
||||||
|
|||||||
+4
-4
@@ -11,19 +11,19 @@ type cache struct {
|
|||||||
data *fastcache.Cache
|
data *fastcache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) AddObfuscated2(data []byte) {
|
func (c cache) AddObfuscated2(data []byte) {
|
||||||
c.data.Set(keyObfuscated2(data), nil)
|
c.data.Set(keyObfuscated2(data), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) AddTLS(data []byte) {
|
func (c cache) AddTLS(data []byte) {
|
||||||
c.data.Set(keyTLS(data), nil)
|
c.data.Set(keyTLS(data), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) HasObfuscated2(data []byte) bool {
|
func (c cache) HasObfuscated2(data []byte) bool {
|
||||||
return c.data.Has(keyObfuscated2(data))
|
return c.data.Has(keyObfuscated2(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) HasTLS(data []byte) bool {
|
func (c cache) HasTLS(data []byte) bool {
|
||||||
return c.data.Has(keyTLS(data))
|
return c.data.Has(keyTLS(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -3,18 +3,28 @@ package antireplay
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/fastcache"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
|
"github.com/VictoriaMetrics/fastcache"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CacheInterface interface {
|
||||||
|
AddObfuscated2([]byte)
|
||||||
|
AddTLS([]byte)
|
||||||
|
HasObfuscated2([]byte) bool
|
||||||
|
HasTLS([]byte) bool
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Cache cache
|
Cache CacheInterface
|
||||||
initOnce sync.Once
|
initOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
initOnce.Do(func() {
|
initOnce.Do(func() {
|
||||||
Cache.data = fastcache.New(config.C.AntiReplayMaxSize)
|
if config.C.AntiReplayMaxSize == 0 {
|
||||||
|
Cache = nilCache{}
|
||||||
|
} else {
|
||||||
|
Cache = cache{fastcache.New(config.C.AntiReplayMaxSize)}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
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 }
|
||||||
+3
-4
@@ -5,9 +5,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/antireplay"
|
"github.com/9seconds/mtg/antireplay"
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/faketls"
|
"github.com/9seconds/mtg/faketls"
|
||||||
@@ -18,6 +15,8 @@ import (
|
|||||||
"github.com/9seconds/mtg/stats"
|
"github.com/9seconds/mtg/stats"
|
||||||
"github.com/9seconds/mtg/telegram"
|
"github.com/9seconds/mtg/telegram"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Proxy() error { // nolint: funlen
|
func Proxy() error { // nolint: funlen
|
||||||
@@ -50,7 +49,7 @@ func Proxy() error { // nolint: funlen
|
|||||||
|
|
||||||
zap.S().Debugw("Configuration", "config", config.Printable())
|
zap.S().Debugw("Configuration", "config", config.Printable())
|
||||||
|
|
||||||
if len(config.C.AdTag) > 0 {
|
if config.C.MiddleProxyMode() {
|
||||||
zap.S().Infow("Use middle proxy connection to Telegram")
|
zap.S().Infow("Use middle proxy connection to Telegram")
|
||||||
|
|
||||||
diff, err := ntp.Fetch()
|
diff, err := ntp.Fetch()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/alecthomas/units"
|
"github.com/alecthomas/units"
|
||||||
@@ -21,6 +22,8 @@ func (s SecretMode) String() string {
|
|||||||
return "simple"
|
return "simple"
|
||||||
case SecretModeSecured:
|
case SecretModeSecured:
|
||||||
return "secured"
|
return "secured"
|
||||||
|
case SecretModeTLS:
|
||||||
|
return "tls"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "tls"
|
return "tls"
|
||||||
@@ -32,6 +35,13 @@ const (
|
|||||||
SecretModeTLS
|
SecretModeTLS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PreferIP uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
PreferIPv4 PreferIP = iota
|
||||||
|
PreferIPv6
|
||||||
|
)
|
||||||
|
|
||||||
const SimpleSecretLength = 16
|
const SimpleSecretLength = 16
|
||||||
|
|
||||||
type OptionType uint8
|
type OptionType uint8
|
||||||
@@ -40,6 +50,8 @@ const (
|
|||||||
OptionTypeDebug OptionType = iota
|
OptionTypeDebug OptionType = iota
|
||||||
OptionTypeVerbose
|
OptionTypeVerbose
|
||||||
|
|
||||||
|
OptionTypePreferIP
|
||||||
|
|
||||||
OptionTypeBind
|
OptionTypeBind
|
||||||
OptionTypePublicIPv4
|
OptionTypePublicIPv4
|
||||||
OptionTypePublicIPv6
|
OptionTypePublicIPv6
|
||||||
@@ -59,6 +71,8 @@ const (
|
|||||||
|
|
||||||
OptionTypeMultiplexPerConnection
|
OptionTypeMultiplexPerConnection
|
||||||
|
|
||||||
|
OptionTypeNTPServers
|
||||||
|
|
||||||
OptionTypeSecret
|
OptionTypeSecret
|
||||||
OptionTypeAdtag
|
OptionTypeAdtag
|
||||||
)
|
)
|
||||||
@@ -86,11 +100,59 @@ type Config struct {
|
|||||||
Debug bool `json:"debug"`
|
Debug bool `json:"debug"`
|
||||||
Verbose bool `json:"verbose"`
|
Verbose bool `json:"verbose"`
|
||||||
SecretMode SecretMode `json:"secret_mode"`
|
SecretMode SecretMode `json:"secret_mode"`
|
||||||
|
PreferIP PreferIP `json:"prefer_ip"`
|
||||||
|
NTPServers []string `json:"ntp_servers"`
|
||||||
|
|
||||||
Secret []byte `json:"secret"`
|
Secret []byte `json:"secret"`
|
||||||
AdTag []byte `json:"adtag"`
|
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 {
|
type Opt struct {
|
||||||
Option OptionType
|
Option OptionType
|
||||||
Value interface{}
|
Value interface{}
|
||||||
@@ -105,6 +167,16 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen
|
|||||||
C.Debug = opt.Value.(bool)
|
C.Debug = opt.Value.(bool)
|
||||||
case OptionTypeVerbose:
|
case OptionTypeVerbose:
|
||||||
C.Verbose = opt.Value.(bool)
|
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:
|
case OptionTypeBind:
|
||||||
C.Bind = opt.Value.(*net.TCPAddr)
|
C.Bind = opt.Value.(*net.TCPAddr)
|
||||||
case OptionTypePublicIPv4:
|
case OptionTypePublicIPv4:
|
||||||
@@ -145,6 +217,11 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen
|
|||||||
C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes))
|
C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes))
|
||||||
case OptionTypeMultiplexPerConnection:
|
case OptionTypeMultiplexPerConnection:
|
||||||
C.MultiplexPerConnection = int(opt.Value.(uint))
|
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:
|
case OptionTypeSecret:
|
||||||
C.Secret = opt.Value.([]byte)
|
C.Secret = opt.Value.([]byte)
|
||||||
case OptionTypeAdtag:
|
case OptionTypeAdtag:
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func fetchIP(ctx context.Context, network string) (net.IP, error) {
|
|||||||
return nil, fmt.Errorf("cannot perform a request: %w", err)
|
return nil, fmt.Errorf("cannot perform a request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close() // nolint: errcheck
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respDataBytes, err := ioutil.ReadAll(resp.Body)
|
respDataBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ func (c ConnectionProtocol) String() string {
|
|||||||
return "any"
|
return "any"
|
||||||
case ConnectionProtocolIPv4:
|
case ConnectionProtocolIPv4:
|
||||||
return "ipv4"
|
return "ipv4"
|
||||||
|
case ConnectionProtocolIPv6:
|
||||||
|
return "ipv6"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "ipv6"
|
return "ipv6"
|
||||||
|
|||||||
+3
-1
@@ -21,7 +21,9 @@ func (t ConnectionType) Tag() []byte {
|
|||||||
return ConnectionTagAbridged
|
return ConnectionTagAbridged
|
||||||
case ConnectionTypeIntermediate:
|
case ConnectionTypeIntermediate:
|
||||||
return ConnectionTagIntermediate
|
return ConnectionTagIntermediate
|
||||||
default:
|
case ConnectionTypeSecure, ConnectionTypeUnknown:
|
||||||
return ConnectionTagSecure
|
return ConnectionTagSecure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ConnectionTagSecure
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-24
@@ -2,13 +2,13 @@ package faketls
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/9seconds/mtg/antireplay"
|
"github.com/9seconds/mtg/antireplay"
|
||||||
@@ -49,8 +49,8 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn := stream.NewFakeTLS(socket)
|
conn := stream.NewFakeTLS(socket)
|
||||||
conn, err := c.ClientProtocol.Handshake(conn)
|
|
||||||
|
|
||||||
|
conn, err := c.ClientProtocol.Handshake(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,10 @@ func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
|
|||||||
return fmt.Errorf("cannot read initial record: %w", err)
|
return fmt.Errorf("cannot read initial record: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientHello, err := tlstypes.ParseClientHello(helloRecord.Data.Bytes())
|
buf := &bytes.Buffer{}
|
||||||
|
helloRecord.Data.WriteBytes(buf)
|
||||||
|
|
||||||
|
clientHello, err := tlstypes.ParseClientHello(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot parse client hello: %w", err)
|
return fmt.Errorf("cannot parse client hello: %w", err)
|
||||||
}
|
}
|
||||||
@@ -86,6 +89,7 @@ func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
|
|||||||
|
|
||||||
if antireplay.Cache.HasTLS(clientHello.Random[:]) {
|
if antireplay.Cache.HasTLS(clientHello.Random[:]) {
|
||||||
stats.Stats.ReplayDetected()
|
stats.Stats.ReplayDetected()
|
||||||
|
|
||||||
return errors.New("replay attack is detected")
|
return errors.New("replay attack is detected")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,32 +105,16 @@ func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientProtocol) cloakHost(clientConn io.ReadWriteCloser) {
|
func (c *ClientProtocol) cloakHost(clientConn io.ReadWriteCloser) {
|
||||||
addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort))
|
stats.Stats.CloakedRequest()
|
||||||
hostConn, err := net.Dial("tcp", addr)
|
|
||||||
|
|
||||||
|
addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort))
|
||||||
|
|
||||||
|
hostConn, err := net.Dial("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer hostConn.Close()
|
cloak(clientConn, hostConn)
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(2)
|
|
||||||
|
|
||||||
go c.pipe(hostConn, clientConn, wg)
|
|
||||||
|
|
||||||
go c.pipe(clientConn, hostConn, wg)
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientProtocol) pipe(dst io.WriteCloser, src io.Reader, wg *sync.WaitGroup) {
|
|
||||||
defer func() {
|
|
||||||
wg.Done()
|
|
||||||
dst.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
io.Copy(dst, src) // nolint: errcheck
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeClientProtocol() protocol.ClientProtocol {
|
func MakeClientProtocol() protocol.ClientProtocol {
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -3,18 +3,20 @@ module github.com/9seconds/mtg
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/VictoriaMetrics/fastcache v1.5.2
|
github.com/VictoriaMetrics/fastcache v1.5.7
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
|
||||||
github.com/beevik/ntp v0.2.0
|
github.com/beevik/ntp v0.3.0
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
github.com/prometheus/client_golang v1.7.1
|
||||||
github.com/prometheus/client_golang v1.2.1
|
github.com/prometheus/common v0.13.0 // indirect
|
||||||
github.com/prometheus/procfs v0.0.7 // indirect
|
|
||||||
github.com/smira/go-statsd v1.3.1
|
github.com/smira/go-statsd v1.3.1
|
||||||
go.uber.org/multierr v1.4.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.13.0
|
go.uber.org/zap v1.16.0
|
||||||
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 // indirect
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
|
||||||
golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
|
||||||
golang.org/x/tools v0.0.0-20191118222007-07fc4c7f2b98 // indirect
|
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff
|
||||||
|
golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458 // indirect
|
||||||
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
|
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 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/VictoriaMetrics/fastcache v1.5.2 h1:Erd8iIuBAL9kke8JzM4+WxkKuFkHh3ktwLanJvDgR44=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.5.2/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE=
|
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 h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
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 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||||
@@ -16,98 +21,268 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2c
|
|||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
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 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
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 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
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 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
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/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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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.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.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.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.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/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 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
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 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
github.com/golang/protobuf v1.3.1/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 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
github.com/golang/protobuf v1.3.2/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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/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 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
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.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
github.com/google/go-cmp v0.3.1/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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
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/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.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.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.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/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.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/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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
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/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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
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 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
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-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/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-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 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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.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.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
|
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||||
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
|
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
|
||||||
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
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 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/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 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
|
|
||||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
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.13.0 h1:vJlpe9wPgDRM1Z+7Wj3zUUjY1nr6/1jNKyl7llliccg=
|
||||||
|
github.com/prometheus/common v0.13.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
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 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
||||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
github.com/prometheus/procfs v0.0.7 h1:RS5GAlMbnkWkhs4+bPocMTmGjYkuCY5djjqEDdXOhcQ=
|
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||||
github.com/prometheus/procfs v0.0.7/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
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/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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
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.1 h1:JalGiHNdK7GqVAPpg7j0Kwp2jZrz/fCg/B4ZuNuBY2w=
|
github.com/smira/go-statsd v1.3.1 h1:JalGiHNdK7GqVAPpg7j0Kwp2jZrz/fCg/B4ZuNuBY2w=
|
||||||
github.com/smira/go-statsd v1.3.1/go.mod h1:1srXJ9/pbnN04G8f4F1jUzsGOnwkPKXciyqpewGlkC4=
|
github.com/smira/go-statsd v1.3.1/go.mod h1:1srXJ9/pbnN04G8f4F1jUzsGOnwkPKXciyqpewGlkC4=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
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.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/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 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
@@ -116,63 +291,197 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
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.1.25/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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||||
|
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.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E=
|
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
||||||
go.uber.org/multierr v1.4.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 h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
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.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-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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f h1:kz4KIr+xcPUsI3VMoqWfPMvtnJ6MGfiVwsWSVzphMO4=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
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-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
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 h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/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.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||||
|
golang.org/x/mod v0.2.0/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-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-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-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-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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-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-20190911185100-cd5d95a43a6e/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-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-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-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-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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2 h1:wAW1U21MfVN0sUipAD8952TBjGXMRHFKQugDlQ9RwwE=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2/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 h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||||
|
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-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8=
|
||||||
|
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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/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-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-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-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/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-20191118222007-07fc4c7f2b98 h1:tZwpOHmF1OEL9wJGSgBALnhFg/8VKjQTtctCX51GLNI=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191118222007-07fc4c7f2b98/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.0.0-20200319210407-521f4a0cd458 h1:DgonIcqC7u+gVZX7lpuReBil5B/i8fvW/hAQdhT6/ao=
|
||||||
|
golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
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 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/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 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/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 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||||
|
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 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
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=
|
||||||
|
|||||||
+11
-2
@@ -4,15 +4,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/mtproto"
|
"github.com/9seconds/mtg/mtproto"
|
||||||
"github.com/9seconds/mtg/mtproto/rpc"
|
"github.com/9seconds/mtg/mtproto/rpc"
|
||||||
"github.com/9seconds/mtg/protocol"
|
"github.com/9seconds/mtg/protocol"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const connectionTTL = time.Hour
|
||||||
|
|
||||||
type connection struct {
|
type connection struct {
|
||||||
conn conntypes.PacketReadWriteCloser
|
conn conntypes.PacketReadWriteCloser
|
||||||
proxyConns map[string]*ProxyConn
|
proxyConns map[string]*ProxyConn
|
||||||
@@ -31,6 +33,9 @@ type connection struct {
|
|||||||
func (c *connection) run() {
|
func (c *connection) run() {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
ttl := time.NewTimer(connectionTTL)
|
||||||
|
defer ttl.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.channelDone:
|
case <-c.channelDone:
|
||||||
@@ -39,6 +44,9 @@ func (c *connection) run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
case <-ttl.C:
|
||||||
|
c.logger.Debugw("Closing connection by TTL")
|
||||||
|
c.Close()
|
||||||
case resp := <-c.channelRead:
|
case resp := <-c.channelRead:
|
||||||
if channel, ok := c.proxyConns[string(resp.ConnID[:])]; ok {
|
if channel, ok := c.proxyConns[string(resp.ConnID[:])]; ok {
|
||||||
if resp.Type == rpc.ProxyResponseTypeCloseExt {
|
if resp.Type == rpc.ProxyResponseTypeCloseExt {
|
||||||
@@ -81,6 +89,7 @@ func (c *connection) readLoop() {
|
|||||||
response, err := rpc.ParseProxyResponse(packet)
|
response, err := rpc.ParseProxyResponse(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Debugw("Failed response", "error", err)
|
c.logger.Debugw("Failed response", "error", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ func (c *connectionList) get(conn *ProxyConn) (*connection, error) {
|
|||||||
|
|
||||||
if err = newConn.Attach(conn); err != nil {
|
if err = newConn.Attach(conn); err != nil {
|
||||||
newConn.Close()
|
newConn.Close()
|
||||||
|
|
||||||
return nil, fmt.Errorf("cannot attach to the newly created connection: %w", err)
|
return nil, fmt.Errorf("cannot attach to the newly created connection: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/cli"
|
"github.com/9seconds/mtg/cli"
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "dev" // has to be set by ldflags
|
var version = "dev" // has to be set by ldflags
|
||||||
@@ -43,6 +42,11 @@ var (
|
|||||||
Short('v').
|
Short('v').
|
||||||
Envar("MTG_VERBOSE").
|
Envar("MTG_VERBOSE").
|
||||||
Bool()
|
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",
|
runBind = runCommand.Flag("bind",
|
||||||
"Host:Port to bind proxy to.").
|
"Host:Port to bind proxy to.").
|
||||||
Short('b').
|
Short('b').
|
||||||
@@ -87,13 +91,13 @@ var (
|
|||||||
"Write buffer size. You can think about it as a buffer from client to Telegram.").
|
"Write buffer size. You can think about it as a buffer from client to Telegram.").
|
||||||
Short('w').
|
Short('w').
|
||||||
Envar("MTG_BUFFER_WRITE").
|
Envar("MTG_BUFFER_WRITE").
|
||||||
Default("64KB").
|
Default("32KB").
|
||||||
Bytes()
|
Bytes()
|
||||||
runReadBufferSize = runCommand.Flag("read-buffer",
|
runReadBufferSize = runCommand.Flag("read-buffer",
|
||||||
"Read buffer size. You can think about it as a buffer from Telegram to client.").
|
"Read buffer size. You can think about it as a buffer from Telegram to client.").
|
||||||
Short('r').
|
Short('r').
|
||||||
Envar("MTG_BUFFER_READ").
|
Envar("MTG_BUFFER_READ").
|
||||||
Default("128KB").
|
Default("32KB").
|
||||||
Bytes()
|
Bytes()
|
||||||
runTLSCloakPort = runCommand.Flag("cloak-port",
|
runTLSCloakPort = runCommand.Flag("cloak-port",
|
||||||
"Port which should be used for host cloaking.").
|
"Port which should be used for host cloaking.").
|
||||||
@@ -110,6 +114,11 @@ var (
|
|||||||
Envar("MTG_MULTIPLEX_PERCONNECTION").
|
Envar("MTG_MULTIPLEX_PERCONNECTION").
|
||||||
Default("50").
|
Default("50").
|
||||||
Uint()
|
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()
|
runSecret = runCommand.Arg("secret", "Secret of this proxy.").Required().HexBytes()
|
||||||
runAdtag = runCommand.Arg("adtag", "ADTag of the proxy.").HexBytes()
|
runAdtag = runCommand.Arg("adtag", "ADTag of the proxy.").HexBytes()
|
||||||
)
|
)
|
||||||
@@ -130,6 +139,7 @@ func main() {
|
|||||||
err := config.Init(
|
err := config.Init(
|
||||||
config.Opt{Option: config.OptionTypeDebug, Value: *runDebug},
|
config.Opt{Option: config.OptionTypeDebug, Value: *runDebug},
|
||||||
config.Opt{Option: config.OptionTypeVerbose, Value: *runVerbose},
|
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.OptionTypeBind, Value: *runBind},
|
||||||
config.Opt{Option: config.OptionTypePublicIPv4, Value: *runPublicIPv4},
|
config.Opt{Option: config.OptionTypePublicIPv4, Value: *runPublicIPv4},
|
||||||
config.Opt{Option: config.OptionTypePublicIPv6, Value: *runPublicIPv6},
|
config.Opt{Option: config.OptionTypePublicIPv6, Value: *runPublicIPv6},
|
||||||
@@ -143,6 +153,7 @@ func main() {
|
|||||||
config.Opt{Option: config.OptionTypeCloakPort, Value: *runTLSCloakPort},
|
config.Opt{Option: config.OptionTypeCloakPort, Value: *runTLSCloakPort},
|
||||||
config.Opt{Option: config.OptionTypeAntiReplayMaxSize, Value: *runAntiReplayMaxSize},
|
config.Opt{Option: config.OptionTypeAntiReplayMaxSize, Value: *runAntiReplayMaxSize},
|
||||||
config.Opt{Option: config.OptionTypeMultiplexPerConnection, Value: *runMultiplexPerConnection},
|
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.OptionTypeSecret, Value: *runSecret},
|
||||||
config.Opt{Option: config.OptionTypeAdtag, Value: *runAdtag},
|
config.Opt{Option: config.OptionTypeAdtag, Value: *runAdtag},
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -19,8 +19,8 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC
|
|||||||
}
|
}
|
||||||
|
|
||||||
rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce)
|
rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce)
|
||||||
rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
|
|
||||||
|
|
||||||
|
rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot do nonce request: %w", err)
|
return nil, fmt.Errorf("cannot do nonce request: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const (
|
|||||||
SeqNoHandshake = -1
|
SeqNoHandshake = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Different constants for RPC protocol
|
// Different constants for RPC protocol.
|
||||||
var (
|
var (
|
||||||
TagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e}
|
TagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e}
|
||||||
TagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44}
|
TagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ type HandshakeResponse struct {
|
|||||||
func (r *HandshakeResponse) Bytes() []byte {
|
func (r *HandshakeResponse) Bytes() []byte {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
buf.Write(r.Type) // nolint: gosec
|
buf.Write(r.Type)
|
||||||
buf.Write(r.Flags) // nolint: gosec
|
buf.Write(r.Flags)
|
||||||
buf.Write(r.SenderPID) // nolint: gosec
|
buf.Write(r.SenderPID)
|
||||||
buf.Write(r.PeerPID) // nolint: gosec
|
buf.Write(r.PeerPID)
|
||||||
|
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ type NonceResponse struct {
|
|||||||
|
|
||||||
// Bytes returns serialized form of the nonce response.
|
// Bytes returns serialized form of the nonce response.
|
||||||
func (r *NonceResponse) Bytes() []byte {
|
func (r *NonceResponse) Bytes() []byte {
|
||||||
buf := &bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
buf.Write(r.Type) // nolint: gosec
|
buf.Write(r.Type)
|
||||||
buf.Write(r.KeySelector) // nolint: gosec
|
buf.Write(r.KeySelector)
|
||||||
buf.Write(r.Crypto) // nolint: gosec
|
buf.Write(r.Crypto)
|
||||||
buf.Write(r.CryptoTS) // nolint: gosec
|
buf.Write(r.CryptoTS)
|
||||||
buf.Write(r.Nonce) // nolint: gosec
|
buf.Write(r.Nonce)
|
||||||
|
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-8
@@ -5,22 +5,16 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/beevik/ntp"
|
"github.com/beevik/ntp"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const autoUpdatePeriod = time.Minute
|
const autoUpdatePeriod = time.Minute
|
||||||
|
|
||||||
var ntpEndpoints = [...]string{
|
|
||||||
"0.pool.ntp.org",
|
|
||||||
"1.pool.ntp.org",
|
|
||||||
"2.pool.ntp.org",
|
|
||||||
"3.pool.ntp.org",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch fetches the data on time drift.
|
// Fetch fetches the data on time drift.
|
||||||
func Fetch() (time.Duration, error) {
|
func Fetch() (time.Duration, error) {
|
||||||
url := ntpEndpoints[rand.Intn(len(ntpEndpoints))]
|
url := config.C.NTPServers[rand.Intn(len(config.C.NTPServers))] // nolint: gosec
|
||||||
|
|
||||||
resp, err := ntp.Query(url)
|
resp, err := ntp.Query(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,6 +39,7 @@ func AutoUpdate() {
|
|||||||
diff, err := Fetch()
|
diff, err := Fetch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debugw("Cannot fetch time from NTP", "error", err)
|
logger.Debugw("Cannot fetch time from NTP", "error", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
|
|||||||
replayKey := decryptedFrame.Unique()
|
replayKey := decryptedFrame.Unique()
|
||||||
if antireplay.Cache.HasObfuscated2(replayKey) {
|
if antireplay.Cache.HasObfuscated2(replayKey) {
|
||||||
stats.Stats.ReplayDetected()
|
stats.Stats.ReplayDetected()
|
||||||
|
|
||||||
return nil, errors.New("replay attack is detected")
|
return nil, errors.New("replay attack is detected")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const (
|
|||||||
frameLen = 64
|
frameLen = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd]
|
// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd].
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
data [frameLen]byte
|
data [frameLen]byte
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -3,9 +3,8 @@ package protocol
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TelegramRequest struct {
|
type TelegramRequest struct {
|
||||||
|
|||||||
+5
-5
@@ -4,14 +4,13 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/obfuscated2"
|
"github.com/9seconds/mtg/obfuscated2"
|
||||||
"github.com/9seconds/mtg/protocol"
|
"github.com/9seconds/mtg/protocol"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const directPipeBufferSize = 1024 * 1024
|
const directPipeBufferSize = 1024
|
||||||
|
|
||||||
func directConnection(request *protocol.TelegramRequest) error {
|
func directConnection(request *protocol.TelegramRequest) error {
|
||||||
telegramConnRaw, err := obfuscated2.TelegramProtocol(request)
|
telegramConnRaw, err := obfuscated2.TelegramProtocol(request)
|
||||||
@@ -42,8 +41,9 @@ func directPipe(dst io.WriteCloser, src io.ReadCloser, wg *sync.WaitGroup, logge
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
buf := make([]byte, directPipeBufferSize)
|
buf := [directPipeBufferSize]byte{}
|
||||||
if _, err := io.CopyBuffer(dst, src, buf); err != nil {
|
|
||||||
|
if _, err := io.CopyBuffer(dst, src, buf[:]); err != nil {
|
||||||
logger.Debugw("Cannot pump sockets", "error", err)
|
logger.Debugw("Cannot pump sockets", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -3,17 +3,17 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/protocol"
|
"github.com/9seconds/mtg/protocol"
|
||||||
"github.com/9seconds/mtg/wrappers/packetack"
|
"github.com/9seconds/mtg/wrappers/packetack"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func middleConnection(request *protocol.TelegramRequest) {
|
func middleConnection(request *protocol.TelegramRequest) {
|
||||||
telegramConn, err := packetack.NewProxy(request)
|
telegramConn, err := packetack.NewProxy(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
request.Logger.Debugw("Cannot dial to Telegram", "error", err)
|
request.Logger.Debugw("Cannot dial to Telegram", "error", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer telegramConn.Close()
|
defer telegramConn.Close()
|
||||||
@@ -27,7 +27,7 @@ func middleConnection(request *protocol.TelegramRequest) {
|
|||||||
clientConn = packetack.NewClientIntermediate(request.ClientConn)
|
clientConn = packetack.NewClientIntermediate(request.ClientConn)
|
||||||
case conntypes.ConnectionTypeSecure:
|
case conntypes.ConnectionTypeSecure:
|
||||||
clientConn = packetack.NewClientIntermediateSecure(request.ClientConn)
|
clientConn = packetack.NewClientIntermediateSecure(request.ClientConn)
|
||||||
default:
|
case conntypes.ConnectionTypeUnknown:
|
||||||
panic("unknown connection type")
|
panic("unknown connection type")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,15 +53,17 @@ func middlePipe(dst conntypes.PacketAckWriteCloser,
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
acks := conntypes.ConnectionAcks{}
|
acks := conntypes.ConnectionAcks{}
|
||||||
packet, err := src.Read(&acks)
|
|
||||||
|
|
||||||
|
packet, err := src.Read(&acks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debugw("Cannot read packet", "error", err)
|
logger.Debugw("Cannot read packet", "error", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = dst.Write(packet, &acks); err != nil {
|
if err = dst.Write(packet, &acks); err != nil {
|
||||||
logger.Debugw("Cannot send packet", "error", err)
|
logger.Debugw("Cannot send packet", "error", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -4,14 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/protocol"
|
"github.com/9seconds/mtg/protocol"
|
||||||
"github.com/9seconds/mtg/stats"
|
"github.com/9seconds/mtg/stats"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
"github.com/9seconds/mtg/wrappers/stream"
|
"github.com/9seconds/mtg/wrappers/stream"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
@@ -30,8 +29,7 @@ func (p *Proxy) Serve(listener net.Listener) {
|
|||||||
case <-doneChan:
|
case <-doneChan:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
p.Logger.Errorw("Cannot allocate incoming connection", "error", err)
|
p.Logger.Fatalw("Cannot allocate incoming connection", "error", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +40,7 @@ func (p *Proxy) Serve(listener net.Listener) {
|
|||||||
func (p *Proxy) accept(conn net.Conn) {
|
func (p *Proxy) accept(conn net.Conn) {
|
||||||
defer func() {
|
defer func() {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
stats.Stats.Crash()
|
stats.Stats.Crash()
|
||||||
p.Logger.Errorw("Crash of accept handler", "error", err)
|
p.Logger.Errorw("Crash of accept handler", "error", err)
|
||||||
@@ -51,8 +50,9 @@ func (p *Proxy) accept(conn net.Conn) {
|
|||||||
connID := conntypes.NewConnID()
|
connID := conntypes.NewConnID()
|
||||||
logger := p.Logger.With("connection_id", connID)
|
logger := p.Logger.With("connection_id", connID)
|
||||||
|
|
||||||
if err := utils.InitTCP(conn); err != nil {
|
if err := utils.InitTCP(conn, config.C.ClientReadBuffer(), config.C.ClientWriteBuffer()); err != nil {
|
||||||
logger.Errorw("Cannot initialize client TCP connection", "error", err)
|
logger.Errorw("Cannot initialize client TCP connection", "error", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,10 +66,12 @@ func (p *Proxy) accept(conn net.Conn) {
|
|||||||
defer clientConn.Close()
|
defer clientConn.Close()
|
||||||
|
|
||||||
clientProtocol := p.ClientProtocolMaker()
|
clientProtocol := p.ClientProtocolMaker()
|
||||||
clientConn, err := clientProtocol.Handshake(clientConn)
|
|
||||||
|
|
||||||
|
clientConn, err := clientProtocol.Handshake(clientConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
stats.Stats.AuthenticationFailed()
|
||||||
logger.Warnw("Cannot perform client handshake", "error", err)
|
logger.Warnw("Cannot perform client handshake", "error", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +90,7 @@ func (p *Proxy) accept(conn net.Conn) {
|
|||||||
|
|
||||||
err = nil
|
err = nil
|
||||||
|
|
||||||
if len(config.C.AdTag) > 0 {
|
if config.C.MiddleProxyMode() {
|
||||||
middleConnection(req)
|
middleConnection(req)
|
||||||
} else {
|
} else {
|
||||||
err = directConnection(req)
|
err = directConnection(req)
|
||||||
|
|||||||
@@ -11,48 +11,58 @@
|
|||||||
# export MTG_IMAGENAME="nineseconds/mtg:latest"
|
# export MTG_IMAGENAME="nineseconds/mtg:latest"
|
||||||
# curl -sfL --compressed https://raw.githubusercontent.com/9seconds/mtg/master/run.sh | bash
|
# curl -sfL --compressed https://raw.githubusercontent.com/9seconds/mtg/master/run.sh | bash
|
||||||
|
|
||||||
set -eu -o pipefail
|
set -eu
|
||||||
|
|
||||||
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
export MTG_CONFIG="${MTG_CONFIG:-$XDG_CONFIG_HOME/mtg}"
|
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
|
mkdir -p "$MTG_CONFIG" || true
|
||||||
|
|
||||||
MTG_SECRET="$MTG_CONFIG/secret"
|
MTG_SECRET="$MTG_CONFIG/secret"
|
||||||
MTG_ENV="$MTG_CONFIG/env"
|
MTG_ENV="$MTG_CONFIG/env"
|
||||||
|
|
||||||
if [ ! -f "$MTG_ENV" ]; then
|
if [ ! -f "$MTG_ENV" ]; then
|
||||||
MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:latest}"
|
MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:stable}"
|
||||||
MTG_PORT="${MTG_PORT:-3128}"
|
MTG_PORT="${MTG_PORT:-3128}"
|
||||||
MTG_CONTAINER="${MTG_CONTAINER:-mtg}"
|
MTG_CONTAINER="${MTG_CONTAINER:-mtg}"
|
||||||
|
|
||||||
echo "MTG_IMAGENAME=${MTG_IMAGENAME}" > "$MTG_ENV"
|
echo "MTG_IMAGENAME=$MTG_IMAGENAME" > "$MTG_ENV"
|
||||||
echo "MTG_PORT=${MTG_PORT}" >> "$MTG_ENV"
|
echo "MTG_PORT=$MTG_PORT" >> "$MTG_ENV"
|
||||||
echo "MTG_CONTAINER=${MTG_CONTAINER}" >> "$MTG_ENV"
|
echo "MTG_CONTAINER=$MTG_CONTAINER" >> "$MTG_ENV"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
source "$MTG_ENV"
|
source "$MTG_ENV"
|
||||||
set +a
|
set +a
|
||||||
|
|
||||||
docker pull "$MTG_IMAGENAME"
|
$DOCKER_CMD pull "$MTG_IMAGENAME" > /dev/null
|
||||||
if [ ! -f "$MTG_SECRET" ]; then
|
if [ ! -f "$MTG_SECRET" ]; then
|
||||||
docker run \
|
$DOCKER_CMD run \
|
||||||
--rm \
|
--rm \
|
||||||
"$MTG_IMAGENAME" \
|
"$MTG_IMAGENAME" \
|
||||||
generate-secret tls -c "$(openssl rand -hex 16).com" \
|
generate-secret tls -c "$(openssl rand -hex 16).com" \
|
||||||
> "$MTG_SECRET"
|
> "$MTG_SECRET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Proxy secret is $(cat "$MTG_SECRET"). Port is $MTG_PORT."
|
echo "Proxy secret is $(cat "$MTG_SECRET"). Port is $MTG_PORT."
|
||||||
echo
|
|
||||||
|
|
||||||
docker ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r docker rm -fv
|
$DOCKER_CMD ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r $DOCKER_CMD rm -fv > /dev/null
|
||||||
docker run \
|
$DOCKER_CMD run \
|
||||||
-d \
|
-d \
|
||||||
--restart=unless-stopped \
|
--restart=unless-stopped \
|
||||||
--name "$MTG_CONTAINER" \
|
--name "$MTG_CONTAINER" \
|
||||||
--ulimit nofile=51200:51200 \
|
--ulimit nofile=51200:51200 \
|
||||||
-p "$MTG_PORT:3128" \
|
-p "$MTG_PORT:3128" \
|
||||||
"$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")"
|
"$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")" > /dev/null
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ type ReplayDetectedInterface interface {
|
|||||||
ReplayDetected()
|
ReplayDetected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthenticationFailedInterface interface {
|
||||||
|
AuthenticationFailed()
|
||||||
|
}
|
||||||
|
|
||||||
|
type CloakedRequestInterface interface {
|
||||||
|
CloakedRequest()
|
||||||
|
}
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
IngressTrafficInterface
|
IngressTrafficInterface
|
||||||
EgressTrafficInterface
|
EgressTrafficInterface
|
||||||
@@ -47,4 +55,6 @@ type Interface interface {
|
|||||||
TelegramDisconnectedInterface
|
TelegramDisconnectedInterface
|
||||||
CrashInterface
|
CrashInterface
|
||||||
ReplayDetectedInterface
|
ReplayDetectedInterface
|
||||||
|
AuthenticationFailedInterface
|
||||||
|
CloakedRequestInterface
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,3 +55,15 @@ func (m multiStats) ReplayDetected() {
|
|||||||
go m[i].ReplayDetected()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,19 +5,20 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type statsPrometheus struct {
|
type statsPrometheus struct {
|
||||||
connections *prometheus.GaugeVec
|
connections *prometheus.GaugeVec
|
||||||
telegramConnections *prometheus.GaugeVec
|
telegramConnections *prometheus.GaugeVec
|
||||||
traffic *prometheus.GaugeVec
|
traffic *prometheus.GaugeVec
|
||||||
crashes prometheus.Counter
|
crashes prometheus.Counter
|
||||||
replayAttacks prometheus.Counter
|
replayAttacks prometheus.Counter
|
||||||
|
authenticationFailed prometheus.Counter
|
||||||
|
cloakedRequests prometheus.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statsPrometheus) IngressTraffic(traffic int) {
|
func (s *statsPrometheus) IngressTraffic(traffic int) {
|
||||||
@@ -49,10 +50,14 @@ func (s *statsPrometheus) changeConnections(connectionType conntypes.ConnectionT
|
|||||||
labels[0] = "abridged"
|
labels[0] = "abridged"
|
||||||
case conntypes.ConnectionTypeSecure:
|
case conntypes.ConnectionTypeSecure:
|
||||||
labels[0] = "secured"
|
labels[0] = "secured"
|
||||||
|
case conntypes.ConnectionTypeIntermediate:
|
||||||
|
labels[0] = "intermediate"
|
||||||
|
case conntypes.ConnectionTypeUnknown:
|
||||||
|
panic("unknown connection type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr.IP.To4() == nil {
|
if addr.IP.To4() == nil {
|
||||||
labels[1] = "ipv6" // nolint: goconst
|
labels[1] = "ipv6"
|
||||||
}
|
}
|
||||||
|
|
||||||
s.connections.WithLabelValues(labels[:]...).Add(increment)
|
s.connections.WithLabelValues(labels[:]...).Add(increment)
|
||||||
@@ -87,6 +92,14 @@ func (s *statsPrometheus) ReplayDetected() {
|
|||||||
s.replayAttacks.Inc()
|
s.replayAttacks.Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *statsPrometheus) AuthenticationFailed() {
|
||||||
|
s.authenticationFailed.Inc()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *statsPrometheus) CloakedRequest() {
|
||||||
|
s.cloakedRequests.Inc()
|
||||||
|
}
|
||||||
|
|
||||||
func newStatsPrometheus(mux *http.ServeMux) Interface {
|
func newStatsPrometheus(mux *http.ServeMux) Interface {
|
||||||
registry := prometheus.NewPedanticRegistry()
|
registry := prometheus.NewPedanticRegistry()
|
||||||
|
|
||||||
@@ -116,6 +129,16 @@ func newStatsPrometheus(mux *http.ServeMux) Interface {
|
|||||||
Name: "replay_attacks",
|
Name: "replay_attacks",
|
||||||
Help: "How many replay attacks were prevented.",
|
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.connections)
|
||||||
@@ -123,6 +146,8 @@ func newStatsPrometheus(mux *http.ServeMux) Interface {
|
|||||||
registry.MustRegister(instance.traffic)
|
registry.MustRegister(instance.traffic)
|
||||||
registry.MustRegister(instance.crashes)
|
registry.MustRegister(instance.crashes)
|
||||||
registry.MustRegister(instance.replayAttacks)
|
registry.MustRegister(instance.replayAttacks)
|
||||||
|
registry.MustRegister(instance.authenticationFailed)
|
||||||
|
registry.MustRegister(instance.cloakedRequests)
|
||||||
|
|
||||||
handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
|
handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
|
||||||
mux.Handle("/", handler)
|
mux.Handle("/", handler)
|
||||||
|
|||||||
+13
-4
@@ -8,11 +8,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
statsd "github.com/smira/go-statsd"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
statsd "github.com/smira/go-statsd"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -91,8 +90,10 @@ func (s *statsStatsd) changeConnections(connectionType conntypes.ConnectionType,
|
|||||||
tags = append(tags, tagConnectionTypeAbridged)
|
tags = append(tags, tagConnectionTypeAbridged)
|
||||||
case conntypes.ConnectionTypeIntermediate:
|
case conntypes.ConnectionTypeIntermediate:
|
||||||
tags = append(tags, tagConnectionTypeIntermediate)
|
tags = append(tags, tagConnectionTypeIntermediate)
|
||||||
default:
|
case conntypes.ConnectionTypeSecure:
|
||||||
tags = append(tags, tagConnectionTypeSecured)
|
tags = append(tags, tagConnectionTypeSecured)
|
||||||
|
case conntypes.ConnectionTypeUnknown:
|
||||||
|
panic("Unknown connection type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr.IP.To4() == nil {
|
if addr.IP.To4() == nil {
|
||||||
@@ -137,6 +138,14 @@ func (s *statsStatsd) ReplayDetected() {
|
|||||||
s.gauge("replay_attacks", 1)
|
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) {
|
func (s *statsStatsd) gauge(metric string, value int64, tags ...*statsStatsdTag) {
|
||||||
key, tagList := s.prepareVals(metric, tags)
|
key, tagList := s.prepareVals(metric, tags)
|
||||||
s.initGauge(metric, key, tagList)
|
s.initGauge(metric, key, tagList)
|
||||||
|
|||||||
+5
-1
@@ -1,6 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -18,7 +19,10 @@ var httpClient = http.Client{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func request(url string) (io.ReadCloser, error) {
|
func request(url string) (io.ReadCloser, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
ctx, cancel := context.WithTimeout(context.Background(), apiHTTPTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-15
@@ -1,21 +1,24 @@
|
|||||||
package telegram
|
package telegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
"github.com/9seconds/mtg/wrappers/stream"
|
"github.com/9seconds/mtg/wrappers/stream"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type baseTelegram struct {
|
type baseTelegram struct {
|
||||||
dialer net.Dialer
|
dialer net.Dialer
|
||||||
|
logger *zap.SugaredLogger
|
||||||
|
|
||||||
secret []byte
|
secret []byte
|
||||||
v4DefaultDC conntypes.DC
|
v4DefaultDC conntypes.DC
|
||||||
V6DefaultDC conntypes.DC
|
v6DefaultDC conntypes.DC
|
||||||
v4Addresses map[conntypes.DC][]string
|
v4Addresses map[conntypes.DC][]string
|
||||||
v6Addresses map[conntypes.DC][]string
|
v6Addresses map[conntypes.DC][]string
|
||||||
}
|
}
|
||||||
@@ -26,25 +29,48 @@ func (b *baseTelegram) Secret() []byte {
|
|||||||
|
|
||||||
func (b *baseTelegram) dial(dc conntypes.DC,
|
func (b *baseTelegram) dial(dc conntypes.DC,
|
||||||
protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) {
|
protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) {
|
||||||
addr := ""
|
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)
|
||||||
|
|
||||||
switch protocol {
|
continue
|
||||||
case conntypes.ConnectionProtocolIPv4:
|
}
|
||||||
addr = b.chooseAddress(b.v4Addresses, dc, b.v4DefaultDC)
|
|
||||||
default:
|
if err := utils.InitTCP(conn, config.C.ProxyReadBuffer(), config.C.ProxyWriteBuffer()); err != nil {
|
||||||
addr = b.chooseAddress(b.v6Addresses, dc, b.V6DefaultDC)
|
b.logger.Infow("Cannot initialize TCP socket", "address", addr, "error", err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.NewTelegramConn(dc, conn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := b.dialer.Dial("tcp", addr)
|
return nil, errors.New("cannot dial to the chosen DC")
|
||||||
if err != nil {
|
}
|
||||||
return nil, fmt.Errorf("dial has failed: %w", err)
|
|
||||||
|
func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.ConnectionProtocol) []string {
|
||||||
|
addresses := make([]string, 0, 2)
|
||||||
|
protos := []conntypes.ConnectionProtocol{
|
||||||
|
conntypes.ConnectionProtocolIPv6,
|
||||||
|
conntypes.ConnectionProtocolIPv4,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.InitTCP(conn); err != nil {
|
if config.C.PreferIP == config.PreferIPv4 {
|
||||||
return nil, fmt.Errorf("cannot initialize tcp socket: %w", err)
|
protos[0], protos[1] = protos[1], protos[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream.NewTelegramConn(dc, conn), nil
|
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,
|
func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,
|
||||||
@@ -58,7 +84,7 @@ func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,
|
|||||||
case len(addrs) == 1:
|
case len(addrs) == 1:
|
||||||
return addrs[0]
|
return addrs[0]
|
||||||
case len(addrs) > 1:
|
case len(addrs) > 1:
|
||||||
return addrs[rand.Intn(len(addrs))]
|
return addrs[rand.Intn(len(addrs))] // nolint: gosec
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
+1
-1
@@ -37,5 +37,5 @@ func (d *directTelegram) Dial(dc conntypes.DC,
|
|||||||
dc = conntypes.DCDefaultIdx
|
dc = conntypes.DCDefaultIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.baseTelegram.dial(dc-1, protocol)
|
return d.baseTelegram.dial(dc-1, conntypes.ConnectionProtocolAny)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -4,6 +4,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const telegramDialTimeout = 10 * time.Second
|
const telegramDialTimeout = 10 * time.Second
|
||||||
@@ -17,11 +19,14 @@ var (
|
|||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
initOnce.Do(func() {
|
initOnce.Do(func() {
|
||||||
|
logger := zap.S().Named("telegram")
|
||||||
|
|
||||||
Direct = &directTelegram{
|
Direct = &directTelegram{
|
||||||
baseTelegram: baseTelegram{
|
baseTelegram: baseTelegram{
|
||||||
dialer: net.Dialer{Timeout: telegramDialTimeout},
|
dialer: net.Dialer{Timeout: telegramDialTimeout},
|
||||||
|
logger: logger.Named("direct"),
|
||||||
v4DefaultDC: directV4DefaultIdx,
|
v4DefaultDC: directV4DefaultIdx,
|
||||||
V6DefaultDC: directV6DefaultIdx,
|
v6DefaultDC: directV6DefaultIdx,
|
||||||
v4Addresses: directV4Addresses,
|
v4Addresses: directV4Addresses,
|
||||||
v6Addresses: directV6Addresses,
|
v6Addresses: directV6Addresses,
|
||||||
},
|
},
|
||||||
@@ -30,6 +35,7 @@ func Init() {
|
|||||||
tg := &middleTelegram{
|
tg := &middleTelegram{
|
||||||
baseTelegram: baseTelegram{
|
baseTelegram: baseTelegram{
|
||||||
dialer: net.Dialer{Timeout: telegramDialTimeout},
|
dialer: net.Dialer{Timeout: telegramDialTimeout},
|
||||||
|
logger: logger.Named("middle"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := tg.update(); err != nil {
|
if err := tg.update(); err != nil {
|
||||||
|
|||||||
+2
-3
@@ -5,10 +5,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/telegram/api"
|
"github.com/9seconds/mtg/telegram/api"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const middleTelegramBackgroundUpdateEvery = time.Hour
|
const middleTelegramBackgroundUpdateEvery = time.Hour
|
||||||
@@ -45,7 +44,7 @@ func (m *middleTelegram) update() error {
|
|||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
m.secret = secret
|
m.secret = secret
|
||||||
m.v4DefaultDC = v4DefaultDC
|
m.v4DefaultDC = v4DefaultDC
|
||||||
m.V6DefaultDC = v6DefaultDC
|
m.v6DefaultDC = v6DefaultDC
|
||||||
m.v4Addresses = v4Addresses
|
m.v4Addresses = v4Addresses
|
||||||
m.v6Addresses = v6Addresses
|
m.v6Addresses = v6Addresses
|
||||||
m.mutex.Unlock()
|
m.mutex.Unlock()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (c ClientHello) Digest() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mac := hmac.New(sha256.New, config.C.Secret)
|
mac := hmac.New(sha256.New, config.C.Secret)
|
||||||
mac.Write(rec.Bytes()) // nolint: errcheck
|
rec.WriteBytes(mac)
|
||||||
computedDigest := mac.Sum(nil)
|
computedDigest := mac.Sum(nil)
|
||||||
|
|
||||||
for i := range computedDigest {
|
for i := range computedDigest {
|
||||||
|
|||||||
+20
-9
@@ -1,5 +1,7 @@
|
|||||||
package tlstypes
|
package tlstypes
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
type RecordType uint8
|
type RecordType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -18,9 +20,9 @@ const (
|
|||||||
type CipherSuiteType uint8
|
type CipherSuiteType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CipherSuiteType_TLS_AES_128_GCM_SHA256 CipherSuiteType = iota // nolint: stylecheck, golint
|
CipherSuiteType_TLS_AES_128_GCM_SHA256 CipherSuiteType = iota // nolint: stylecheck,golint
|
||||||
CipherSuiteType_TLS_AES_256_GCM_SHA384 // nolint: stylecheck, golint
|
CipherSuiteType_TLS_AES_256_GCM_SHA384 // nolint: stylecheck,golint
|
||||||
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256 // nolint: stylecheck, golint
|
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256 // nolint: stylecheck,golint
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c CipherSuiteType) Bytes() []byte {
|
func (c CipherSuiteType) Bytes() []byte {
|
||||||
@@ -29,6 +31,8 @@ func (c CipherSuiteType) Bytes() []byte {
|
|||||||
return CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes
|
return CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes
|
||||||
case CipherSuiteType_TLS_AES_256_GCM_SHA384:
|
case CipherSuiteType_TLS_AES_256_GCM_SHA384:
|
||||||
return CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes
|
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
|
return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes
|
||||||
@@ -44,6 +48,8 @@ func (v Version) Bytes() []byte {
|
|||||||
return Version12Bytes
|
return Version12Bytes
|
||||||
case Version11:
|
case Version11:
|
||||||
return Version11Bytes
|
return Version11Bytes
|
||||||
|
case Version10, VersionUnknown:
|
||||||
|
return Version10Bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
return Version10Bytes
|
return Version10Bytes
|
||||||
@@ -63,17 +69,22 @@ var (
|
|||||||
Version12Bytes = []byte{0x03, 0x03}
|
Version12Bytes = []byte{0x03, 0x03}
|
||||||
Version13Bytes = []byte{0x03, 0x04}
|
Version13Bytes = []byte{0x03, 0x04}
|
||||||
|
|
||||||
CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes = []byte{0x13, 0x01} // nolint: stylecheck, golint
|
CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes = []byte{0x13, 0x01} // nolint: stylecheck,golint
|
||||||
CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes = []byte{0x13, 0x02} // nolint: stylecheck, golint
|
CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes = []byte{0x13, 0x02} // nolint: stylecheck,golint
|
||||||
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes = []byte{0x13, 0x03} // nolint; stylecheck, golint
|
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes = []byte{0x13, 0x03} // nolint: stylecheck,golint
|
||||||
)
|
)
|
||||||
|
|
||||||
type Byter interface {
|
type Byter interface {
|
||||||
Bytes() []byte
|
WriteBytes(io.Writer)
|
||||||
|
Len() int
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawBytes []byte
|
type RawBytes []byte
|
||||||
|
|
||||||
func (r RawBytes) Bytes() []byte {
|
func (r RawBytes) WriteBytes(writer io.Writer) {
|
||||||
return []byte(r)
|
writer.Write(r) // nolint: errcheck
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r RawBytes) Len() int {
|
||||||
|
return len(r)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-7
@@ -2,6 +2,7 @@ package tlstypes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
)
|
)
|
||||||
@@ -14,24 +15,29 @@ type Handshake struct {
|
|||||||
Tail Byter
|
Tail Byter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handshake) Bytes() []byte {
|
func (h *Handshake) WriteBytes(writer io.Writer) {
|
||||||
buf := bytes.Buffer{}
|
|
||||||
packetBuf := bytes.Buffer{}
|
packetBuf := bytes.Buffer{}
|
||||||
|
|
||||||
buf.WriteByte(byte(h.Type))
|
writer.Write([]byte{byte(h.Type)}) // nolint: errcheck
|
||||||
|
|
||||||
packetBuf.Write(h.Version.Bytes())
|
packetBuf.Write(h.Version.Bytes())
|
||||||
packetBuf.Write(h.Random[:])
|
packetBuf.Write(h.Random[:])
|
||||||
packetBuf.WriteByte(byte(len(h.SessionID)))
|
packetBuf.WriteByte(byte(len(h.SessionID)))
|
||||||
packetBuf.Write(h.SessionID)
|
packetBuf.Write(h.SessionID)
|
||||||
packetBuf.Write(h.Tail.Bytes())
|
h.Tail.WriteBytes(&packetBuf)
|
||||||
|
|
||||||
sizeUint24 := utils.ToUint24(uint32(packetBuf.Len()))
|
sizeUint24 := utils.ToUint24(uint32(packetBuf.Len()))
|
||||||
sizeUint24Bytes := sizeUint24[:]
|
sizeUint24Bytes := sizeUint24[:]
|
||||||
sizeUint24Bytes[0], sizeUint24Bytes[2] = sizeUint24Bytes[2], sizeUint24Bytes[0]
|
sizeUint24Bytes[0], sizeUint24Bytes[2] = sizeUint24Bytes[2], sizeUint24Bytes[0]
|
||||||
|
|
||||||
buf.Write(sizeUint24Bytes)
|
writer.Write(sizeUint24Bytes) // nolint: errcheck
|
||||||
packetBuf.WriteTo(&buf) // nolint: errcheck
|
packetBuf.WriteTo(writer) // nolint: errcheck
|
||||||
|
}
|
||||||
|
|
||||||
return buf.Bytes()
|
func (h *Handshake) Len() int {
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
|
h.WriteBytes(&buf)
|
||||||
|
|
||||||
|
return buf.Len()
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-9
@@ -15,16 +15,15 @@ type Record struct {
|
|||||||
Data Byter
|
Data Byter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Record) Bytes() []byte {
|
func (r Record) WriteBytes(writer io.Writer) {
|
||||||
buf := bytes.Buffer{}
|
writer.Write([]byte{byte(r.Type)}) // nolint: errcheck
|
||||||
data := r.Data.Bytes()
|
writer.Write(r.Version.Bytes()) // nolint: errcheck
|
||||||
|
binary.Write(writer, binary.BigEndian, uint16(r.Data.Len())) // nolint: errcheck
|
||||||
|
r.Data.WriteBytes(writer)
|
||||||
|
}
|
||||||
|
|
||||||
buf.WriteByte(byte(r.Type))
|
func (r Record) Len() int {
|
||||||
buf.Write(r.Version.Bytes())
|
return 1 + 2 + 2 + r.Data.Len()
|
||||||
binary.Write(&buf, binary.BigEndian, uint16(len(data))) // nolint: errcheck
|
|
||||||
buf.Write(data)
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadRecord(reader io.Reader) (Record, error) {
|
func ReadRecord(reader io.Reader) (Record, error) {
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServerHello struct {
|
type ServerHello struct {
|
||||||
@@ -20,30 +19,33 @@ type ServerHello struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s ServerHello) WelcomePacket() []byte {
|
func (s ServerHello) WelcomePacket() []byte {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
s.Random = [32]byte{}
|
s.Random = [32]byte{}
|
||||||
rec := Record{
|
rec := Record{
|
||||||
Type: RecordTypeHandshake,
|
Type: RecordTypeHandshake,
|
||||||
Version: Version12,
|
Version: Version12,
|
||||||
Data: &s,
|
Data: &s,
|
||||||
}
|
}
|
||||||
buf := bytes.NewBuffer(rec.Bytes())
|
rec.WriteBytes(buf)
|
||||||
|
|
||||||
recChangeCipher := Record{
|
recChangeCipher := Record{
|
||||||
Type: RecordTypeChangeCipherSpec,
|
Type: RecordTypeChangeCipherSpec,
|
||||||
Version: Version12,
|
Version: Version12,
|
||||||
Data: RawBytes([]byte{0x01}),
|
Data: RawBytes([]byte{0x01}),
|
||||||
}
|
}
|
||||||
buf.Write(recChangeCipher.Bytes())
|
recChangeCipher.WriteBytes(buf)
|
||||||
|
|
||||||
hostCert := make([]byte, 1024+mrand.Intn(3092))
|
hostCert := make([]byte, 1024+mrand.Intn(3092)) // nolint: gosec
|
||||||
rand.Read(hostCert) // nolint: errcheck
|
rand.Read(hostCert) // nolint: errcheck
|
||||||
|
|
||||||
recData := Record{
|
recData := Record{
|
||||||
Type: RecordTypeApplicationData,
|
Type: RecordTypeApplicationData,
|
||||||
Version: Version12,
|
Version: Version12,
|
||||||
Data: RawBytes(hostCert),
|
Data: RawBytes(hostCert),
|
||||||
}
|
}
|
||||||
buf.Write(recData.Bytes())
|
recData.WriteBytes(buf)
|
||||||
|
|
||||||
packet := buf.Bytes()
|
packet := buf.Bytes()
|
||||||
|
|
||||||
mac := hmac.New(sha256.New, config.C.Secret)
|
mac := hmac.New(sha256.New, config.C.Secret)
|
||||||
|
|||||||
+7
-5
@@ -3,24 +3,26 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitTCP(conn net.Conn) error {
|
func InitTCP(conn net.Conn, readBufferSize int, writeBufferSize int) error {
|
||||||
tcpConn := conn.(*net.TCPConn)
|
tcpConn := conn.(*net.TCPConn)
|
||||||
|
|
||||||
if err := tcpConn.SetNoDelay(true); err != nil {
|
if err := tcpConn.SetNoDelay(true); err != nil {
|
||||||
return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err)
|
return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetReadBuffer(config.C.ReadBuffer); err != nil {
|
if err := tcpConn.SetReadBuffer(readBufferSize); err != nil {
|
||||||
return fmt.Errorf("cannot set read buffer size: %w", err)
|
return fmt.Errorf("cannot set read buffer size: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetWriteBuffer(config.C.WriteBuffer); err != nil {
|
if err := tcpConn.SetWriteBuffer(writeBufferSize); err != nil {
|
||||||
return fmt.Errorf("cannot set write buffer size: %w", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MakeStreamCipher(key, iv []byte) cipher.Stream {
|
func MakeStreamCipher(key, iv []byte) cipher.Stream {
|
||||||
block, _ := aes.NewCipher(key) // nolint: gosec
|
block, _ := aes.NewCipher(key)
|
||||||
|
|
||||||
return cipher.NewCTR(block, iv)
|
return cipher.NewCTR(block, iv)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -43,6 +42,7 @@ type wrapperMtprotoFrame struct {
|
|||||||
|
|
||||||
func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen
|
func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
sum := crc32.NewIEEE()
|
sum := crc32.NewIEEE()
|
||||||
writer := io.MultiWriter(buf, sum)
|
writer := io.MultiWriter(buf, sum)
|
||||||
|
|
||||||
@@ -71,7 +71,6 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
buf.Grow(int(messageLength) - 4 - 4)
|
|
||||||
|
|
||||||
if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil {
|
if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil {
|
||||||
return nil, fmt.Errorf("cannot read the message frame: %w", err)
|
return nil, fmt.Errorf("cannot read the message frame: %w", err)
|
||||||
@@ -85,7 +84,7 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
|
|||||||
return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo)
|
return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, _ := ioutil.ReadAll(buf) // nolint: gosec
|
data, _ := ioutil.ReadAll(buf)
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
// write to buf, not to writer. This is because we are going to fetch
|
// write to buf, not to writer. This is because we are going to fetch
|
||||||
// crc32 checksum.
|
// crc32 checksum.
|
||||||
@@ -114,7 +113,6 @@ func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error {
|
|||||||
paddingLength := (aes.BlockSize - messageLength%aes.BlockSize) % aes.BlockSize
|
paddingLength := (aes.BlockSize - messageLength%aes.BlockSize) % aes.BlockSize
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
buf.Grow(messageLength + paddingLength)
|
|
||||||
|
|
||||||
binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck
|
binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck
|
||||||
binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck
|
binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const clientIntermediateQuickAckLength = 0x80000000
|
const clientIntermediateQuickAckLength = 0x80000000
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperClientIntermediateSecure struct {
|
type wrapperClientIntermediateSecure struct {
|
||||||
@@ -35,11 +34,12 @@ func (w *wrapperClientIntermediateSecure) Write(packet conntypes.Packet, acks *c
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
paddingLength := rand.Intn(4)
|
paddingLength := rand.Intn(4) // nolint: gosec
|
||||||
|
|
||||||
buf.Grow(4 + len(packet) + paddingLength)
|
buf.Grow(4 + len(packet) + paddingLength)
|
||||||
|
|
||||||
binary.Write(&buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck
|
binary.Write(buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck
|
||||||
buf.Write(packet)
|
buf.Write(packet)
|
||||||
buf.Write(make([]byte, paddingLength))
|
buf.Write(make([]byte, paddingLength))
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ type wrapperProxy struct {
|
|||||||
|
|
||||||
func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
|
func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
flags := w.flags
|
flags := w.flags
|
||||||
|
|
||||||
if acks.Quick {
|
if acks.Quick {
|
||||||
flags |= rpc.ProxyRequestFlagsQuickAck
|
flags |= rpc.ProxyRequestFlagsQuickAck
|
||||||
}
|
}
|
||||||
@@ -43,6 +43,7 @@ func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.Connection
|
|||||||
buf.WriteByte(byte(len(config.C.AdTag)))
|
buf.WriteByte(byte(len(config.C.AdTag)))
|
||||||
buf.Write(config.C.AdTag)
|
buf.Write(config.C.AdTag)
|
||||||
buf.Write(make([]byte, (4-buf.Len()%4)%4))
|
buf.Write(make([]byte, (4-buf.Len()%4)%4))
|
||||||
|
buf.Grow(len(packet))
|
||||||
buf.Write(packet)
|
buf.Write(packet)
|
||||||
|
|
||||||
return w.proxy.Write(buf.Bytes())
|
return w.proxy.Write(buf.Bytes())
|
||||||
@@ -63,6 +64,7 @@ func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, e
|
|||||||
|
|
||||||
func (w *wrapperProxy) Close() error {
|
func (w *wrapperProxy) Close() error {
|
||||||
w.proxy.Close()
|
w.proxy.Close()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@ func NewProxy(request *protocol.TelegramRequest) (conntypes.PacketAckReadWriteCl
|
|||||||
flags |= rpc.ProxyRequestFlagsIntermediate
|
flags |= rpc.ProxyRequestFlagsIntermediate
|
||||||
case conntypes.ConnectionTypeSecure:
|
case conntypes.ConnectionTypeSecure:
|
||||||
flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
|
flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
|
||||||
default:
|
case conntypes.ConnectionTypeUnknown:
|
||||||
panic("unknown connection type")
|
panic("unknown connection type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/utils"
|
"github.com/9seconds/mtg/utils"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperBlockCipher struct {
|
type wrapperBlockCipher struct {
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/config"
|
"github.com/9seconds/mtg/config"
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type connPurpose uint8
|
type connPurpose uint8
|
||||||
@@ -29,6 +28,7 @@ type wrapperConn struct {
|
|||||||
func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
|
func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
|
||||||
if err := w.parent.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
|
if err := w.parent.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot set write deadline to the socket: %w", err)
|
return 0, fmt.Errorf("cannot set write deadline to the socket: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ func (w *wrapperConn) Write(p []byte) (int, error) {
|
|||||||
w.logger.Debugw("write to stream", "bytes", n, "error", err)
|
w.logger.Debugw("write to stream", "bytes", n, "error", err)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Close() // nolint: gosec
|
w.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, err
|
return n, err
|
||||||
@@ -49,6 +49,7 @@ func (w *wrapperConn) Write(p []byte) (int, error) {
|
|||||||
func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
|
func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
|
||||||
if err := w.parent.SetReadDeadline(time.Now().Add(timeout)); err != nil {
|
if err := w.parent.SetReadDeadline(time.Now().Add(timeout)); err != nil {
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot set read deadline to the socket: %w", err)
|
return 0, fmt.Errorf("cannot set read deadline to the socket: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ func (w *wrapperConn) Read(p []byte) (int, error) {
|
|||||||
|
|
||||||
func (w *wrapperConn) Close() error {
|
func (w *wrapperConn) Close() error {
|
||||||
w.logger.Debugw("Close connection")
|
w.logger.Debugw("Close connection")
|
||||||
|
|
||||||
return w.parent.Close()
|
return w.parent.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperCtx struct {
|
type wrapperCtx struct {
|
||||||
@@ -21,6 +20,7 @@ func (w *wrapperCtx) WriteTimeout(p []byte, timeout time.Duration) (int, error)
|
|||||||
select {
|
select {
|
||||||
case <-w.ctx.Done():
|
case <-w.ctx.Done():
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
||||||
default:
|
default:
|
||||||
return w.parent.WriteTimeout(p, timeout)
|
return w.parent.WriteTimeout(p, timeout)
|
||||||
@@ -31,6 +31,7 @@ func (w *wrapperCtx) Write(p []byte) (int, error) {
|
|||||||
select {
|
select {
|
||||||
case <-w.ctx.Done():
|
case <-w.ctx.Done():
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
||||||
default:
|
default:
|
||||||
return w.parent.Write(p)
|
return w.parent.Write(p)
|
||||||
@@ -41,6 +42,7 @@ func (w *wrapperCtx) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
|
|||||||
select {
|
select {
|
||||||
case <-w.ctx.Done():
|
case <-w.ctx.Done():
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
||||||
default:
|
default:
|
||||||
return w.parent.ReadTimeout(p, timeout)
|
return w.parent.ReadTimeout(p, timeout)
|
||||||
@@ -51,6 +53,7 @@ func (w *wrapperCtx) Read(p []byte) (int, error) {
|
|||||||
select {
|
select {
|
||||||
case <-w.ctx.Done():
|
case <-w.ctx.Done():
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
|
||||||
default:
|
default:
|
||||||
return w.parent.Read(p)
|
return w.parent.Read(p)
|
||||||
@@ -59,6 +62,7 @@ func (w *wrapperCtx) Read(p []byte) (int, error) {
|
|||||||
|
|
||||||
func (w *wrapperCtx) Close() error {
|
func (w *wrapperCtx) Close() error {
|
||||||
w.cancel()
|
w.cancel()
|
||||||
|
|
||||||
return w.parent.Close()
|
return w.parent.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/tlstypes"
|
"github.com/9seconds/mtg/tlstypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperFakeTLS struct {
|
type wrapperFakeTLS struct {
|
||||||
@@ -32,20 +32,25 @@ func (w *wrapperFakeTLS) WriteTimeout(p []byte, timeout time.Duration) (int, err
|
|||||||
if elapsed > timeout {
|
if elapsed > timeout {
|
||||||
return w.parent.WriteTimeout(b, timeout-elapsed)
|
return w.parent.WriteTimeout(b, timeout-elapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, errors.New("timeout")
|
return 0, errors.New("timeout")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
|
func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
|
||||||
sum := 0
|
sum := 0
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
for _, v := range tlstypes.MakeRecords(p) {
|
for _, v := range tlstypes.MakeRecords(p) {
|
||||||
_, err := writeFunc(v.Bytes())
|
buf.Reset()
|
||||||
|
v.WriteBytes(&buf)
|
||||||
|
|
||||||
|
_, err := writeFunc(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sum, err
|
return sum, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += len(v.Data.Bytes())
|
sum += v.Data.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum, nil
|
return sum, nil
|
||||||
@@ -86,7 +91,12 @@ func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWrit
|
|||||||
switch rec.Type {
|
switch rec.Type {
|
||||||
case tlstypes.RecordTypeChangeCipherSpec:
|
case tlstypes.RecordTypeChangeCipherSpec:
|
||||||
case tlstypes.RecordTypeApplicationData:
|
case tlstypes.RecordTypeApplicationData:
|
||||||
return rec.Data.Bytes(), nil
|
buf := &bytes.Buffer{}
|
||||||
|
rec.Data.WriteBytes(buf)
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
case tlstypes.RecordTypeHandshake:
|
||||||
|
return nil, errors.New("unsupported record type handshake")
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported record type %v", rec.Type)
|
return nil, fmt.Errorf("unsupported record type %v", rec.Type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/md5" // nolint: gosec
|
"crypto/md5"
|
||||||
"crypto/sha1" // nolint: gosec
|
"crypto/sha1"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
@@ -55,9 +55,10 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
|
|||||||
client, remote *net.TCPAddr,
|
client, remote *net.TCPAddr,
|
||||||
secret []byte) ([]byte, []byte) {
|
secret []byte) ([]byte, []byte) {
|
||||||
message := bytes.Buffer{}
|
message := bytes.Buffer{}
|
||||||
message.Write(resp.Nonce) // nolint: gosec
|
|
||||||
message.Write(req.Nonce) // nolint: gosec
|
message.Write(resp.Nonce)
|
||||||
message.Write(req.CryptoTS) // nolint: gosec
|
message.Write(req.Nonce)
|
||||||
|
message.Write(req.CryptoTS)
|
||||||
|
|
||||||
clientIPv4 := mtprotoEmptyIP[:]
|
clientIPv4 := mtprotoEmptyIP[:]
|
||||||
serverIPv4 := mtprotoEmptyIP[:]
|
serverIPv4 := mtprotoEmptyIP[:]
|
||||||
@@ -67,34 +68,34 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
|
|||||||
serverIPv4 = utils.ReverseBytes(remote.IP.To4())
|
serverIPv4 = utils.ReverseBytes(remote.IP.To4())
|
||||||
}
|
}
|
||||||
|
|
||||||
message.Write(serverIPv4) // nolint: gosec
|
message.Write(serverIPv4)
|
||||||
|
|
||||||
var port [2]byte
|
var port [2]byte
|
||||||
|
|
||||||
binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
|
binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
|
||||||
message.Write(port[:]) // nolint: gosec
|
message.Write(port[:])
|
||||||
|
|
||||||
switch purpose {
|
switch purpose {
|
||||||
case mtprotoCipherPurposeClient:
|
case mtprotoCipherPurposeClient:
|
||||||
message.WriteString("CLIENT") // nolint: gosec
|
message.WriteString("CLIENT")
|
||||||
case mtprotoCipherPurposeServer:
|
case mtprotoCipherPurposeServer:
|
||||||
message.WriteString("SERVER") // nolint: gosec
|
message.WriteString("SERVER")
|
||||||
default:
|
default:
|
||||||
panic("Unexpected cipher purpose")
|
panic("Unexpected cipher purpose")
|
||||||
}
|
}
|
||||||
|
|
||||||
message.Write(clientIPv4) // nolint: gosec
|
message.Write(clientIPv4)
|
||||||
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
|
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
|
||||||
message.Write(port[:]) // nolint: gosec
|
message.Write(port[:])
|
||||||
message.Write(secret) // nolint: gosec
|
message.Write(secret)
|
||||||
message.Write(resp.Nonce) // nolint: gosec
|
message.Write(resp.Nonce)
|
||||||
|
|
||||||
if client.IP.To4() == nil {
|
if client.IP.To4() == nil {
|
||||||
message.Write(client.IP.To16()) // nolint: gosec
|
message.Write(client.IP.To16())
|
||||||
message.Write(remote.IP.To16()) // nolint: gosec
|
message.Write(remote.IP.To16())
|
||||||
}
|
}
|
||||||
|
|
||||||
message.Write(req.Nonce) // nolint: gosec
|
message.Write(req.Nonce)
|
||||||
|
|
||||||
data := message.Bytes()
|
data := message.Bytes()
|
||||||
md5sum := md5.Sum(data[1:]) // nolint: gas
|
md5sum := md5.Sum(data[1:]) // nolint: gas
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperObfuscated2 struct {
|
type wrapperObfuscated2 struct {
|
||||||
@@ -40,16 +40,24 @@ func (w *wrapperObfuscated2) Read(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
|
func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
|
||||||
buf := make([]byte, len(p))
|
buffer := bytes.Buffer{}
|
||||||
copy(buf, p)
|
|
||||||
|
buffer.Write(p)
|
||||||
|
|
||||||
|
buf := buffer.Bytes()
|
||||||
|
|
||||||
w.encryptor.XORKeyStream(buf, buf)
|
w.encryptor.XORKeyStream(buf, buf)
|
||||||
|
|
||||||
return w.parent.WriteTimeout(buf, timeout)
|
return w.parent.WriteTimeout(buf, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
|
func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
|
||||||
buf := make([]byte, len(p))
|
buffer := bytes.Buffer{}
|
||||||
copy(buf, p)
|
|
||||||
|
buffer.Write(p)
|
||||||
|
|
||||||
|
buf := buffer.Bytes()
|
||||||
|
|
||||||
w.encryptor.XORKeyStream(buf, buf)
|
w.encryptor.XORKeyStream(buf, buf)
|
||||||
|
|
||||||
return w.parent.Write(buf)
|
return w.parent.Write(buf)
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReadWriteCloseRewinder interface {
|
type ReadWriteCloseRewinder interface {
|
||||||
@@ -88,6 +87,7 @@ func (w *wrapperRewind) RemoteAddr() *net.TCPAddr {
|
|||||||
|
|
||||||
func (w *wrapperRewind) Close() error {
|
func (w *wrapperRewind) Close() error {
|
||||||
w.buf.Reset()
|
w.buf.Reset()
|
||||||
|
|
||||||
return w.parent.Close()
|
return w.parent.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/stats"
|
"github.com/9seconds/mtg/stats"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperTelegramStats struct {
|
type wrapperTelegramStats struct {
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
"github.com/9seconds/mtg/stats"
|
"github.com/9seconds/mtg/stats"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrapperTrafficStats struct {
|
type wrapperTrafficStats struct {
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/conntypes"
|
"github.com/9seconds/mtg/conntypes"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
Reference in New Issue
Block a user