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
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

server.go 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package proxy
  2. import (
  3. "context"
  4. "io"
  5. "net"
  6. "strconv"
  7. "sync"
  8. "time"
  9. "github.com/9seconds/mtg/obfuscated2"
  10. "github.com/juju/errors"
  11. uuid "github.com/satori/go.uuid"
  12. "go.uber.org/zap"
  13. )
  14. const bufferSize = 4096
  15. type Server struct {
  16. ip net.IP
  17. port int
  18. secret []byte
  19. logger *zap.SugaredLogger
  20. lsock net.Listener
  21. ctx context.Context
  22. readTimeout time.Duration
  23. writeTimeout time.Duration
  24. stats *Stats
  25. ipv6 bool
  26. }
  27. func (s *Server) Serve() error {
  28. lsock, err := net.Listen("tcp", s.Addr())
  29. if err != nil {
  30. return errors.Annotate(err, "Cannot create listen socket")
  31. }
  32. for {
  33. if conn, err := lsock.Accept(); err != nil {
  34. s.logger.Warn("Cannot allocate incoming connection", "error", err)
  35. } else {
  36. go s.accept(conn)
  37. }
  38. }
  39. return nil
  40. }
  41. func (s *Server) Addr() string {
  42. return net.JoinHostPort(s.ip.String(), strconv.Itoa(s.port))
  43. }
  44. func (s *Server) accept(conn net.Conn) {
  45. defer func() {
  46. s.stats.closeConnection()
  47. conn.Close()
  48. if r := recover(); r != nil {
  49. s.logger.Errorw("Crash of accept handler", "error", r)
  50. }
  51. }()
  52. s.stats.newConnection()
  53. ctx, cancel := context.WithCancel(context.Background())
  54. socketID := s.makeSocketID()
  55. s.logger.Debugw("Client connected",
  56. "secret", s.secret,
  57. "addr", conn.RemoteAddr().String(),
  58. "socketid", socketID,
  59. )
  60. clientConn, dc, err := s.getClientStream(conn, ctx, cancel, socketID)
  61. if err != nil {
  62. s.logger.Warnw("Cannot initialize client connection",
  63. "secret", s.secret,
  64. "addr", conn.RemoteAddr().String(),
  65. "socketid", socketID,
  66. "error", err,
  67. )
  68. return
  69. }
  70. defer clientConn.Close()
  71. tgConn, err := s.getTelegramStream(dc, ctx, cancel, socketID)
  72. if err != nil {
  73. s.logger.Warnw("Cannot initialize Telegram connection",
  74. "socketid", socketID,
  75. "error", err,
  76. )
  77. return
  78. }
  79. defer tgConn.Close()
  80. wait := &sync.WaitGroup{}
  81. wait.Add(2)
  82. go s.pipe(wait, clientConn, tgConn)
  83. go s.pipe(wait, tgConn, clientConn)
  84. <-ctx.Done()
  85. wait.Wait()
  86. s.logger.Debugw("Client disconnected",
  87. "secret", s.secret,
  88. "addr", conn.RemoteAddr().String(),
  89. "socketid", socketID,
  90. )
  91. }
  92. func (s *Server) makeSocketID() string {
  93. return uuid.NewV4().String()
  94. }
  95. func (s *Server) getClientStream(conn net.Conn, ctx context.Context, cancel context.CancelFunc, socketID string) (io.ReadWriteCloser, int16, error) {
  96. wConn := newTimeoutReadWriteCloser(conn, s.readTimeout, s.writeTimeout)
  97. wConn = newTrafficReadWriteCloser(wConn, s.stats.addIncomingTraffic, s.stats.addOutgoingTraffic)
  98. frame, err := obfuscated2.ExtractFrame(wConn)
  99. if err != nil {
  100. return nil, 0, errors.Annotate(err, "Cannot create client stream")
  101. }
  102. obfs2, dc, err := obfuscated2.ParseObfuscated2ClientFrame(s.secret, frame)
  103. if err != nil {
  104. return nil, 0, errors.Annotate(err, "Cannot create client stream")
  105. }
  106. wConn = newLogReadWriteCloser(wConn, s.logger, socketID, "client")
  107. wConn = newCipherReadWriteCloser(wConn, obfs2)
  108. wConn = newCtxReadWriteCloser(wConn, ctx, cancel)
  109. return wConn, dc, nil
  110. }
  111. func (s *Server) getTelegramStream(dc int16, ctx context.Context, cancel context.CancelFunc, socketID string) (io.ReadWriteCloser, error) {
  112. socket, err := dialToTelegram(s.ipv6, dc, s.readTimeout)
  113. if err != nil {
  114. return nil, errors.Annotate(err, "Cannot dial")
  115. }
  116. wConn := newTimeoutReadWriteCloser(socket, s.readTimeout, s.writeTimeout)
  117. wConn = newTrafficReadWriteCloser(wConn, s.stats.addIncomingTraffic, s.stats.addOutgoingTraffic)
  118. obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame()
  119. if n, err := socket.Write(frame); err != nil || n != len(frame) {
  120. return nil, errors.Annotate(err, "Cannot write hadnshake frame")
  121. }
  122. wConn = newLogReadWriteCloser(wConn, s.logger, socketID, "telegram")
  123. wConn = newCipherReadWriteCloser(wConn, obfs2)
  124. wConn = newCtxReadWriteCloser(wConn, ctx, cancel)
  125. return wConn, nil
  126. }
  127. func (s *Server) pipe(wait *sync.WaitGroup, reader io.Reader, writer io.Writer) {
  128. defer wait.Done()
  129. io.Copy(writer, reader)
  130. }
  131. func NewServer(ip net.IP, port int, secret []byte, logger *zap.SugaredLogger,
  132. readTimeout, writeTimeout time.Duration, ipv6 bool, stat *Stats) *Server {
  133. return &Server{
  134. ip: ip,
  135. port: port,
  136. secret: secret,
  137. ctx: context.Background(),
  138. logger: logger,
  139. readTimeout: readTimeout,
  140. writeTimeout: writeTimeout,
  141. stats: stat,
  142. ipv6: ipv6,
  143. }
  144. }