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个字符

proxy.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package packetack
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "net"
  7. "github.com/9seconds/mtg/config"
  8. "github.com/9seconds/mtg/conntypes"
  9. "github.com/9seconds/mtg/hub"
  10. "github.com/9seconds/mtg/mtproto/rpc"
  11. "github.com/9seconds/mtg/protocol"
  12. )
  13. type wrapperProxy struct {
  14. request *protocol.TelegramRequest
  15. proxy *hub.ProxyConn
  16. clientIPPort []byte
  17. ourIPPort []byte
  18. flags rpc.ProxyRequestFlags
  19. }
  20. func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
  21. buf := bytes.Buffer{}
  22. flags := w.flags
  23. if acks.Quick {
  24. flags |= rpc.ProxyRequestFlagsQuickAck
  25. }
  26. if bytes.HasPrefix(packet, rpc.ProxyRequestFlagsEncryptedPrefix[:]) {
  27. flags |= rpc.ProxyRequestFlagsEncrypted
  28. }
  29. buf.Write(rpc.TagProxyRequest)
  30. buf.Write(flags.Bytes())
  31. buf.Write(w.request.ConnID[:])
  32. buf.Write(w.clientIPPort)
  33. buf.Write(w.ourIPPort)
  34. buf.Write(rpc.ProxyRequestExtraSize)
  35. buf.Write(rpc.ProxyRequestProxyTag)
  36. buf.WriteByte(byte(len(config.C.AdTag)))
  37. buf.Write(config.C.AdTag)
  38. buf.Write(make([]byte, (4-buf.Len()%4)%4))
  39. buf.Grow(len(packet))
  40. buf.Write(packet)
  41. return w.proxy.Write(buf.Bytes())
  42. }
  43. func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
  44. resp, err := w.proxy.Read()
  45. if err != nil {
  46. return nil, fmt.Errorf("cannot read a response: %w", err)
  47. }
  48. if resp.Type == rpc.ProxyResponseTypeSimpleAck {
  49. acks.Simple = true
  50. }
  51. return resp.Payload, nil
  52. }
  53. func (w *wrapperProxy) Close() error {
  54. w.proxy.Close()
  55. return nil
  56. }
  57. func NewProxy(request *protocol.TelegramRequest) (conntypes.PacketAckReadWriteCloser, error) {
  58. flags := rpc.ProxyRequestFlagsHasAdTag | rpc.ProxyRequestFlagsMagic | rpc.ProxyRequestFlagsExtMode2
  59. switch request.ClientProtocol.ConnectionType() {
  60. case conntypes.ConnectionTypeAbridged:
  61. flags |= rpc.ProxyRequestFlagsAbdridged
  62. case conntypes.ConnectionTypeIntermediate:
  63. flags |= rpc.ProxyRequestFlagsIntermediate
  64. case conntypes.ConnectionTypeSecure:
  65. flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
  66. case conntypes.ConnectionTypeUnknown:
  67. panic("unknown connection type")
  68. }
  69. proxy, err := hub.Hub.Register(request)
  70. if err != nil {
  71. return nil, fmt.Errorf("cannot make a new proxy wrapper: %w", err)
  72. }
  73. return &wrapperProxy{
  74. flags: flags,
  75. request: request,
  76. proxy: proxy,
  77. clientIPPort: proxyGetIPPort(request.ClientConn.RemoteAddr()),
  78. ourIPPort: proxyGetIPPort(request.ClientConn.LocalAddr()),
  79. }, nil
  80. }
  81. func proxyGetIPPort(addr *net.TCPAddr) []byte {
  82. rv := [16 + 4]byte{}
  83. port := [4]byte{}
  84. copy(rv[:16], addr.IP.To16())
  85. binary.LittleEndian.PutUint32(port[:], uint32(addr.Port))
  86. copy(rv[16:], port[:])
  87. return rv[:]
  88. }