Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package obfuscated2
  2. import (
  3. "crypto/rand"
  4. "fmt"
  5. "github.com/9seconds/mtg/conntypes"
  6. "github.com/9seconds/mtg/protocol"
  7. "github.com/9seconds/mtg/telegram"
  8. "github.com/9seconds/mtg/utils"
  9. "github.com/9seconds/mtg/wrappers/stream"
  10. )
  11. func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteCloser, error) {
  12. conn, err := telegram.Direct.Dial(req.ClientProtocol.DC(),
  13. req.ClientProtocol.ConnectionProtocol())
  14. if err != nil {
  15. return nil, fmt.Errorf("cannot dial to telegram: %w", err)
  16. }
  17. conn = stream.NewTimeout(conn)
  18. conn = stream.NewCtx(req.Ctx, req.Cancel, conn)
  19. fm := generateFrame(req.ClientProtocol)
  20. data := fm.Bytes()
  21. encryptor := utils.MakeStreamCipher(fm.Key(), fm.IV())
  22. decryptedFrame := fm.Invert()
  23. decryptor := utils.MakeStreamCipher(decryptedFrame.Key(), decryptedFrame.IV())
  24. copyFrame := make([]byte, frameLen)
  25. copy(copyFrame[:frameOffsetIV], data[:frameOffsetIV])
  26. encryptor.XORKeyStream(data, data)
  27. copy(data[:frameOffsetIV], copyFrame[:frameOffsetIV])
  28. if _, err := conn.Write(data); err != nil {
  29. return nil, fmt.Errorf("cannot write handshake frame to telegram: %w", err)
  30. }
  31. return stream.NewObfuscated2(conn, encryptor, decryptor), nil
  32. }
  33. func generateFrame(cp protocol.ClientProtocol) Frame {
  34. fm := Frame{}
  35. data := fm.Bytes()
  36. for {
  37. if _, err := rand.Read(data); err != nil {
  38. continue
  39. }
  40. if data[0] == 0xef { //nolint: gomnd
  41. continue
  42. }
  43. val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) //nolint: gomnd, lll
  44. if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { //nolint: lll
  45. continue
  46. }
  47. val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) //nolint: gomnd
  48. if val == 0x00000000 { //nolint: gomnd
  49. continue
  50. }
  51. copy(fm.Magic(), cp.ConnectionType().Tag())
  52. return fm
  53. }
  54. }