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.

telegram_protocol.go 1.7KB

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