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.

welcome.go 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package faketls
  2. import (
  3. "crypto/hmac"
  4. "crypto/rand"
  5. "crypto/sha256"
  6. "encoding/binary"
  7. "io"
  8. mrand "math/rand"
  9. "github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
  10. "golang.org/x/crypto/curve25519"
  11. )
  12. func SendWelcomePacket(writer io.Writer, secret []byte, clientHello ClientHello) error {
  13. buf := acquireBytesBuffer()
  14. defer releaseBytesBuffer(buf)
  15. rec := record.AcquireRecord()
  16. defer record.ReleaseRecord(rec)
  17. rec.Type = record.TypeHandshake
  18. rec.Version = record.Version12
  19. generateServerHello(&rec.Payload, clientHello)
  20. rec.Dump(buf) //nolint: errcheck
  21. rec.Reset()
  22. rec.Type = record.TypeChangeCipherSpec
  23. rec.Version = record.Version12
  24. rec.Payload.WriteByte(ChangeCipherValue)
  25. rec.Dump(buf) //nolint: errcheck
  26. rec.Reset()
  27. rec.Type = record.TypeApplicationData
  28. rec.Version = record.Version12
  29. if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.Intn(3092))); err != nil {
  30. panic(err)
  31. }
  32. rec.Dump(buf) //nolint: errcheck
  33. packet := buf.Bytes()
  34. mac := hmac.New(sha256.New, secret)
  35. mac.Write(clientHello.Random[:])
  36. mac.Write(packet)
  37. copy(packet[WelcomePacketRandomOffset:], mac.Sum(nil))
  38. if _, err := writer.Write(packet); err != nil {
  39. return err //nolint: wrapcheck
  40. }
  41. return nil
  42. }
  43. func generateServerHello(writer io.Writer, clientHello ClientHello) {
  44. bodyBuf := acquireBytesBuffer()
  45. defer releaseBytesBuffer(bodyBuf)
  46. sliceBuf := [2]byte{}
  47. digest := [RandomLen]byte{}
  48. binary.BigEndian.PutUint16(sliceBuf[:], uint16(record.Version12))
  49. bodyBuf.Write(sliceBuf[:])
  50. bodyBuf.Write(digest[:])
  51. bodyBuf.WriteByte(byte(len(clientHello.SessionID)))
  52. bodyBuf.Write(clientHello.SessionID)
  53. binary.BigEndian.PutUint16(sliceBuf[:], clientHello.CipherSuite)
  54. bodyBuf.Write(sliceBuf[:])
  55. bodyBuf.Write(serverHelloSuffix)
  56. scalar := [32]byte{}
  57. if _, err := rand.Read(scalar[:]); err != nil {
  58. panic(err)
  59. }
  60. curve, _ := curve25519.X25519(scalar[:], curve25519.Basepoint)
  61. bodyBuf.Write(curve)
  62. header := [4]byte{0, 0, 0, 0}
  63. binary.BigEndian.PutUint32(header[:], uint32(bodyBuf.Len()))
  64. header[0] = HandshakeTypeServer
  65. writer.Write(header[:]) //nolint: errcheck
  66. bodyBuf.WriteTo(writer) //nolint: errcheck
  67. }