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
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

handshake_frame.go 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package obfuscation
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "slices"
  6. )
  7. // https://core.telegram.org/mtproto/mtproto-transports#transport-obfuscation
  8. const (
  9. // default DC is nothing is selected
  10. defaultDC = 2
  11. // the length of the handshake frame. Always 64 bytes
  12. hfLen = 64
  13. hfLenKey = 32
  14. hfLenIV = 16
  15. hfLenConnectionType = 4
  16. // A structure of obfuscated handshake frame is following:
  17. //
  18. // [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd].
  19. //
  20. // - 8 bytes of noise
  21. // - 32 bytes of AES Key
  22. // - 16 bytes of AES IV
  23. // - 4 bytes of 'connection type' - this has some setting like a connection type
  24. // - 2 bytes of 'DC'. DC is little endian int16
  25. // - 2 bytes of noise
  26. hfOffsetKey = 8
  27. hfOffsetIV = hfOffsetKey + hfLenKey
  28. hfOffsetConnectionType = hfOffsetIV + hfLenIV
  29. hfOffsetDC = hfOffsetConnectionType + hfLenConnectionType
  30. )
  31. // Connection-Type: Secure. We support only fake tls.
  32. var hfConnectionType = [hfLenConnectionType]byte{0xdd, 0xdd, 0xdd, 0xdd}
  33. type handshakeFrame struct {
  34. data [hfLen]byte
  35. }
  36. func (h *handshakeFrame) key() []byte {
  37. return h.data[hfOffsetKey : hfOffsetKey+hfLenKey]
  38. }
  39. func (h *handshakeFrame) iv() []byte {
  40. return h.data[hfOffsetIV : hfOffsetIV+hfLenIV]
  41. }
  42. func (h *handshakeFrame) connectionType() []byte {
  43. return h.data[hfOffsetConnectionType : hfOffsetConnectionType+hfLenConnectionType]
  44. }
  45. func (h *handshakeFrame) dcSlice() []byte {
  46. return h.data[hfOffsetDC : hfOffsetDC+2]
  47. }
  48. func (h *handshakeFrame) dc() int {
  49. idx := int16(binary.LittleEndian.Uint16(h.dcSlice()))
  50. switch {
  51. case idx > 0:
  52. return int(idx)
  53. case idx < 0:
  54. return -int(idx)
  55. }
  56. return defaultDC
  57. }
  58. func (h *handshakeFrame) revert() {
  59. slices.Reverse(h.data[hfOffsetKey:hfOffsetConnectionType])
  60. }
  61. func generateHandshake(dc int) handshakeFrame {
  62. frame := handshakeFrame{}
  63. for {
  64. if _, err := rand.Read(frame.data[:]); err != nil {
  65. panic(err)
  66. }
  67. // https://github.com/tdlib/td/blob/master/td/mtproto/TcpTransport.cpp#L157-L158.
  68. if frame.data[0] == 0xef { // abridged header
  69. // https://core.telegram.org/mtproto/mtproto-transports#abridged
  70. continue
  71. }
  72. switch binary.LittleEndian.Uint32(frame.data[:4]) {
  73. case 0x44414548, // HEAD
  74. 0x54534f50, // POST
  75. 0x20544547, // GET
  76. 0x4954504f, // OPTI
  77. 0x02010316, // ????
  78. 0xdddddddd, // PaddedIntermediate header
  79. 0xeeeeeeee: // Intermediate header
  80. continue
  81. }
  82. if frame.data[4]|frame.data[5]|frame.data[6]|frame.data[7] == 0 {
  83. continue
  84. }
  85. copy(frame.connectionType(), hfConnectionType[:])
  86. binary.LittleEndian.PutUint16(frame.dcSlice(), uint16(dc))
  87. return frame
  88. }
  89. }