mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-02 00:11:56 +03:00
REPOSITORY / ScuroNeko/mtg
Compare commits
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1074193a8 | ||
|
|
78dea9ae3f | ||
|
|
da8dba1585 | ||
|
|
33852ca481 | ||
|
|
eff53694a0 | ||
|
|
74a7c505eb | ||
|
|
9983f7fcba | ||
|
|
a90072260e | ||
|
|
b153240bc3 | ||
|
|
6dfbd26524 | ||
|
|
39e7663e0c | ||
|
|
71f7bf6cad | ||
|
|
fba0e235c1 | ||
|
|
70be70de3c | ||
|
|
b565d83d40 | ||
|
|
ebc459440c | ||
|
|
6e6049a73a | ||
|
|
916714a909 | ||
|
|
f68b195306 | ||
|
|
5f1d1ce883 | ||
|
|
16558a7c55 | ||
|
|
e7958aaf33 | ||
|
|
7d6b661d97 | ||
|
|
28b3cbe91a | ||
|
|
6818364231 | ||
|
|
ea97bf51c8 | ||
|
|
1678ddbd53 | ||
|
|
f81f29cbb4 | ||
|
|
2d9259db48 | ||
|
|
c721c636d9 | ||
|
|
60472072aa | ||
|
|
6721e6fd9f | ||
|
|
47fb5c23cb | ||
|
|
fce6118c71 | ||
|
|
d277a2975a | ||
|
|
c3f21a7b0d |
@@ -10,3 +10,4 @@ format = "colored-line-number"
|
||||
|
||||
[linters]
|
||||
enable-all = true
|
||||
disable = ["gochecknoglobals"]
|
||||
|
||||
+1
-1
@@ -6,6 +6,7 @@ dist: trusty
|
||||
|
||||
go:
|
||||
- "1.11.x"
|
||||
- 1.12.x
|
||||
- master
|
||||
|
||||
before_script: make prepare
|
||||
@@ -13,7 +14,6 @@ before_script: make prepare
|
||||
script:
|
||||
- make all
|
||||
- make lint
|
||||
- make critic
|
||||
- make test
|
||||
|
||||
matrix:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
###############################################################################
|
||||
# BUILD STAGE
|
||||
|
||||
FROM golang:1.11-alpine
|
||||
FROM golang:1.12-alpine
|
||||
|
||||
RUN set -x \
|
||||
&& apk --no-cache --update add \
|
||||
|
||||
@@ -3,26 +3,28 @@ IMAGE_NAME := mtg
|
||||
APP_NAME := $(IMAGE_NAME)
|
||||
|
||||
CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}")
|
||||
APP_DEPS := version.go
|
||||
|
||||
GOLANGCI_LINT_VERSION := v1.10.2
|
||||
GOLANGCI_LINT_VERSION := v1.15.0
|
||||
|
||||
COMMON_BUILD_FLAGS := -ldflags="-s -w"
|
||||
VERSION_GO := $(shell go version)
|
||||
VERSION_DATE := $(shell date -Ru)
|
||||
VERSION_TAG := $(shell git describe --tags --always)
|
||||
COMMON_BUILD_FLAGS := -ldflags="-s -w -X 'main.version=$(VERSION_TAG) ($(VERSION_GO)) [$(VERSION_DATE)]'"
|
||||
|
||||
MOD_ON := env GO111MODULE=on
|
||||
MOD_OFF := env GO111MODULE=auto
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
$(APP_NAME): $(APP_DEPS)
|
||||
$(APP_NAME):
|
||||
@$(MOD_ON) go build $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
|
||||
|
||||
static-$(APP_NAME): $(APP_DEPS)
|
||||
static-$(APP_NAME):
|
||||
@$(MOD_ON) env CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
|
||||
|
||||
$(APP_NAME)-%: GOOS=$(shell echo -n "$@" | sed 's?$(APP_NAME)-??' | cut -f1 -d-)
|
||||
$(APP_NAME)-%: GOARCH=$(shell echo -n "$@" | sed 's?$(APP_NAME)-??' | cut -f2 -d-)
|
||||
$(APP_NAME)-%: $(APP_DEPS) ccbuilds
|
||||
$(APP_NAME)-%: ccbuilds
|
||||
@$(MOD_ON) env "GOOS=$(GOOS)" "GOARCH=$(GOARCH)" \
|
||||
go build \
|
||||
$(COMMON_BUILD_FLAGS) \
|
||||
@@ -31,9 +33,6 @@ $(APP_NAME)-%: $(APP_DEPS) ccbuilds
|
||||
ccbuilds:
|
||||
@rm -rf ./ccbuilds && mkdir -p ./ccbuilds
|
||||
|
||||
version.go:
|
||||
@$(MOD_ON) go generate main.go
|
||||
|
||||
vendor: go.mod go.sum
|
||||
@$(MOD_ON) go mod vendor
|
||||
|
||||
@@ -53,17 +52,13 @@ crosscompile-dir:
|
||||
@rm -rf "$(CC_DIR)" && mkdir -p "$(CC_DIR)"
|
||||
|
||||
.PHONY: test
|
||||
test: vendor $(APP_DEPS)
|
||||
test: vendor
|
||||
@$(MOD_ON) go test -v ./...
|
||||
|
||||
.PHONY: lint
|
||||
lint: vendor $(APP_DEPS)
|
||||
lint: vendor
|
||||
@$(MOD_OFF) golangci-lint run
|
||||
|
||||
.PHONY: critic
|
||||
critic: vendor $(APP_DEPS)
|
||||
@$(MOD_OFF) gocritic check-project "$(ROOT_DIR)"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@git clean -xfd && \
|
||||
@@ -75,13 +70,9 @@ docker:
|
||||
@docker build --pull -t "$(IMAGE_NAME)" "$(ROOT_DIR)"
|
||||
|
||||
.PHONY: prepare
|
||||
prepare: install-lint install-critic
|
||||
prepare: install-lint
|
||||
|
||||
.PHONY: install-lint
|
||||
install-lint:
|
||||
@curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \
|
||||
| $(MOD_OFF) bash -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
||||
|
||||
.PHONY: install-critic
|
||||
install-critic:
|
||||
@$(MOD_OFF) go get -u github.com/go-critic/go-critic/...
|
||||
|
||||
@@ -95,6 +95,11 @@ docker pull nineseconds/mtg:stable
|
||||
docker pull nineseconds/mtg:0.10
|
||||
```
|
||||
|
||||
# Ansible role
|
||||
|
||||
You can find unofficial Ansible role for mtg here: https://github.com/rlex/ansible-role-mtg
|
||||
Also, there is another project on Ansible Galaxy: https://galaxy.ansible.com/ivansible/lin_mtproxy
|
||||
|
||||
# Configuration
|
||||
|
||||
Basically, to run this tool you need to configure as less as possible.
|
||||
@@ -113,11 +118,58 @@ head -c 512 /dev/urandom | md5sum | cut -f 1 -d ' '
|
||||
|
||||
## Secure mode
|
||||
|
||||
If you want to support new secure mode, please prepend `dd` to the
|
||||
secret. For example, secret `cf18fa8ea0267057e2c61a5f7322a8e7` should
|
||||
be `ddcf18fa8ea0267057e2c61a5f7322a8e7`. But pay attention that some
|
||||
old clients won't support this mode. If this is not your case, I would
|
||||
suggest to go with this mode.
|
||||
_tl;dr - use secret mode for all new installation of proxy; only clients
|
||||
with dd-secrets will be able to connect. This mode abuses attempts to
|
||||
DPI MTPROTO traffic._
|
||||
|
||||
Secure mode is not the best name and of course, it creates a lot of
|
||||
confusion. To explain what it means, we need to tell you some bits on
|
||||
dd-secrets.
|
||||
|
||||
MTPROTO proxy protocol requires 16-byte secret. You usually
|
||||
propagate it as a 32 characters hexadecimal string like
|
||||
`282831900f371ca182feb0e4e1e1aeef` (if you decode this string
|
||||
to bytes, you will get a real secret which is used in the
|
||||
protocol). Everything went quite good until the moment when
|
||||
developers found an evidence that [protocol is quite weak to
|
||||
DPI](https://github.com/TelegramMessenger/MTProxy/issues/35) and some
|
||||
enthusiasts even created simple proofs of concepts on [detecting MTPROTO
|
||||
traffic](https://github.com/darkk/poormansmtproto).
|
||||
|
||||
Telegram team has introduced a patch called dd-secrets. If you have
|
||||
a secret `282831900f371ca182feb0e4e1e1aeef` then your dd-secret is
|
||||
`dd282831900f371ca182feb0e4e1e1aeef`. That is, you just add dd prefix
|
||||
to the secret, prepend it with dd. In that case, original secret
|
||||
`282831900f371ca182feb0e4e1e1aeef` is used but client and server start
|
||||
to act a little bit different: they start to add random noise to the
|
||||
packets so they can't be detected by their length. In order to keep
|
||||
backward compatibility, all proxies a quite liberal to the secrets to
|
||||
use: if the client uses plain secret, without dd prefix, they fall back
|
||||
to the normal behavior. If dd-secret is used (proxy can extract this
|
||||
information on the handshake), then more secured, the hardened behavior
|
||||
is used.
|
||||
|
||||
Yes, it can look like a hack but it is as it is.
|
||||
|
||||
Now going back to the secure mode: if you do not pass `-s` flag to the
|
||||
mtg, then it checks what mode is requested by the client. If the client
|
||||
uses plain secret, without dd prefix, then proxy falls back to the
|
||||
original behavior and do not play with paddings. If dd-secret is used
|
||||
and client demands this mode, then proxy start to add that random noise
|
||||
to the packets. But if you pass `-s`, then only clients with dd-secrets
|
||||
can connect. How to migrate existing clients then? If a client is new
|
||||
enough, you can just prepend the secret with dd string in the settings.
|
||||
If it is an old guy, then nothing to do, sorry.
|
||||
|
||||
Why this mode matters? We do not have evidence but there is quite a big
|
||||
suspicion that some ISPs start to filter MTPROTO traffic. If they detect
|
||||
the IP address which acts as a proxy, they block it and no clients can
|
||||
use this proxy. This is an attempt to prevent such a situation.
|
||||
|
||||
General rule of thumb: with all new installation of proxies I would
|
||||
advise to go with secure mode by default. But please do remember that it
|
||||
means that clients, which do not pass dd-prefix to their secrets, will
|
||||
not be able to connect. *Secure mode works only with dd-prefixes!*
|
||||
|
||||
Oneliners to generate such secrets:
|
||||
|
||||
@@ -131,9 +183,14 @@ or
|
||||
echo dd$(head -c 512 /dev/urandom | md5sum | cut -f 1 -d ' ')
|
||||
```
|
||||
|
||||
If you want to enforce the usage of secure mode, please pass `-s` or
|
||||
`--secure-only` flags. In that case, clients which do not use dd-secrets
|
||||
are going to be disconnected from the proxy.
|
||||
|
||||
## Antireplay cache
|
||||
|
||||
In order to prevent replay attacks, we have internal storage of first
|
||||
frames messages for connected clients. These frames are generated
|
||||
randomly by design and we have negligible possibility of duplication
|
||||
(probability is 1/(2^64)) but it could be quite effective in order to
|
||||
prevent replays.
|
||||
|
||||
|
||||
## Environment variables
|
||||
@@ -142,28 +199,30 @@ It is possible to configure this tool using environment variables. You
|
||||
can configure any flag but not secret or adtag. Here is the list of
|
||||
supported environment variables:
|
||||
|
||||
| Environment variable | Corresponding flags | Default value | Description |
|
||||
|--------------------------|------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `MTG_DEBUG` | `-d`, `--debug` | `false` | Run in debug mode. Usually, you need to run in this mode only if you develop this tool or its maintainer is asking you to provide logs with such verbosity. |
|
||||
| `MTG_VERBOSE` | `-v`, `--verbose` | `false` | Run in verbose mode. This is way less chatty than debug mode. |
|
||||
| `MTG_IP` | `-b`, `--bind-ip` | `127.0.0.1` | Which IP should we bind to. As usual, `0.0.0.0` means that we want to listen on all interfaces. Also, 4 zeroes will bind to both IPv4 and IPv6. |
|
||||
| `MTG_PORT` | `-p`, `--bind-port` | `3128` | Which port should we bind to (listen on). |
|
||||
| `MTG_IPV4` | `-4`, `--public-ipv4` | [Autodetect](https://ifconfig.co) | IPv4 address of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv4 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. |
|
||||
| `MTG_IPV4_PORT` | `--public-ipv4-port` | Value of `--bind-port` | Which port should be public of IPv4 interface. This affects only generated links and should be changed only if you NAT your proxy or run it in a docker container. |
|
||||
| `MTG_IPV6` | `-6`, `--public-ipv6` | [Autodetect](https://ifconfig.co) | IPv6 address of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv6 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. |
|
||||
| `MTG_IPV6_PORT` | `--public-ipv6-port` | Value of `--bind-port` | Which port should be public of IPv6 interface. This affects only generated links and should be changed only if you NAT your proxy or run it in a docker container. |
|
||||
| `MTG_STATS_IP` | `-t`, `--stats-ip` | `127.0.0.1` | Which IP should we bind the internal statistics HTTP server. |
|
||||
| `MTG_STATS_PORT` | `-q`, `--stats-port` | `3129` | Which port should we bind the internal statistics HTTP server. |
|
||||
| `MTG_STATSD_IP` | `--statsd-ip` | | IP/host addresses of statsd service. No defaults, by defaults we do not send anything there. |
|
||||
| `MTG_STATSD_PORT` | `--statsd-port` | `8125` | Which port should we use to work with statsd. |
|
||||
| `MTG_STATSD_NETWORK` | `--statsd-network` | `udp` | Which protocol should we use to work with statsd. Possible options are `udp` and `tcp`. |
|
||||
| `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` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. |
|
||||
| `MTG_PROMETHEUS_PREFIX` | `--prometheus-prefix` | `mtg` | Which namespace should be used for prometheus metrics. |
|
||||
| `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_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_SECURE_ONLY` | `-s`, `--secure-only` | `false` | Support only clients with secure mode (i.e only clients with dd-secrets). |
|
||||
| Environment variable | Corresponding flags | Default value | Description |
|
||||
|-------------------------------|-----------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `MTG_DEBUG` | `-d`, `--debug` | `false` | Run in debug mode. Usually, you need to run in this mode only if you develop this tool or its maintainer is asking you to provide logs with such verbosity. |
|
||||
| `MTG_VERBOSE` | `-v`, `--verbose` | `false` | Run in verbose mode. This is way less chatty than debug mode. |
|
||||
| `MTG_IP` | `-b`, `--bind-ip` | `127.0.0.1` | Which IP should we bind to. As usual, `0.0.0.0` means that we want to listen on all interfaces. Also, 4 zeroes will bind to both IPv4 and IPv6. |
|
||||
| `MTG_PORT` | `-p`, `--bind-port` | `3128` | Which port should we bind to (listen on). |
|
||||
| `MTG_IPV4` | `-4`, `--public-ipv4` | [Autodetect](https://ifconfig.co) | IPv4 address of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv4 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. |
|
||||
| `MTG_IPV4_PORT` | `--public-ipv4-port` | Value of `--bind-port` | Which port should be public of IPv4 interface. This affects only generated links and should be changed only if you NAT your proxy or run it in a docker container. |
|
||||
| `MTG_IPV6` | `-6`, `--public-ipv6` | [Autodetect](https://ifconfig.co) | IPv6 address of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv6 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. |
|
||||
| `MTG_IPV6_PORT` | `--public-ipv6-port` | Value of `--bind-port` | Which port should be public of IPv6 interface. This affects only generated links and should be changed only if you NAT your proxy or run it in a docker container. |
|
||||
| `MTG_STATS_IP` | `-t`, `--stats-ip` | `127.0.0.1` | Which IP should we bind the internal statistics HTTP server. |
|
||||
| `MTG_STATS_PORT` | `-q`, `--stats-port` | `3129` | Which port should we bind the internal statistics HTTP server. |
|
||||
| `MTG_STATSD_IP` | `--statsd-ip` | | IP/host addresses of statsd service. No defaults, by defaults we do not send anything there. |
|
||||
| `MTG_STATSD_PORT` | `--statsd-port` | `8125` | Which port should we use to work with statsd. |
|
||||
| `MTG_STATSD_NETWORK` | `--statsd-network` | `udp` | Which protocol should we use to work with statsd. Possible options are `udp` and `tcp`. |
|
||||
| `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` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. |
|
||||
| `MTG_PROMETHEUS_PREFIX` | `--prometheus-prefix` | `mtg` | Which namespace should be used for prometheus metrics. |
|
||||
| `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_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_SECURE_ONLY` | `-s`, `--secure-only` | `false` | Support only clients with secure mode (i.e only clients with dd-secrets). |
|
||||
| `MTG_ANTIREPLAY_MAXSIZE` | `anti-replay-max-size` | `128` | Max size of antireplay cache in megabytes. |
|
||||
| `MTG_ANTIREPLAY_EVICTIONTIME` | `anti-replay-eviction-time` | `168h` | Eviction time for antireplay cache entries. |
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package antireplay
|
||||
|
||||
import (
|
||||
"github.com/allegro/bigcache"
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/9seconds/mtg/config"
|
||||
)
|
||||
|
||||
// Cache defines storage for obfuscated2 handshake frames.
|
||||
type Cache struct {
|
||||
cache *bigcache.BigCache
|
||||
}
|
||||
|
||||
func (a Cache) Add(frame []byte) {
|
||||
a.cache.Set(string(frame), nil) // nolint: errcheck
|
||||
}
|
||||
|
||||
func (a Cache) Has(frame []byte) bool {
|
||||
_, err := a.cache.Get(string(frame))
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func NewCache(config *config.Config) (Cache, error) {
|
||||
cache, err := bigcache.NewBigCache(bigcache.Config{
|
||||
Shards: 1024,
|
||||
LifeWindow: config.AntiReplayEvictionTime,
|
||||
Hasher: hasher{},
|
||||
HardMaxCacheSize: config.AntiReplayMaxSize,
|
||||
})
|
||||
if err != nil {
|
||||
return Cache{}, errors.Annotate(err, "Cannot make cache")
|
||||
}
|
||||
|
||||
return Cache{cache}, nil
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package antireplay
|
||||
|
||||
import "github.com/cespare/xxhash"
|
||||
|
||||
type hasher struct{}
|
||||
|
||||
func (h hasher) Sum64(value string) uint64 {
|
||||
return xxhash.Sum64String(value)
|
||||
}
|
||||
+2
-1
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/9seconds/mtg/antireplay"
|
||||
"github.com/9seconds/mtg/config"
|
||||
"github.com/9seconds/mtg/mtproto"
|
||||
"github.com/9seconds/mtg/wrappers"
|
||||
@@ -11,4 +12,4 @@ import (
|
||||
|
||||
// Init defines common method for initializing client connections.
|
||||
type Init func(context.Context, context.CancelFunc, net.Conn, string,
|
||||
*config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error)
|
||||
antireplay.Cache, *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error)
|
||||
|
||||
+9
-1
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/9seconds/mtg/antireplay"
|
||||
"github.com/9seconds/mtg/config"
|
||||
"github.com/9seconds/mtg/mtproto"
|
||||
"github.com/9seconds/mtg/obfuscated2"
|
||||
@@ -18,7 +19,8 @@ const handshakeTimeout = 10 * time.Second
|
||||
// DirectInit initializes client connection for proxy which connects to
|
||||
// Telegram directly.
|
||||
func DirectInit(ctx context.Context, cancel context.CancelFunc, socket net.Conn,
|
||||
connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
|
||||
connID string, antiReplayCache antireplay.Cache,
|
||||
conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
|
||||
tcpSocket := socket.(*net.TCPConn)
|
||||
if err := tcpSocket.SetNoDelay(false); err != nil {
|
||||
return nil, nil, errors.Annotate(err, "Cannot disable NO_DELAY to client socket")
|
||||
@@ -42,6 +44,12 @@ func DirectInit(ctx context.Context, cancel context.CancelFunc, socket net.Conn,
|
||||
if err != nil {
|
||||
return nil, nil, errors.Annotate(err, "Cannot parse obfuscated frame")
|
||||
}
|
||||
|
||||
if antiReplayCache.Has([]byte(frame)) {
|
||||
return nil, nil, errors.New("Replay attack is detected")
|
||||
}
|
||||
antiReplayCache.Add([]byte(frame))
|
||||
|
||||
connOpts.ConnectionProto = mtproto.ConnectionProtocolAny
|
||||
connOpts.ClientAddr = conn.RemoteAddr()
|
||||
|
||||
|
||||
+4
-2
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/9seconds/mtg/antireplay"
|
||||
"github.com/9seconds/mtg/config"
|
||||
"github.com/9seconds/mtg/mtproto"
|
||||
"github.com/9seconds/mtg/wrappers"
|
||||
@@ -12,8 +13,9 @@ import (
|
||||
// MiddleInit initializes client connection for proxy which has to
|
||||
// support promoted channels, connect to Telegram middle proxies etc.
|
||||
func MiddleInit(ctx context.Context, cancel context.CancelFunc, socket net.Conn,
|
||||
connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
|
||||
conn, opts, err := DirectInit(ctx, cancel, socket, connID, conf)
|
||||
connID string, antiReplayCache antireplay.Cache,
|
||||
conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
|
||||
conn, opts, err := DirectInit(ctx, cancel, socket, connID, antiReplayCache, conf)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+23
-16
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/juju/errors"
|
||||
statsd "gopkg.in/alexcesaro/statsd.v2"
|
||||
@@ -31,6 +32,9 @@ type Config struct {
|
||||
PublicIPv6 net.IP
|
||||
StatsIP net.IP
|
||||
|
||||
AntiReplayMaxSize int
|
||||
AntiReplayEvictionTime time.Duration
|
||||
|
||||
StatsD struct {
|
||||
Addr net.Addr
|
||||
Prefix string
|
||||
@@ -121,6 +125,7 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
|
||||
statsdIP, statsdNetwork, statsdPrefix, statsdTagsFormat string,
|
||||
statsdTags map[string]string, prometheusPrefix string,
|
||||
secureOnly bool,
|
||||
antiReplayMaxSize int, antiReplayEvictionTime time.Duration,
|
||||
secret, adtag []byte) (*Config, error) {
|
||||
secureMode := secureOnly
|
||||
if bytes.HasPrefix(secret, []byte{0xdd}) && len(secret) == 17 {
|
||||
@@ -160,22 +165,24 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
|
||||
}
|
||||
|
||||
conf := &Config{
|
||||
Debug: debug,
|
||||
Verbose: verbose,
|
||||
SecureOnly: secureOnly,
|
||||
BindIP: bindIP,
|
||||
BindPort: bindPort,
|
||||
PublicIPv4: publicIPv4,
|
||||
PublicIPv4Port: publicIPv4Port,
|
||||
PublicIPv6: publicIPv6,
|
||||
PublicIPv6Port: publicIPv6Port,
|
||||
StatsIP: statsIP,
|
||||
StatsPort: statsPort,
|
||||
Secret: secret,
|
||||
AdTag: adtag,
|
||||
SecureMode: secureMode,
|
||||
ReadBufferSize: int(readBufferSize),
|
||||
WriteBufferSize: int(writeBufferSize),
|
||||
Debug: debug,
|
||||
Verbose: verbose,
|
||||
SecureOnly: secureOnly,
|
||||
BindIP: bindIP,
|
||||
BindPort: bindPort,
|
||||
PublicIPv4: publicIPv4,
|
||||
PublicIPv4Port: publicIPv4Port,
|
||||
PublicIPv6: publicIPv6,
|
||||
PublicIPv6Port: publicIPv6Port,
|
||||
StatsIP: statsIP,
|
||||
StatsPort: statsPort,
|
||||
Secret: secret,
|
||||
AdTag: adtag,
|
||||
SecureMode: secureMode,
|
||||
ReadBufferSize: int(readBufferSize),
|
||||
WriteBufferSize: int(writeBufferSize),
|
||||
AntiReplayMaxSize: antiReplayMaxSize,
|
||||
AntiReplayEvictionTime: antiReplayEvictionTime,
|
||||
}
|
||||
conf.Prometheus.Prefix = prometheusPrefix
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ func getGlobalIPv6() (net.IP, error) {
|
||||
}
|
||||
|
||||
func fetchIP(network string) (net.IP, error) {
|
||||
dialer := &net.Dialer{DualStack: false}
|
||||
dialer := &net.Dialer{FallbackDelay: -1}
|
||||
client := &http.Client{
|
||||
Jar: nil,
|
||||
Transport: &http.Transport{
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
module github.com/9seconds/mtg
|
||||
|
||||
replace github.com/golang/lint => github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1
|
||||
|
||||
require (
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
||||
github.com/allegro/bigcache v1.2.0
|
||||
github.com/beevik/ntp v0.2.0
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/gofrs/uuid v3.1.0+incompatible
|
||||
github.com/gogo/protobuf v1.1.1 // indirect
|
||||
github.com/golang/protobuf v1.2.0 // indirect
|
||||
github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea
|
||||
github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect
|
||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 // indirect
|
||||
github.com/gofrs/uuid v3.2.0+incompatible
|
||||
github.com/juju/errors v0.0.0-20190207033735-e65537c515d7
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
|
||||
github.com/juju/testing v0.0.0-20190429233213-dfc56b8c09fc // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/pkg/errors v0.8.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v0.9.0
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
|
||||
github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37 // indirect
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
go.uber.org/atomic v1.3.2 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/prometheus/client_golang v0.9.4
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
go.uber.org/atomic v1.4.0 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.9.1
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
|
||||
go.uber.org/zap v1.10.0
|
||||
golang.org/x/net v0.0.0-20190607181551-461777fb6f67 // indirect
|
||||
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae // indirect
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
gopkg.in/alexcesaro/statsd.v2 v2.0.0
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
)
|
||||
|
||||
@@ -1,27 +1,46 @@
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
|
||||
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
||||
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/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
|
||||
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
|
||||
github.com/beevik/ntp v0.2.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/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/gofrs/uuid v3.1.0+incompatible h1:q2rtkjaKT4YEr6E1kamy0Ha4RtepWlQBedyHx0uzKwA=
|
||||
github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
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/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea h1:g2k+8WR7cHch4g0tBDhfiEvAp7fXxTNBiD1oC1Oxj3E=
|
||||
github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8=
|
||||
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 h1:WQM1NildKThwdP7qWrNAFGzp4ijNLw8RlgENkaI4MJs=
|
||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
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/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 h1:dMIPRDg6gi7CUp0Kj2+HxqJ5kTr1iAdzsXYIrLCNSmU=
|
||||
github.com/juju/errors v0.0.0-20190207033735-e65537c515d7/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/testing v0.0.0-20190429233213-dfc56b8c09fc h1:5xUWujf6ES9tEpFHFzI34vcHm8U07lGjxAuJML3qwqM=
|
||||
github.com/juju/testing v0.0.0-20190429233213-dfc56b8c09fc/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -29,30 +48,58 @@ 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/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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
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/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.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/prometheus/client_golang v0.9.0 h1:tXuTFVHC03mW0D+Ua1Q2d1EAVqLTuggX50V0VLICCzY=
|
||||
github.com/prometheus/client_golang v0.9.0/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.4 h1:Y8E/JaaPbmFSW2V81Ab/d8yZFYQQGbni1b1jPcG9Y6A=
|
||||
github.com/prometheus/client_golang v0.9.4/go.mod h1:oCXIBxdI62A4cR6aTRJCgetEjecSIYzOEaeAn4iYEpM=
|
||||
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/common v0.0.0-20181015124227-bcb74de08d37 h1:Y7YdJ9Xb3MoQOzAWXnDunAJYpvhVwZdTirNfGUgPKaA=
|
||||
github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
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/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
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.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190607181551-461777fb6f67 h1:rJJxsykSlULwd2P2+pg/rtnwN2FrWp4IuCxOSyS0V00=
|
||||
golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae h1:xiXzMMEQdQcric9hXtr1QU98MHunKK7OTtsoU6bYWs4=
|
||||
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc=
|
||||
@@ -64,3 +111,5 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
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.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package main
|
||||
|
||||
//go:generate scripts/generate_version.sh
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -22,6 +20,8 @@ import (
|
||||
"github.com/9seconds/mtg/stats"
|
||||
)
|
||||
|
||||
var version = "dev" // this has to be set by build ld flags
|
||||
|
||||
var (
|
||||
app = kingpin.New("mtg", "Simple MTPROTO proxy.")
|
||||
|
||||
@@ -134,17 +134,26 @@ var (
|
||||
Envar("MTG_SECURE_ONLY").
|
||||
Bool()
|
||||
|
||||
antiReplayMaxSize = app.Flag("anti-replay-max-size",
|
||||
"Max size of antireplay cache in megabytes.").
|
||||
Envar("MTG_ANTIREPLAY_MAXSIZE").
|
||||
Default("128").
|
||||
Int()
|
||||
antiReplayEvictionTime = app.Flag("anti-replay-eviction-time",
|
||||
"Eviction time period for obfuscated2 handshakes").
|
||||
Envar("MTG_ANTIREPLAY_EVICTIONTIME").
|
||||
Default("168h").
|
||||
Duration()
|
||||
|
||||
secret = app.Arg("secret", "Secret of this proxy.").Required().HexBytes()
|
||||
adtag = app.Arg("adtag", "ADTag of the proxy.").HexBytes()
|
||||
)
|
||||
|
||||
func init() {
|
||||
func main() { // nolint: gocyclo
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
app.Version(version)
|
||||
app.HelpFlag.Short('h')
|
||||
}
|
||||
|
||||
func main() { // nolint: gocyclo
|
||||
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
|
||||
err := setRLimit()
|
||||
@@ -158,6 +167,7 @@ func main() { // nolint: gocyclo
|
||||
*bindPort, *publicIPv4Port, *publicIPv6Port, *statsPort, *statsdPort,
|
||||
*statsdIP, *statsdNetwork, *statsdPrefix, *statsdTagsFormat,
|
||||
*statsdTags, *prometheusPrefix, *secureOnly,
|
||||
*antiReplayMaxSize, *antiReplayEvictionTime,
|
||||
*secret, *adtag,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -183,6 +193,7 @@ func main() { // nolint: gocyclo
|
||||
defer logger.Sync() // nolint: errcheck
|
||||
|
||||
printURLs(conf.GetURLs())
|
||||
zap.S().Debugw("Configuration", "config", conf)
|
||||
|
||||
if conf.UseMiddleProxy() {
|
||||
zap.S().Infow("Use middle proxy connection to Telegram")
|
||||
@@ -203,7 +214,10 @@ func main() { // nolint: gocyclo
|
||||
panic(err)
|
||||
}
|
||||
|
||||
server := proxy.NewProxy(conf)
|
||||
server, err := proxy.NewProxy(conf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := server.Serve(); err != nil {
|
||||
zap.S().Fatalw("Server stopped", "error", err)
|
||||
}
|
||||
|
||||
+2
-7
@@ -23,11 +23,6 @@ var (
|
||||
ProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00}
|
||||
ProxyRequestProxyTag = []byte{0xae, 0x26, 0x1e, 0xdb}
|
||||
|
||||
HandshakeSenderPID []byte
|
||||
HandshakePeerPID []byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
HandshakeSenderPID = []byte("IPIPPRPDTIME")
|
||||
HandshakePeerPID = []byte("IPIPPRPDTIME")
|
||||
}
|
||||
HandshakePeerPID = []byte("IPIPPRPDTIME")
|
||||
)
|
||||
|
||||
@@ -78,10 +78,10 @@ func TestFrameGenerateValid(t *testing.T) {
|
||||
}
|
||||
for _, test := range validTests {
|
||||
t.Run(strconv.Itoa(int(test)), func(tt *testing.T) {
|
||||
frame := generateFrame(test)
|
||||
frame := generateFrame(test) // nolint: scopelint
|
||||
conType, err := frame.ConnectionType()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, conType, test)
|
||||
assert.Nil(tt, err)
|
||||
assert.Equal(tt, conType, test) // nolint: scopelint
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+17
-9
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/juju/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/9seconds/mtg/antireplay"
|
||||
"github.com/9seconds/mtg/client"
|
||||
"github.com/9seconds/mtg/config"
|
||||
"github.com/9seconds/mtg/mtproto"
|
||||
@@ -20,9 +21,10 @@ import (
|
||||
|
||||
// Proxy is a core of this program.
|
||||
type Proxy struct {
|
||||
clientInit client.Init
|
||||
tg telegram.Telegram
|
||||
conf *config.Config
|
||||
antiReplayCache antireplay.Cache
|
||||
clientInit client.Init
|
||||
tg telegram.Telegram
|
||||
conf *config.Config
|
||||
}
|
||||
|
||||
// Serve runs TCP proxy server.
|
||||
@@ -58,7 +60,7 @@ func (p *Proxy) accept(conn net.Conn) {
|
||||
|
||||
log.Infow("Client connected", "addr", conn.RemoteAddr())
|
||||
|
||||
clientConn, opts, err := p.clientInit(ctx, cancel, conn, connID, p.conf)
|
||||
clientConn, opts, err := p.clientInit(ctx, cancel, conn, connID, p.antiReplayCache, p.conf)
|
||||
if err != nil {
|
||||
log.Errorw("Cannot initialize client connection", "error", err)
|
||||
return
|
||||
@@ -150,10 +152,15 @@ func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst io.Writer, wait *s
|
||||
}
|
||||
|
||||
// NewProxy returns new proxy instance.
|
||||
func NewProxy(conf *config.Config) *Proxy {
|
||||
func NewProxy(conf *config.Config) (*Proxy, error) {
|
||||
var clientInit client.Init
|
||||
var tg telegram.Telegram
|
||||
|
||||
cache, err := antireplay.NewCache(conf)
|
||||
if err != nil {
|
||||
return nil, errors.Annotate(err, "Cannot make proxy")
|
||||
}
|
||||
|
||||
if conf.UseMiddleProxy() {
|
||||
clientInit = client.MiddleInit
|
||||
tg = telegram.NewMiddleTelegram(conf)
|
||||
@@ -163,8 +170,9 @@ func NewProxy(conf *config.Config) *Proxy {
|
||||
}
|
||||
|
||||
return &Proxy{
|
||||
conf: conf,
|
||||
clientInit: clientInit,
|
||||
tg: tg,
|
||||
}
|
||||
antiReplayCache: cache,
|
||||
conf: conf,
|
||||
clientInit: clientInit,
|
||||
tg: tg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
PROJECT_DIR="$(git rev-parse --show-toplevel)"
|
||||
OUTPUT_FILE="${PROJECT_DIR}/version.go"
|
||||
|
||||
cat > "$OUTPUT_FILE" <<EOF
|
||||
package main
|
||||
// autogenerated by $(basename "$0") on $(date -Ru)
|
||||
|
||||
const version = "$(git describe --long --always) ($(go version)) [$(date -Ru)]"
|
||||
EOF
|
||||
+1
-1
@@ -22,7 +22,7 @@ func Init(conf *config.Config) error {
|
||||
go prometheus.run()
|
||||
|
||||
go NewStats(conf).start()
|
||||
go startServer(conf)
|
||||
go startServer(conf, prometheus.getHTTPHandler())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+15
-4
@@ -1,10 +1,12 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"github.com/9seconds/mtg/config"
|
||||
)
|
||||
@@ -12,6 +14,8 @@ import (
|
||||
const prometheusPollTime = time.Second
|
||||
|
||||
type prometheusExporter struct {
|
||||
registry prometheus.Gatherer
|
||||
|
||||
connections *prometheus.GaugeVec
|
||||
traffic *prometheus.GaugeVec
|
||||
speed *prometheus.GaugeVec
|
||||
@@ -36,7 +40,13 @@ func (p *prometheusExporter) run() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *prometheusExporter) getHTTPHandler() http.Handler {
|
||||
return promhttp.HandlerFor(p.registry, promhttp.HandlerOpts{})
|
||||
}
|
||||
|
||||
func newPrometheus(conf *config.Config) (*prometheusExporter, error) {
|
||||
registry := prometheus.NewRegistry()
|
||||
|
||||
connections := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: conf.Prometheus.Prefix,
|
||||
Name: "connections",
|
||||
@@ -58,20 +68,21 @@ func newPrometheus(conf *config.Config) (*prometheusExporter, error) {
|
||||
Help: "How many crashes happened.",
|
||||
})
|
||||
|
||||
if err := prometheus.Register(connections); err != nil {
|
||||
if err := registry.Register(connections); err != nil {
|
||||
return nil, errors.Annotate(err, "Cannot register connections collector")
|
||||
}
|
||||
if err := prometheus.Register(traffic); err != nil {
|
||||
if err := registry.Register(traffic); err != nil {
|
||||
return nil, errors.Annotate(err, "cannot register traffic collector")
|
||||
}
|
||||
if err := prometheus.Register(speed); err != nil {
|
||||
if err := registry.Register(speed); err != nil {
|
||||
return nil, errors.Annotate(err, "cannot register speed collector")
|
||||
}
|
||||
if err := prometheus.Register(crashes); err != nil {
|
||||
if err := registry.Register(crashes); err != nil {
|
||||
return nil, errors.Annotate(err, "cannot register crashes collector")
|
||||
}
|
||||
|
||||
return &prometheusExporter{
|
||||
registry: registry,
|
||||
connections: connections,
|
||||
traffic: traffic,
|
||||
speed: speed,
|
||||
|
||||
+3
-4
@@ -4,16 +4,15 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/9seconds/mtg/config"
|
||||
)
|
||||
|
||||
func startServer(conf *config.Config) {
|
||||
func startServer(conf *config.Config, prometheusHandler http.Handler) {
|
||||
log := zap.S().Named("stats")
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
first, err := json.Marshal(GetStats())
|
||||
@@ -33,7 +32,7 @@ func startServer(conf *config.Config) {
|
||||
log.Errorw("Cannot encode json", "error", err)
|
||||
}
|
||||
})
|
||||
http.Handle("/prometheus/", promhttp.Handler())
|
||||
http.Handle("/prometheus/", prometheusHandler)
|
||||
|
||||
if err := http.ListenAndServe(conf.StatAddr(), nil); err != nil {
|
||||
log.Fatalw("Stats server has been stopped", "error", err)
|
||||
|
||||
@@ -5,12 +5,10 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var streamCipherBufferPool sync.Pool
|
||||
|
||||
func init() {
|
||||
var (
|
||||
streamCipherBufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &bytes.Buffer{}
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user