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
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

obfuscator.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package obfuscation
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/sha256"
  6. "crypto/subtle"
  7. "encoding/hex"
  8. "fmt"
  9. "hash"
  10. "io"
  11. "github.com/9seconds/mtg/v2/essentials"
  12. )
  13. // Obfuscator implements the obfuscated2 handshake
  14. // (https://core.telegram.org/mtproto/mtproto-transports#transport-obfuscation).
  15. // Set Secret to the MTProxy secret for key-mixed handshakes; leave nil for
  16. // direct DC connections.
  17. type Obfuscator struct {
  18. Secret []byte
  19. }
  20. // ReadHandshake reads the 64-byte obfuscated2 client handshake from r,
  21. // validates it, and returns the DC the client requested along with a
  22. // transparent en/decrypting wrapper over r.
  23. func (o Obfuscator) ReadHandshake(r essentials.Conn) (int, essentials.Conn, error) {
  24. frame := handshakeFrame{}
  25. if _, err := io.ReadFull(r, frame.data[:]); err != nil {
  26. return 0, nil, fmt.Errorf("cannot read frame: %w", err)
  27. }
  28. hasher := sha256.New()
  29. recvCipher := o.getCipher(&frame, hasher)
  30. frame.revert()
  31. hasher.Reset()
  32. sendCipher := o.getCipher(&frame, hasher)
  33. recvCipher.XORKeyStream(frame.data[:], frame.data[:])
  34. if val := frame.connectionType(); subtle.ConstantTimeCompare(val, hfConnectionType[:]) != 1 {
  35. return 0, nil, fmt.Errorf("unsupported connection type: %s", hex.EncodeToString(val))
  36. }
  37. cn := conn{
  38. Conn: r,
  39. recvCipher: recvCipher,
  40. sendCipher: sendCipher,
  41. }
  42. return frame.dc(), cn, nil
  43. }
  44. // SendHandshake writes a fresh 64-byte obfuscated2 handshake for the given
  45. // DC to w and returns a transparent en/decrypting wrapper over w.
  46. func (o Obfuscator) SendHandshake(w essentials.Conn, dc int) (essentials.Conn, error) {
  47. frame := generateHandshake(dc)
  48. copyFrame := frame
  49. hasher := sha256.New()
  50. sendCipher := o.getCipher(&frame, hasher)
  51. frame.revert()
  52. hasher.Reset()
  53. recvCipher := o.getCipher(&frame, hasher)
  54. sendCipher.XORKeyStream(frame.data[:], frame.data[:])
  55. copy(frame.key(), copyFrame.key())
  56. copy(frame.iv(), copyFrame.iv())
  57. if _, err := w.Write(frame.data[:]); err != nil {
  58. return nil, fmt.Errorf("cannot send a handshake: %w", err)
  59. }
  60. return conn{
  61. Conn: w,
  62. recvCipher: recvCipher,
  63. sendCipher: sendCipher,
  64. }, nil
  65. }
  66. func (o Obfuscator) getCipher(f *handshakeFrame, hasher hash.Hash) cipher.Stream {
  67. blockKey := f.key()
  68. if o.Secret != nil {
  69. hasher.Write(blockKey)
  70. hasher.Write(o.Secret)
  71. blockKey = hasher.Sum(nil)
  72. }
  73. block, _ := aes.NewCipher(blockKey)
  74. return cipher.NewCTR(block, f.iv())
  75. }