From 5009859a1e3ed7131177ddddba41a3cf26ee3c03 Mon Sep 17 00:00:00 2001 From: 9seconds Date: Fri, 11 Oct 2019 09:41:18 +0300 Subject: [PATCH] linting the code --- Makefile | 6 +----- cli/generate.go | 1 + cli/proxy.go | 12 ++++++++++-- cli/utils.go | 1 + config/config.go | 12 ++++++++---- config/global_ips.go | 5 +++++ config/urls.go | 1 + conntypes/protocol.go | 1 + conntypes/wrappers.go | 2 -- hub/connection.go | 2 ++ hub/connection_hub.go | 6 +++++- hub/ctx_channel.go | 2 ++ hub/hub.go | 5 +++-- hub/registry.go | 1 + main.go | 1 - mtproto/protocol.go | 16 +++++++++++----- mtproto/rpc/handshake_response.go | 7 ++++--- mtproto/rpc/nonce_request.go | 1 + mtproto/rpc/nonce_response.go | 10 ++++++---- mtproto/rpc/proxy_flags.go | 7 +++++++ mtproto/rpc/proxy_response.go | 6 ++++-- ntp/ntp.go | 4 +++- obfuscated2/client_protocol.go | 7 +++++-- obfuscated2/telegram_protocol.go | 2 ++ proxy/direct.go | 3 +++ proxy/middle.go | 7 ++++--- proxy/proxy.go | 7 ++++++- stats/stats.go | 4 ++++ stats/stats_prometheus.go | 4 ++++ stats/stats_statsd.go | 1 + telegram/api/addresses.go | 9 ++++++--- telegram/api/api.go | 4 +++- telegram/api/secret.go | 1 + telegram/base.go | 2 +- telegram/middle.go | 1 + utils/init_tcp.go | 2 ++ utils/read_full.go | 1 + utils/reverse_bytes.go | 2 +- utils/rlimit.go | 1 + utils/signal_context.go | 1 + wrappers/packet/mtproto_frame.go | 18 ++++++++++++------ wrappers/packetack/client_abridged.go | 11 ++++++++++- wrappers/packetack/client_intermediate.go | 5 +++++ .../packetack/client_intermediate_secure.go | 5 ++++- wrappers/packetack/proxy.go | 4 +++- wrappers/stream/blockcipher.go | 3 +++ wrappers/stream/conn.go | 2 ++ wrappers/stream/mtproto_cipher.go | 8 ++++++-- wrappers/stream/obfuscated2.go | 2 ++ wrappers/stream/stats_telegram.go | 1 + 50 files changed, 172 insertions(+), 55 deletions(-) delete mode 100644 conntypes/wrappers.go diff --git a/Makefile b/Makefile index dfed95d..e90b35d 100644 --- a/Makefile +++ b/Makefile @@ -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}") -GOLANGCI_LINT_VERSION := v1.15.0 +GOLANGCI_LINT_VERSION := v1.20.0 VERSION_GO := $(shell go version) VERSION_DATE := $(shell date -Ru) @@ -51,10 +51,6 @@ crosscompile: $(CC_BINARIES) crosscompile-dir: @rm -rf "$(CC_DIR)" && mkdir -p "$(CC_DIR)" -.PHONY: test -test: vendor - @$(MOD_ON) go test -v ./... - .PHONY: lint lint: vendor @$(MOD_OFF) golangci-lint run diff --git a/cli/generate.go b/cli/generate.go index 8010280..96c8311 100644 --- a/cli/generate.go +++ b/cli/generate.go @@ -12,6 +12,7 @@ func Generate(secretType string) { if _, err := rand.Read(data); err != nil { panic(err) } + secret := hex.EncodeToString(data) switch secretType { diff --git a/cli/proxy.go b/cli/proxy.go index e2d8b20..ef94430 100644 --- a/cli/proxy.go +++ b/cli/proxy.go @@ -19,10 +19,11 @@ import ( "github.com/9seconds/mtg/utils" ) -func Proxy() error { +func Proxy() error { // nolint: funlen ctx := utils.GetSignalContext() atom := zap.NewAtomicLevel() + switch { case config.C.Debug: atom.SetLevel(zapcore.DebugLevel) @@ -38,23 +39,28 @@ func Proxy() error { zapcore.Lock(os.Stderr), atom, )) + zap.ReplaceGlobals(logger) defer logger.Sync() // nolint: errcheck if err := config.InitPublicAddress(ctx); err != nil { Fatal(err) } + zap.S().Debugw("Configuration", "config", config.Printable()) if len(config.C.AdTag) > 0 { zap.S().Infow("Use middle proxy connection to Telegram") + diff, err := ntp.Fetch() if err != nil { Fatal("Cannot fetch time data from NTP") } + if diff > time.Second { Fatal("Your local time is skewed and drift is bigger than a second. Please sync your time.") } + go ntp.AutoUpdate() } else { zap.S().Infow("Use direct connection to Telegram") @@ -62,10 +68,11 @@ func Proxy() error { PrintJSONStdout(config.GetURLs()) - antireplay.Init() if err := stats.Init(ctx); err != nil { Fatal(err) } + + antireplay.Init() telegram.Init() hub.Init(ctx) @@ -73,6 +80,7 @@ func Proxy() error { if err != nil { Fatal(err) } + go func() { <-ctx.Done() proxyListener.Close() diff --git a/cli/utils.go b/cli/utils.go index 36f1128..f26c1b6 100644 --- a/cli/utils.go +++ b/cli/utils.go @@ -11,6 +11,7 @@ func Fatal(arg interface{}) { if value, ok := arg.(error); ok { arg = fmt.Errorf("fatal error: %+v", value) } + PrintStderr(arg) os.Exit(1) } diff --git a/config/config.go b/config/config.go index a8bf8fd..7bb12d6 100644 --- a/config/config.go +++ b/config/config.go @@ -23,6 +23,7 @@ func (s SecretMode) String() string { case SecretModeSecured: return "secured" } + return "tls" } @@ -135,7 +136,7 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen case "influxdb": C.StatsdTagsFormat = statsd.InfluxDB default: - return fmt.Errorf("Incorrect statsd tag %s", value) + return fmt.Errorf("incorrect statsd tag %s", value) } case OptionTypeStatsdTags: C.StatsdTags = opt.Value.(map[string]string) @@ -152,7 +153,7 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen case OptionTypeAdtag: C.AdTag = opt.Value.([]byte) default: - return fmt.Errorf("Unknown tag %v", opt.Option) + return fmt.Errorf("unknown tag %v", opt.Option) } } @@ -163,7 +164,7 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen case len(C.Secret) == SimpleSecretLength: C.SecretMode = SecretModeSimple default: - return errors.New("Incorrect secret") + return errors.New("incorrect secret") } return nil @@ -173,11 +174,13 @@ func InitPublicAddress(ctx context.Context) error { if C.PublicIPv4.Port == 0 { C.PublicIPv4.Port = C.Bind.Port } + if C.PublicIPv6.Port == 0 { C.PublicIPv6.Port = C.Bind.Port } foundAddress := C.PublicIPv4.IP != nil || C.PublicIPv6.IP != nil + if C.PublicIPv4.IP == nil { ip, err := getGlobalIPv4(ctx) if err != nil { @@ -187,6 +190,7 @@ func InitPublicAddress(ctx context.Context) error { foundAddress = true } } + if C.PublicIPv6.IP == nil { ip, err := getGlobalIPv6(ctx) if err != nil { @@ -198,7 +202,7 @@ func InitPublicAddress(ctx context.Context) error { } if !foundAddress { - return errors.New("Cannot resolve any public address") + return errors.New("cannot resolve any public address") } return nil diff --git a/config/global_ips.go b/config/global_ips.go index be5fe5c..e27b969 100644 --- a/config/global_ips.go +++ b/config/global_ips.go @@ -21,6 +21,7 @@ func getGlobalIPv4(ctx context.Context) (net.IP, error) { if err != nil || ip.To4() == nil { return nil, fmt.Errorf("cannot find public ipv4 address: %w", err) } + return ip, nil } @@ -29,6 +30,7 @@ func getGlobalIPv6(ctx context.Context) (net.IP, error) { if err != nil || ip.To4() != nil { return nil, fmt.Errorf("cannot find public ipv6 address: %w", err) } + return ip, nil } @@ -54,14 +56,17 @@ func fetchIP(ctx context.Context, network string) (net.IP, error) { if resp != nil { io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck } + return nil, fmt.Errorf("cannot perform a request: %w", err) } + defer resp.Body.Close() // nolint: errcheck respDataBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("cannot read response body: %w", err) } + respData := strings.TrimSpace(string(respDataBytes)) ip := net.ParseIP(respData) diff --git a/config/urls.go b/config/urls.go index b4471d6..28a6b7b 100644 --- a/config/urls.go +++ b/config/urls.go @@ -22,6 +22,7 @@ type IPURLs struct { func GetURLs() (urls IPURLs) { secret := "" + switch C.SecretMode { case SecretModeSimple: secret = hex.EncodeToString(C.Secret) diff --git a/conntypes/protocol.go b/conntypes/protocol.go index 21da2c0..15a1c69 100644 --- a/conntypes/protocol.go +++ b/conntypes/protocol.go @@ -9,6 +9,7 @@ func (c ConnectionProtocol) String() string { case ConnectionProtocolIPv4: return "ipv4" } + return "ipv6" } diff --git a/conntypes/wrappers.go b/conntypes/wrappers.go deleted file mode 100644 index a086871..0000000 --- a/conntypes/wrappers.go +++ /dev/null @@ -1,2 +0,0 @@ -package conntypes - diff --git a/hub/connection.go b/hub/connection.go index 4420a97..c3edeb8 100644 --- a/hub/connection.go +++ b/hub/connection.go @@ -47,6 +47,7 @@ func (c *connection) write(packet conntypes.Packet) error { c.pending = 0 c.mutex.Unlock() } + return err } @@ -89,6 +90,7 @@ func (c *connection) run() { logger.Debugw("Failed response", "error", err) continue } + if response.Type == rpc.ProxyResponseTypeCloseExt { logger.Debugw("Proxy has closed connection") return diff --git a/hub/connection_hub.go b/hub/connection_hub.go index a1101b0..8ba9027 100644 --- a/hub/connection_hub.go +++ b/hub/connection_hub.go @@ -50,11 +50,11 @@ func (c *connectionHub) runGC() { case conn.closed(): logger.Debugw("Delete closed socket", "key", key) delete(c.sockets, key) - case conn.idle(): logger.Debugw("Delete idle socket", "key", key) conn.shutdown() delete(c.sockets, key) + return } } @@ -65,12 +65,14 @@ func (c *connectionHub) runConnectionRequest(req *connectionHubRequest) { for key, conn := range c.sockets { delete(c.sockets, key) + if !conn.closed() { logger.Debugw("Choose connection", "id", conn.id, "remote_addr", conn.conn.RemoteAddr()) req.response <- conn close(req.response) + return } } @@ -81,6 +83,7 @@ func (c *connectionHub) runConnectionRequest(req *connectionHubRequest) { "remote_addr", conn.conn.RemoteAddr()) req.response <- conn } + close(req.response) } @@ -93,6 +96,7 @@ func (c *connectionHub) runReturnConnection(conn *connection) { c.logger.Named("return-connection").Debugw("Return connection", "id", conn.id, "remote_addr", conn.conn.RemoteAddr()) + c.sockets[conn.id] = conn } diff --git a/hub/ctx_channel.go b/hub/ctx_channel.go index 0f599e4..e9e8b86 100644 --- a/hub/ctx_channel.go +++ b/hub/ctx_channel.go @@ -46,11 +46,13 @@ func (c *ctxChannel) sendBack(response *rpc.ProxyResponse) error { func (c *ctxChannel) Close() error { c.cancel() c.channel = nil + return nil } func newCtxChannel(ctx context.Context) *ctxChannel { ctx, cancel := context.WithCancel(ctx) + return &ctxChannel{ channel: make(chan *rpc.ProxyResponse), ctx: ctx, diff --git a/hub/hub.go b/hub/hub.go index e0545e2..57c2875 100644 --- a/hub/hub.go +++ b/hub/hub.go @@ -42,9 +42,9 @@ func (h *hub) Write(packet conntypes.Packet, req *protocol.TelegramRequest) erro func (h *hub) getHub(req *protocol.TelegramRequest) *connectionHub { keyBuilder := strings.Builder{} - binary.Write(&keyBuilder, binary.LittleEndian, int16(req.ClientProtocol.DC())) + binary.Write(&keyBuilder, binary.LittleEndian, int16(req.ClientProtocol.DC())) // nolint: errcheck keyBuilder.WriteRune('_') - binary.Write(&keyBuilder, binary.LittleEndian, uint8(req.ClientProtocol.ConnectionProtocol())) + binary.Write(&keyBuilder, binary.LittleEndian, uint8(req.ClientProtocol.ConnectionProtocol())) // nolint: errcheck key := keyBuilder.String() h.mutex.RLock() @@ -60,6 +60,7 @@ func (h *hub) getHub(req *protocol.TelegramRequest) *connectionHub { h.logger.Debugw("Create new connection hub", "dc", req.ClientProtocol.DC(), "protocol", req.ClientProtocol.ConnectionProtocol()) + rv = newConnectionHub(h.logger.With( "dc", req.ClientProtocol.DC(), "protocol", req.ClientProtocol.ConnectionProtocol(), diff --git a/hub/registry.go b/hub/registry.go index 5f6e33c..c8652a1 100644 --- a/hub/registry.go +++ b/hub/registry.go @@ -40,5 +40,6 @@ func (r *registry) getChannel(id conntypes.ConnID) (*ctxChannel, bool) { if value, ok := r.conns[string(id[:])]; ok { return value, true } + return nil, false } diff --git a/main.go b/main.go index e795f33..7d0fb31 100644 --- a/main.go +++ b/main.go @@ -119,7 +119,6 @@ func main() { switch kingpin.MustParse(app.Parse(os.Args[1:])) { case generateSecretCommand.FullCommand(): cli.Generate(*generateSecretType) - case proxyCommand.FullCommand(): err := config.Init( config.Opt{Option: config.OptionTypeDebug, Value: *proxyDebug}, diff --git a/mtproto/protocol.go b/mtproto/protocol.go index f90d784..b7dae2e 100644 --- a/mtproto/protocol.go +++ b/mtproto/protocol.go @@ -20,6 +20,7 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce) rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn) + if err != nil { return nil, fmt.Errorf("cannot do nonce request: %w", err) } @@ -35,6 +36,7 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC if err := doRPCHandshakeRequest(frameConn); err != nil { return nil, fmt.Errorf("cannot do handshake request: %w", err) } + if err := getRPCHandshakeResponse(frameConn); err != nil { return nil, fmt.Errorf("cannot get handshake response: %w", err) } @@ -42,11 +44,12 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC return frameConn, nil } -func doRPCNonceRequest(conn conntypes.PacketWriter) (*rpc.NonceRequest, error) { +func doRPCNonceRequest(conn conntypes.BasePacketWriter) (*rpc.NonceRequest, error) { rpcNonceReq, err := rpc.NewNonceRequest(telegram.Middle.Secret()) if err != nil { panic(err) } + if err := conn.Write(rpcNonceReq.Bytes()); err != nil { return nil, err } @@ -54,7 +57,7 @@ func doRPCNonceRequest(conn conntypes.PacketWriter) (*rpc.NonceRequest, error) { return rpcNonceReq, nil } -func getRPCNonceResponse(conn conntypes.PacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) { +func getRPCNonceResponse(conn conntypes.BasePacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) { packet, err := conn.Read() if err != nil { return nil, fmt.Errorf("cannot read from connection: %w", err) @@ -62,8 +65,9 @@ func getRPCNonceResponse(conn conntypes.PacketReader, req *rpc.NonceRequest) (*r resp, err := rpc.NewNonceResponse(packet) if err != nil { - return nil, fmt.Errorf("cannot build rpc nonce responce: %w", err) + return nil, fmt.Errorf("cannot build rpc nonce response: %w", err) } + if err = resp.Valid(req); err != nil { return nil, fmt.Errorf("invalid nonce response: %w", err) } @@ -71,14 +75,15 @@ func getRPCNonceResponse(conn conntypes.PacketReader, req *rpc.NonceRequest) (*r return resp, nil } -func doRPCHandshakeRequest(conn conntypes.PacketWriter) error { +func doRPCHandshakeRequest(conn conntypes.BasePacketWriter) error { if err := conn.Write(rpc.HandshakeRequest); err != nil { return fmt.Errorf("cannot make a request: %w", err) } + return nil } -func getRPCHandshakeResponse(conn conntypes.PacketReader) error { +func getRPCHandshakeResponse(conn conntypes.BasePacketReader) error { packet, err := conn.Read() if err != nil { return fmt.Errorf("cannot read a response: %w", err) @@ -88,6 +93,7 @@ func getRPCHandshakeResponse(conn conntypes.PacketReader) error { if err != nil { return fmt.Errorf("cannot build a handshake response: %w", err) } + if err := resp.Valid(); err != nil { return fmt.Errorf("invalid handshake response: %w", err) } diff --git a/mtproto/rpc/handshake_response.go b/mtproto/rpc/handshake_response.go index 659ce7c..1f1d509 100644 --- a/mtproto/rpc/handshake_response.go +++ b/mtproto/rpc/handshake_response.go @@ -28,10 +28,11 @@ func (r *HandshakeResponse) Bytes() []byte { // Valid checks that handshake response compliments request. func (r *HandshakeResponse) Valid() error { if !bytes.Equal(r.Type, TagHandshake) { - return errors.New("Unexpected handshake tag") + return errors.New("unexpected handshake tag") } + if !bytes.Equal(r.PeerPID, HandshakeSenderPID) { - return errors.New("Incorrect sender PID") + return errors.New("incorrect sender PID") } return nil @@ -41,7 +42,7 @@ func (r *HandshakeResponse) Valid() error { // data. func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) { if len(data) != 32 { - return nil, fmt.Errorf("Incorrect handshake response length %d", len(data)) + return nil, fmt.Errorf("incorrect handshake response length %d", len(data)) } return &HandshakeResponse{ diff --git a/mtproto/rpc/nonce_request.go b/mtproto/rpc/nonce_request.go index 2915dad..8a06c26 100644 --- a/mtproto/rpc/nonce_request.go +++ b/mtproto/rpc/nonce_request.go @@ -36,6 +36,7 @@ func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) { if _, err := rand.Read(nonce); err != nil { return nil, fmt.Errorf("cannot generate nonce: %w", err) } + copy(keySelector, proxySecret) timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // 256 ^ 4 - do not know how to name diff --git a/mtproto/rpc/nonce_response.go b/mtproto/rpc/nonce_response.go index 08b9a4b..b214eb5 100644 --- a/mtproto/rpc/nonce_response.go +++ b/mtproto/rpc/nonce_response.go @@ -28,13 +28,15 @@ func (r *NonceResponse) Bytes() []byte { func (r *NonceResponse) Valid(req *NonceRequest) error { if !bytes.Equal(r.Type, TagNonce) { - return errors.New("Unexpected RPC type") + return errors.New("unexpected RPC type") } + if !bytes.Equal(r.Crypto, NonceCryptoAES) { - return errors.New("Unexpected crypto type") + return errors.New("unexpected crypto type") } + if !bytes.Equal(r.KeySelector, req.KeySelector) { - return errors.New("Unexpected key selector") + return errors.New("unexpected key selector") } return nil @@ -43,7 +45,7 @@ func (r *NonceResponse) Valid(req *NonceRequest) error { // NewNonceResponse build new nonce response based on the given data. func NewNonceResponse(data []byte) (*NonceResponse, error) { if len(data) != 32 { - return nil, fmt.Errorf("Unexpected message length %d", len(data)) + return nil, fmt.Errorf("unexpected message length %d", len(data)) } return &NonceResponse{ diff --git a/mtproto/rpc/proxy_flags.go b/mtproto/rpc/proxy_flags.go index c0e87fa..2179c66 100644 --- a/mtproto/rpc/proxy_flags.go +++ b/mtproto/rpc/proxy_flags.go @@ -33,24 +33,31 @@ func (r ProxyRequestFlags) String() string { if r&ProxyRequestFlagsHasAdTag != 0 { flags = append(flags, "HAS_AD_TAG") } + if r&ProxyRequestFlagsEncrypted != 0 { flags = append(flags, "ENCRYPTED") } + if r&ProxyRequestFlagsMagic != 0 { flags = append(flags, "MAGIC") } + if r&ProxyRequestFlagsExtMode2 != 0 { flags = append(flags, "EXT_MODE_2") } + if r&ProxyRequestFlagsIntermediate != 0 { flags = append(flags, "INTERMEDIATE") } + if r&ProxyRequestFlagsAbdridged != 0 { flags = append(flags, "ABRIDGED") } + if r&ProxyRequestFlagsQuickAck != 0 { flags = append(flags, "QUICK_ACK") } + if r&ProxyRequestFlagsPad != 0 { flags = append(flags, "PAD") } diff --git a/mtproto/rpc/proxy_response.go b/mtproto/rpc/proxy_response.go index 2b91810..5366f34 100644 --- a/mtproto/rpc/proxy_response.go +++ b/mtproto/rpc/proxy_response.go @@ -29,21 +29,23 @@ func ParseProxyResponse(packet conntypes.Packet) (*ProxyResponse, error) { } tag := packet[:4] + switch { case bytes.Equal(tag, TagProxyAns): response.Type = ProxyResponseTypeAns copy(response.ConnID[:], packet[8:16]) response.Payload = packet[16:] - return &response, nil + return &response, nil case bytes.Equal(tag, TagSimpleAck): response.Type = ProxyResponseTypeSimpleAck copy(response.ConnID[:], packet[4:12]) response.Payload = packet[12:] - return &response, nil + return &response, nil case bytes.Equal(tag, TagCloseExt): response.Type = ProxyResponseTypeCloseExt + return &response, nil } diff --git a/ntp/ntp.go b/ntp/ntp.go index ee5d515..0b4fa1f 100644 --- a/ntp/ntp.go +++ b/ntp/ntp.go @@ -21,15 +21,17 @@ var ntpEndpoints = [...]string{ // Fetch fetches the data on time drift. func Fetch() (time.Duration, error) { url := ntpEndpoints[rand.Intn(len(ntpEndpoints))] + resp, err := ntp.Query(url) if err != nil { - return 0, fmt.Errorf("Cannot fetch NTP server %s: %w", url, err) + return 0, fmt.Errorf("cannot fetch NTP server %s: %w", url, err) } offsetInt := int64(resp.ClockOffset) if offsetInt < 0 { offsetInt = -offsetInt } + offset := time.Duration(offsetInt) return offset, nil diff --git a/obfuscated2/client_protocol.go b/obfuscated2/client_protocol.go index 3dd00ec..3ccc7c4 100644 --- a/obfuscated2/client_protocol.go +++ b/obfuscated2/client_protocol.go @@ -58,6 +58,7 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn decryptor.XORKeyStream(decryptedFrame.Bytes(), fm.Bytes()) magic := decryptedFrame.Magic() + switch { case bytes.Equal(magic, conntypes.ConnectionTagAbridged): c.connectionType = conntypes.ConnectionTypeAbridged @@ -66,7 +67,7 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn case bytes.Equal(magic, conntypes.ConnectionTagSecure): c.connectionType = conntypes.ConnectionTypeSecure default: - return nil, errors.New("Unknown connection type") + return nil, errors.New("unknown connection type") } c.connectionProtocol = conntypes.ConnectionProtocolIPv4 @@ -81,8 +82,9 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn antiReplayKey := decryptedFrame.Unique() if antireplay.Cache.Has(antiReplayKey) { - return nil, errors.New("Replay attack is detected") + return nil, errors.New("replay attack is detected") } + antireplay.Cache.Add(antiReplayKey) return stream.NewObfuscated2(socket, encryptor, decryptor), nil @@ -92,6 +94,7 @@ func (c *ClientProtocol) ReadFrame(socket conntypes.StreamReader) (fm Frame, err if _, err = io.ReadFull(handshakeReader{socket}, fm.Bytes()); err != nil { err = fmt.Errorf("cannot extract obfuscated2 frame: %w", err) } + return } diff --git a/obfuscated2/telegram_protocol.go b/obfuscated2/telegram_protocol.go index 9a92acb..cf17099 100644 --- a/obfuscated2/telegram_protocol.go +++ b/obfuscated2/telegram_protocol.go @@ -17,6 +17,7 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteC if err != nil { return nil, fmt.Errorf("cannot dial to telegram: %w", err) } + conn = stream.NewTimeout(conn) conn = stream.NewCtx(req.Ctx, req.Cancel, conn) fm := generateFrame(req.ClientProtocol) @@ -45,6 +46,7 @@ func generateFrame(cp protocol.ClientProtocol) (fm Frame) { if _, err := rand.Read(data); err != nil { continue } + if data[0] == 0xef { continue } diff --git a/proxy/direct.go b/proxy/direct.go index 23266ae..7067cbb 100644 --- a/proxy/direct.go +++ b/proxy/direct.go @@ -18,13 +18,16 @@ func directConnection(request *protocol.TelegramRequest) error { if err != nil { return err } + telegramConn := telegramConnRaw.(conntypes.StreamReadWriteCloser) + defer telegramConn.Close() wg := &sync.WaitGroup{} wg.Add(2) go directPipe(telegramConn, request.ClientConn, wg, request.Logger) + go directPipe(request.ClientConn, telegramConn, wg, request.Logger) wg.Wait() diff --git a/proxy/middle.go b/proxy/middle.go index c8c79e3..d7d3d42 100644 --- a/proxy/middle.go +++ b/proxy/middle.go @@ -10,11 +10,12 @@ import ( "github.com/9seconds/mtg/wrappers/packetack" ) -func middleConnection(request *protocol.TelegramRequest) error { +func middleConnection(request *protocol.TelegramRequest) { telegramConn := packetack.NewProxy(request) defer telegramConn.Close() var clientConn conntypes.PacketAckFullReadWriteCloser + switch request.ClientProtocol.ConnectionType() { case conntypes.ConnectionTypeAbridged: clientConn = packetack.NewClientAbridged(request.ClientConn) @@ -30,11 +31,10 @@ func middleConnection(request *protocol.TelegramRequest) error { wg.Add(2) go middlePipe(telegramConn, clientConn, wg, request.Logger) + go middlePipe(clientConn, telegramConn, wg, request.Logger) wg.Wait() - - return nil } func middlePipe(dst conntypes.PacketAckWriteCloser, @@ -50,6 +50,7 @@ func middlePipe(dst conntypes.PacketAckWriteCloser, for { acks := conntypes.ConnectionAcks{} packet, err := src.Read(&acks) + if err != nil { logger.Debugw("Cannot read packet", "error", err) return diff --git a/proxy/proxy.go b/proxy/proxy.go index 46bc62f..809482e 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -34,6 +34,7 @@ func (p *Proxy) Serve(listener net.Listener) { continue } } + go p.accept(conn) } } @@ -61,10 +62,12 @@ func (p *Proxy) accept(conn net.Conn) { clientConn := stream.NewClientConn(conn, connID) clientConn = stream.NewCtx(ctx, cancel, clientConn) clientConn = stream.NewTimeout(clientConn) + defer clientConn.Close() clientProtocol := p.ClientProtocolMaker() clientConn, err := clientProtocol.Handshake(clientConn) + if err != nil { logger.Warnw("Cannot perform client handshake", "error", err) return @@ -83,8 +86,10 @@ func (p *Proxy) accept(conn net.Conn) { ClientProtocol: clientProtocol, } + err = nil + if len(config.C.AdTag) > 0 { - err = middleConnection(req) + middleConnection(req) } else { err = directConnection(req) } diff --git a/stats/stats.go b/stats/stats.go index 535b5f3..044e704 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -20,11 +20,13 @@ func Init(ctx context.Context) error { } stats := []Interface{instancePrometheus} + if config.C.StatsdAddr != nil { instanceStatsd, err := newStatsStatsd() if err != nil { return fmt.Errorf("cannot inialize statsd: %w", err) } + stats = append(stats, instanceStatsd) } @@ -36,7 +38,9 @@ func Init(ctx context.Context) error { srv := http.Server{ Handler: mux, } + go srv.Serve(listener) // nolint: errcheck + go func() { <-ctx.Done() srv.Shutdown(context.Background()) // nolint: errcheck diff --git a/stats/stats_prometheus.go b/stats/stats_prometheus.go index bcb0c91..69a3f6c 100644 --- a/stats/stats_prometheus.go +++ b/stats/stats_prometheus.go @@ -122,15 +122,19 @@ func newStatsPrometheus(mux *http.ServeMux) (Interface, error) { if err := registry.Register(instance.connections); err != nil { return nil, fmt.Errorf("cannot register metrics for connections: %w", err) } + if err := registry.Register(instance.telegramConnections); err != nil { return nil, fmt.Errorf("cannot register metrics for telegram connections: %w", err) } + if err := registry.Register(instance.traffic); err != nil { return nil, fmt.Errorf("cannot register metrics for traffic: %w", err) } + if err := registry.Register(instance.crashes); err != nil { return nil, fmt.Errorf("cannot register metrics for crashes: %w", err) } + if err := registry.Register(instance.antiReplays); err != nil { return nil, fmt.Errorf("cannot register metrics for anti replays: %w", err) } diff --git a/stats/stats_statsd.go b/stats/stats_statsd.go index 9451ed7..e68ede7 100644 --- a/stats/stats_statsd.go +++ b/stats/stats_statsd.go @@ -96,6 +96,7 @@ func newStatsStatsd() (Interface, error) { for k, v := range config.C.StatsdTags { tags = append(tags, k, v) } + options = append(options, statsd.Tags(tags...)) } diff --git a/telegram/api/addresses.go b/telegram/api/addresses.go index f65fcac..c7573e4 100644 --- a/telegram/api/addresses.go +++ b/telegram/api/addresses.go @@ -31,34 +31,36 @@ func getAddresses(url string) (map[conntypes.DC][]string, conntypes.DC, error) { if err != nil { return nil, 0, fmt.Errorf("cannot get http response: %w", err) } + defer resp.Close() scanner := bufio.NewScanner(resp) data := map[conntypes.DC][]string{} + defaultDC := conntypes.DCDefaultIdx - var defaultDC = conntypes.DCDefaultIdx for scanner.Scan() { text := strings.TrimSpace(scanner.Text()) + switch { case strings.HasPrefix(text, "#"): continue - case strings.HasPrefix(text, "proxy_for"): addr, idx, err := addressesParseProxyFor(text) if err != nil { return nil, 0, fmt.Errorf("cannot parse 'proxy_for' section: %w", err) } + if addresses, ok := data[idx]; ok { data[idx] = append(addresses, addr) } else { data[idx] = []string{addr} } - case strings.HasPrefix(text, "default"): idx, err := addressesParseDefault(text) if err != nil { return nil, 0, fmt.Errorf("cannot parse 'default' section: %w", err) } + defaultDC = idx } } @@ -97,6 +99,7 @@ func addressesParseDefault(text string) (conntypes.DC, error) { } dcString := strings.TrimRight(chunks[1], ";") + dc, err := strconv.ParseInt(dcString, 10, 16) if err != nil { return 0, fmt.Errorf("incorrect config '%s': %w", text, err) diff --git a/telegram/api/api.go b/telegram/api/api.go index 8b36d83..91a21c1 100644 --- a/telegram/api/api.go +++ b/telegram/api/api.go @@ -22,15 +22,17 @@ func request(url string) (io.ReadCloser, error) { if err != nil { panic(err) } + req.Header.Set("Accept", "text/plan") req.Header.Set("User-Agent", apiUserAgent) resp, err := httpClient.Do(req) if err != nil { if resp != nil { - io.Copy(ioutil.Discard, resp.Body) + io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck resp.Body.Close() } + return nil, fmt.Errorf("cannot perform a request: %w", err) } diff --git a/telegram/api/secret.go b/telegram/api/secret.go index c2b2e43..c5a1137 100644 --- a/telegram/api/secret.go +++ b/telegram/api/secret.go @@ -12,6 +12,7 @@ func Secret() ([]byte, error) { if err != nil { return nil, fmt.Errorf("cannot access telegram server: %w", err) } + defer resp.Close() secret, err := ioutil.ReadAll(resp) diff --git a/telegram/base.go b/telegram/base.go index eef2175..51cfd42 100644 --- a/telegram/base.go +++ b/telegram/base.go @@ -51,7 +51,7 @@ func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string, dc, defaultDC conntypes.DC) string { addrs, ok := addresses[dc] if !ok { - addrs, _ = addresses[defaultDC] + addrs = addresses[defaultDC] } switch { diff --git a/telegram/middle.go b/telegram/middle.go index 88278b1..519332e 100644 --- a/telegram/middle.go +++ b/telegram/middle.go @@ -55,6 +55,7 @@ func (m *middleTelegram) update() error { func (m *middleTelegram) backgroundUpdate() { logger := zap.S().Named("telegram") + for range time.Tick(middleTelegramBackgroundUpdateEvery) { if err := m.update(); err != nil { logger.Warnw("Cannot update Telegram proxies", "error", err) diff --git a/utils/init_tcp.go b/utils/init_tcp.go index 6f0ea2d..3bf90ca 100644 --- a/utils/init_tcp.go +++ b/utils/init_tcp.go @@ -13,9 +13,11 @@ func InitTCP(conn net.Conn) error { if err := tcpConn.SetNoDelay(true); err != nil { return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err) } + if err := tcpConn.SetReadBuffer(config.C.ReadBuffer); err != nil { return fmt.Errorf("cannot set read buffer size: %w", err) } + if err := tcpConn.SetWriteBuffer(config.C.WriteBuffer); err != nil { return fmt.Errorf("cannot set write buffer size: %w", err) } diff --git a/utils/read_full.go b/utils/read_full.go index afb2554..912aa19 100644 --- a/utils/read_full.go +++ b/utils/read_full.go @@ -13,6 +13,7 @@ func ReadFull(src io.Reader) (rv []byte, err error) { if err != nil { return nil, err } + rv = append(rv, buf[:n]...) } diff --git a/utils/reverse_bytes.go b/utils/reverse_bytes.go index ab7cd5b..87ad8f6 100644 --- a/utils/reverse_bytes.go +++ b/utils/reverse_bytes.go @@ -4,8 +4,8 @@ package utils func ReverseBytes(data []byte) []byte { dataLen := len(data) rv := make([]byte, dataLen) - rv[dataLen/2] = data[dataLen/2] + for i := dataLen/2 - 1; i >= 0; i-- { opp := dataLen - i - 1 rv[i], rv[opp] = data[opp], data[i] diff --git a/utils/rlimit.go b/utils/rlimit.go index d62d3fa..b474076 100644 --- a/utils/rlimit.go +++ b/utils/rlimit.go @@ -13,6 +13,7 @@ func SetLimits() error { if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rLimit); err != nil { return fmt.Errorf("cannot get rlimit: %w", err) } + rLimit.Cur = rLimit.Max if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit); err != nil { diff --git a/utils/signal_context.go b/utils/signal_context.go index 40e2b6f..6d3951f 100644 --- a/utils/signal_context.go +++ b/utils/signal_context.go @@ -14,6 +14,7 @@ func GetSignalContext() context.Context { sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + go func() { for range sigChan { cancel() diff --git a/wrappers/packet/mtproto_frame.go b/wrappers/packet/mtproto_frame.go index a43f4eb..6a1cd1a 100644 --- a/wrappers/packet/mtproto_frame.go +++ b/wrappers/packet/mtproto_frame.go @@ -41,7 +41,7 @@ type wrapperMtprotoFrame struct { writeSeqNo int32 } -func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { +func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen buf := &bytes.Buffer{} sum := crc32.NewIEEE() writer := io.MultiWriter(buf, sum) @@ -49,9 +49,11 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { for { buf.Reset() sum.Reset() + if _, err := io.CopyN(writer, w.parent, 4); err != nil { return nil, fmt.Errorf("cannot read frame padding: %w", err) } + if !bytes.Equal(buf.Bytes(), mtprotoFramePadding) { break } @@ -62,19 +64,23 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { "messageLength", messageLength, "sequence_number", w.readSeqNo, ) + if messageLength%4 != 0 || messageLength < mtprotoFrameMinMessageLength || messageLength > mtprotoFrameMaxMessageLength { - return nil, fmt.Errorf("Incorrect frame message length %d", messageLength) + return nil, fmt.Errorf("incorrect frame message length %d", messageLength) } buf.Reset() buf.Grow(int(messageLength) - 4 - 4) + if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil { return nil, fmt.Errorf("cannot read the message frame: %w", err) } var seqNo int32 - binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck, gosec + + binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck + if seqNo != w.readSeqNo { return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo) } @@ -110,12 +116,12 @@ func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error { buf := &bytes.Buffer{} buf.Grow(messageLength + paddingLength) - binary.Write(buf, binary.LittleEndian, uint32(messageLength)) - binary.Write(buf, binary.LittleEndian, w.writeSeqNo) + binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck + binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck buf.Write(p) checksum := crc32.ChecksumIEEE(buf.Bytes()) - binary.Write(buf, binary.LittleEndian, checksum) + binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) w.logger.Debugw("Write MTProto frame", diff --git a/wrappers/packetack/client_abridged.go b/wrappers/packetack/client_abridged.go index c9b26e1..1b8aa9a 100644 --- a/wrappers/packetack/client_abridged.go +++ b/wrappers/packetack/client_abridged.go @@ -26,9 +26,11 @@ func (w *wrapperClientAbridged) Read(acks *conntypes.ConnectionAcks) (conntypes. buf := bytes.Buffer{} buf.Grow(1) + if _, err := io.CopyN(&buf, w.parent, 1); err != nil { return nil, fmt.Errorf("cannot read message length: %w", err) } + msgLength := uint32(buf.Bytes()[0]) buf.Reset() @@ -39,17 +41,21 @@ func (w *wrapperClientAbridged) Read(acks *conntypes.ConnectionAcks) (conntypes. if msgLength == clientAbridgedSmallPacketLength { buf.Grow(3) + if _, err := io.CopyN(&buf, w.parent, 3); err != nil { return nil, fmt.Errorf("cannot read correct message length: %w", err) } + number := utils.Uint24{} copy(number[:], buf.Bytes()) msgLength = utils.FromUint24(number) } + msgLength *= 4 buf.Reset() buf.Grow(int(msgLength)) + if _, err := io.CopyN(&buf, w.parent, int64(msgLength)); err != nil { return nil, fmt.Errorf("cannot read message: %w", err) } @@ -66,18 +72,20 @@ func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.C if _, err := w.parent.Write(utils.ReverseBytes(packet)); err != nil { return fmt.Errorf("cannot send a simpleacked packet: %w", err) } + return nil } packetLength := len(packet) / 4 + switch { case packetLength < clientAbridgedSmallPacketLength: data := append([]byte{byte(packetLength)}, packet...) if _, err := w.parent.Write(data); err != nil { return fmt.Errorf("cannot send small packet: %w", err) } - return nil + return nil case packetLength < clientAbridgedLargePacketLength: length24 := utils.ToUint24(uint32(packetLength)) buf := bytes.Buffer{} @@ -89,6 +97,7 @@ func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.C if _, err := w.parent.Write(buf.Bytes()); err != nil { return fmt.Errorf("cannot send large packet: %w", err) } + return nil } diff --git a/wrappers/packetack/client_intermediate.go b/wrappers/packetack/client_intermediate.go index 0415c8c..71ca5f5 100644 --- a/wrappers/packetack/client_intermediate.go +++ b/wrappers/packetack/client_intermediate.go @@ -22,9 +22,11 @@ func (w *wrapperClientIntermediate) Read(acks *conntypes.ConnectionAcks) (connty buf := bytes.Buffer{} buf.Grow(4) + if _, err := io.CopyN(&buf, w.parent, 4); err != nil { return nil, fmt.Errorf("cannot read message length: %w", err) } + length := binary.LittleEndian.Uint32(buf.Bytes()) if length > clientIntermediateQuickAckLength { @@ -34,6 +36,7 @@ func (w *wrapperClientIntermediate) Read(acks *conntypes.ConnectionAcks) (connty buf.Reset() buf.Grow(int(length)) + if _, err := io.CopyN(&buf, w.parent, int64(length)); err != nil { return nil, fmt.Errorf("cannot read the message: %w", err) } @@ -46,6 +49,7 @@ func (w *wrapperClientIntermediate) Write(packet conntypes.Packet, acks *conntyp if _, err := w.parent.Write(packet); err != nil { return fmt.Errorf("cannot send simpleacked packet: %w", err) } + return nil } @@ -55,6 +59,7 @@ func (w *wrapperClientIntermediate) Write(packet conntypes.Packet, acks *conntyp if _, err := w.parent.Write(append(length[:], packet...)); err != nil { return fmt.Errorf("cannot send packet: %w", err) } + return nil } diff --git a/wrappers/packetack/client_intermediate_secure.go b/wrappers/packetack/client_intermediate_secure.go index a42afec..153e779 100644 --- a/wrappers/packetack/client_intermediate_secure.go +++ b/wrappers/packetack/client_intermediate_secure.go @@ -20,6 +20,7 @@ func (w *wrapperClientIntermediateSecure) Read(acks *conntypes.ConnectionAcks) ( if err != nil { return nil, err } + length := len(data) - (len(data) % 4) return data[:length], nil @@ -30,6 +31,7 @@ func (w *wrapperClientIntermediateSecure) Write(packet conntypes.Packet, acks *c if _, err := w.parent.Write(packet); err != nil { return fmt.Errorf("cannot send simpleacked packet: %w", err) } + return nil } @@ -37,13 +39,14 @@ func (w *wrapperClientIntermediateSecure) Write(packet conntypes.Packet, acks *c paddingLength := rand.Intn(4) buf.Grow(4 + len(packet) + paddingLength) - binary.Write(&buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) + binary.Write(&buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck buf.Write(packet) buf.Write(make([]byte, paddingLength)) if _, err := w.parent.Write(buf.Bytes()); err != nil { return fmt.Errorf("cannot send packet: %w", err) } + return nil } diff --git a/wrappers/packetack/proxy.go b/wrappers/packetack/proxy.go index 301035c..768eddb 100644 --- a/wrappers/packetack/proxy.go +++ b/wrappers/packetack/proxy.go @@ -15,12 +15,12 @@ import ( ) type wrapperProxy struct { - flags rpc.ProxyRequestFlags request *protocol.TelegramRequest clientIPPort []byte ourIPPort []byte channelRead hub.ChannelReadCloser closeOnce sync.Once + flags rpc.ProxyRequestFlags } func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error { @@ -30,6 +30,7 @@ func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.Connection if acks.Quick { flags |= rpc.ProxyRequestFlagsQuickAck } + if bytes.HasPrefix(packet, rpc.ProxyRequestFlagsEncryptedPrefix[:]) { flags |= rpc.ProxyRequestFlagsEncrypted } @@ -67,6 +68,7 @@ func (w *wrapperProxy) Close() error { w.channelRead.Close() hub.Registry.Unregister(w.request.ConnID) }) + return nil } diff --git a/wrappers/stream/blockcipher.go b/wrappers/stream/blockcipher.go index 5755ddb..34ff7d8 100644 --- a/wrappers/stream/blockcipher.go +++ b/wrappers/stream/blockcipher.go @@ -27,6 +27,7 @@ func (w *wrapperBlockCipher) Write(p []byte) (int, error) { if err != nil { return 0, err } + return w.parent.Write(encrypted) } @@ -35,6 +36,7 @@ func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int, if err != nil { return 0, err } + return w.parent.WriteTimeout(encrypted, timeout) } @@ -49,6 +51,7 @@ func (w *wrapperBlockCipher) Read(p []byte) (int, error) { if err != nil { return 0, fmt.Errorf("cannot read data: %w", err) } + currentBuffer = append(currentBuffer, rv...) } diff --git a/wrappers/stream/conn.go b/wrappers/stream/conn.go index d534ec3..8b0bf80 100644 --- a/wrappers/stream/conn.go +++ b/wrappers/stream/conn.go @@ -38,6 +38,7 @@ func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) func (w *wrapperConn) Write(p []byte) (int, error) { n, err := w.parent.Write(p) w.logger.Debugw("write to stream", "bytes", n, "error", err) + if err != nil { w.Close() // nolint: gosec } @@ -57,6 +58,7 @@ func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) func (w *wrapperConn) Read(p []byte) (int, error) { n, err := w.parent.Read(p) w.logger.Debugw("Read from stream", "bytes", n, "error", err) + if err != nil { w.Close() } diff --git a/wrappers/stream/mtproto_cipher.go b/wrappers/stream/mtproto_cipher.go index 85f8ce7..a46b528 100644 --- a/wrappers/stream/mtproto_cipher.go +++ b/wrappers/stream/mtproto_cipher.go @@ -4,8 +4,8 @@ import ( "bytes" "crypto/aes" "crypto/cipher" - "crypto/md5" - "crypto/sha1" + "crypto/md5" // nolint: gosec + "crypto/sha1" // nolint: gosec "encoding/binary" "net" @@ -61,13 +61,16 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose, clientIPv4 := mtprotoEmptyIP[:] serverIPv4 := mtprotoEmptyIP[:] + if client.IP.To4() != nil { clientIPv4 = utils.ReverseBytes(client.IP.To4()) serverIPv4 = utils.ReverseBytes(remote.IP.To4()) } + message.Write(serverIPv4) // nolint: gosec var port [2]byte + binary.LittleEndian.PutUint16(port[:], uint16(client.Port)) message.Write(port[:]) // nolint: gosec @@ -90,6 +93,7 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose, message.Write(client.IP.To16()) // nolint: gosec message.Write(remote.IP.To16()) // nolint: gosec } + message.Write(req.Nonce) // nolint: gosec data := message.Bytes() diff --git a/wrappers/stream/obfuscated2.go b/wrappers/stream/obfuscated2.go index 9ad4ae2..d94b245 100644 --- a/wrappers/stream/obfuscated2.go +++ b/wrappers/stream/obfuscated2.go @@ -22,6 +22,7 @@ func (w *wrapperObfuscated2) ReadTimeout(p []byte, timeout time.Duration) (int, if err != nil { return 0, fmt.Errorf("cannot read stream ciphered data: %w", err) } + w.decryptor.XORKeyStream(p, p[:n]) return n, nil @@ -32,6 +33,7 @@ func (w *wrapperObfuscated2) Read(p []byte) (int, error) { if err != nil { return n, err } + w.decryptor.XORKeyStream(p, p[:n]) return n, nil diff --git a/wrappers/stream/stats_telegram.go b/wrappers/stream/stats_telegram.go index c45b769..064790c 100644 --- a/wrappers/stream/stats_telegram.go +++ b/wrappers/stream/stats_telegram.go @@ -65,6 +65,7 @@ func NewTelegramStats(dc conntypes.DC, parent conntypes.StreamReadWriteCloser) c parent: parent, dc: dc, } + stats.Stats.TelegramConnected(dc, parent.RemoteAddr()) return conn