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 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package proxy
  2. import (
  3. "io"
  4. "net"
  5. "sync"
  6. "github.com/juju/errors"
  7. uuid "github.com/satori/go.uuid"
  8. "go.uber.org/zap"
  9. "github.com/9seconds/mtg/client"
  10. "github.com/9seconds/mtg/config"
  11. "github.com/9seconds/mtg/mtproto"
  12. "github.com/9seconds/mtg/telegram"
  13. "github.com/9seconds/mtg/wrappers"
  14. )
  15. type Proxy struct {
  16. clientInit client.Init
  17. tg telegram.Telegram
  18. conf *config.Config
  19. }
  20. func (p *Proxy) Serve() error {
  21. lsock, err := net.Listen("tcp", p.conf.BindAddr())
  22. if err != nil {
  23. return errors.Annotate(err, "Cannot create listen socket")
  24. }
  25. for {
  26. if conn, err := lsock.Accept(); err != nil {
  27. zap.S().Errorw("Cannot allocate incoming connection", "error", err)
  28. } else {
  29. go p.accept(conn)
  30. }
  31. }
  32. }
  33. func (p *Proxy) accept(conn net.Conn) {
  34. connID := uuid.NewV4().String()
  35. log := zap.S().With("connection_id", connID)
  36. defer func() {
  37. conn.Close()
  38. if err := recover(); err != nil {
  39. log.Errorw("Crash of accept handler", "error", err)
  40. }
  41. }()
  42. log.Infow("Client connected", "addr", conn.RemoteAddr())
  43. client, opts, err := p.clientInit(conn, connID, p.conf)
  44. if err != nil {
  45. log.Errorw("Cannot initialize client connection", "error", err)
  46. return
  47. }
  48. defer client.(io.Closer).Close()
  49. server, err := p.getTelegramConn(opts, connID)
  50. if err != nil {
  51. log.Errorw("Cannot initialize server connection", "error", err)
  52. return
  53. }
  54. defer server.(io.Closer).Close()
  55. wait := &sync.WaitGroup{}
  56. wait.Add(2)
  57. if p.conf.UseMiddleProxy() {
  58. clientPacket := client.(wrappers.PacketReadWriteCloser)
  59. serverPacket := server.(wrappers.PacketReadWriteCloser)
  60. go p.middlePipe(clientPacket, serverPacket, wait, &opts.ReadHacks)
  61. go p.middlePipe(serverPacket, clientPacket, wait, &opts.WriteHacks)
  62. } else {
  63. clientStream := client.(wrappers.StreamReadWriteCloser)
  64. serverStream := server.(wrappers.StreamReadWriteCloser)
  65. go p.directPipe(clientStream, serverStream, wait)
  66. go p.directPipe(serverStream, clientStream, wait)
  67. }
  68. wait.Wait()
  69. log.Infow("Client disconnected", "addr", conn.RemoteAddr())
  70. }
  71. func (p *Proxy) getTelegramConn(opts *mtproto.ConnectionOpts, connID string) (wrappers.Wrap, error) {
  72. streamConn, err := p.tg.Dial(connID, opts)
  73. if err != nil {
  74. return nil, errors.Annotate(err, "Cannot dial to Telegram")
  75. }
  76. packetConn, err := p.tg.Init(opts, streamConn)
  77. if err != nil {
  78. return nil, errors.Annotate(err, "Cannot handshake telegram")
  79. }
  80. return packetConn, nil
  81. }
  82. func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst wrappers.PacketWriteCloser, wait *sync.WaitGroup, hacks *mtproto.Hacks) {
  83. defer func() {
  84. src.Close()
  85. dst.Close()
  86. wait.Done()
  87. }()
  88. for {
  89. hacks.SimpleAck = false
  90. hacks.QuickAck = false
  91. packet, err := src.Read()
  92. if err != nil {
  93. src.Logger().Warnw("Cannot read packet", "error", err)
  94. return
  95. }
  96. if _, err = dst.Write(packet); err != nil {
  97. src.Logger().Warnw("Cannot write packet", "error", err)
  98. return
  99. }
  100. }
  101. }
  102. func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst wrappers.StreamWriteCloser, wait *sync.WaitGroup) {
  103. defer func() {
  104. src.Close()
  105. dst.Close()
  106. wait.Done()
  107. }()
  108. if _, err := io.Copy(dst, src); err != nil {
  109. src.Logger().Warnw("Cannot pump sockets", "error", err)
  110. }
  111. }
  112. func NewProxy(conf *config.Config) *Proxy {
  113. var clientInit client.Init
  114. var tg telegram.Telegram
  115. if conf.UseMiddleProxy() {
  116. clientInit = client.MiddleInit
  117. tg = telegram.NewMiddleTelegram(conf)
  118. } else {
  119. clientInit = client.DirectInit
  120. tg = telegram.NewDirectTelegram(conf)
  121. }
  122. return &Proxy{
  123. conf: conf,
  124. clientInit: clientInit,
  125. tg: tg,
  126. }
  127. }