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.

client_protocol.go 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package faketls
  2. import (
  3. "bufio"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "strconv"
  10. "sync"
  11. "time"
  12. "github.com/9seconds/mtg/config"
  13. "github.com/9seconds/mtg/conntypes"
  14. "github.com/9seconds/mtg/obfuscated2"
  15. "github.com/9seconds/mtg/protocol"
  16. "github.com/9seconds/mtg/tlstypes"
  17. "github.com/9seconds/mtg/wrappers/stream"
  18. )
  19. type ClientProtocol struct {
  20. obfuscated2.ClientProtocol
  21. }
  22. func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) {
  23. rewinded := stream.NewRewind(socket)
  24. bufferedReader := bufio.NewReader(rewinded)
  25. for _, expected := range faketlsStartBytes {
  26. if actual, err := bufferedReader.ReadByte(); err != nil || actual != expected {
  27. rewinded.Rewind()
  28. c.cloakHost(rewinded)
  29. return nil, errors.New("failed first bytes of tls handshake")
  30. }
  31. }
  32. rewinded.Rewind()
  33. rewinded = stream.NewRewind(rewinded)
  34. if err := c.tlsHandshake(rewinded); err != nil {
  35. rewinded.Rewind()
  36. c.cloakHost(rewinded)
  37. return nil, fmt.Errorf("failed tls handshake: %w", err)
  38. }
  39. conn := stream.NewFakeTLS(socket)
  40. conn, err := c.ClientProtocol.Handshake(conn)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return conn, err
  45. }
  46. func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
  47. helloRecord, err := tlstypes.ReadRecord(conn)
  48. if err != nil {
  49. return fmt.Errorf("cannot read initial record: %w", err)
  50. }
  51. clientHello, err := tlstypes.ParseClientHello(helloRecord.Data.Bytes())
  52. if err != nil {
  53. return fmt.Errorf("cannot parse client hello: %w", err)
  54. }
  55. digest := clientHello.Digest()
  56. for i := 0; i < len(digest)-4; i++ {
  57. if digest[i] != 0 {
  58. return errBadDigest
  59. }
  60. }
  61. timestamp := int64(binary.LittleEndian.Uint32(digest[len(digest)-4:]))
  62. createdAt := time.Unix(timestamp, 0)
  63. timeDiff := time.Since(createdAt)
  64. if (timeDiff > TimeSkew || timeDiff < -TimeSkew) && timestamp > TimeFromBoot {
  65. return errBadTime
  66. }
  67. hostCert, err := connectionServerInstance.get()
  68. if err != nil {
  69. return fmt.Errorf("cannot get host certificate: %w", err)
  70. }
  71. serverHello := tlstypes.NewServerHello(clientHello)
  72. serverHelloPacket := serverHello.WelcomePacket(hostCert)
  73. if _, err := conn.Write(serverHelloPacket); err != nil {
  74. return fmt.Errorf("cannot send welcome packet: %w", err)
  75. }
  76. return nil
  77. }
  78. func (c *ClientProtocol) cloakHost(clientConn io.ReadWriteCloser) {
  79. addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort))
  80. hostConn, err := net.Dial("tcp", addr)
  81. if err != nil {
  82. return
  83. }
  84. defer hostConn.Close()
  85. wg := &sync.WaitGroup{}
  86. wg.Add(2)
  87. go c.pipe(hostConn, clientConn, wg)
  88. go c.pipe(clientConn, hostConn, wg)
  89. wg.Wait()
  90. }
  91. func (c *ClientProtocol) pipe(dst io.WriteCloser, src io.Reader, wg *sync.WaitGroup) {
  92. defer func() {
  93. wg.Done()
  94. dst.Close()
  95. }()
  96. io.Copy(dst, src) // nolint: errcheck
  97. }
  98. func MakeClientProtocol() protocol.ClientProtocol {
  99. return &ClientProtocol{}
  100. }