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文字以内のものにしてください。

client_protocol.go 2.7KB

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