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
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

proxy.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. flags rpc.ProxyRequestFlags
  15. request *protocol.TelegramRequest
  16. clientIPPort []byte
  17. ourIPPort []byte
  18. channelRead hub.ChannelReadCloser
  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.Write(packet)
  40. return hub.Hub.Write(buf.Bytes(), w.request)
  41. }
  42. func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
  43. resp, err := w.channelRead.Read()
  44. if err != nil {
  45. return nil, fmt.Errorf("cannot read a response: %w", err)
  46. }
  47. if resp.Type == rpc.ProxyResponseTypeSimpleAck {
  48. acks.Simple = true
  49. }
  50. return resp.Payload, nil
  51. }
  52. func (w *wrapperProxy) Close() error {
  53. return w.channelRead.Close()
  54. }
  55. func NewProxy(request *protocol.TelegramRequest) conntypes.PacketAckReadWriteCloser {
  56. flags := rpc.ProxyRequestFlagsHasAdTag | rpc.ProxyRequestFlagsMagic | rpc.ProxyRequestFlagsExtMode2
  57. switch request.ClientProtocol.ConnectionType() {
  58. case conntypes.ConnectionTypeAbridged:
  59. flags |= rpc.ProxyRequestFlagsAbdridged
  60. case conntypes.ConnectionTypeIntermediate:
  61. flags |= rpc.ProxyRequestFlagsIntermediate
  62. case conntypes.ConnectionTypeSecure:
  63. flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
  64. default:
  65. panic("unknown connection type")
  66. }
  67. return &wrapperProxy{
  68. flags: flags,
  69. request: request,
  70. channelRead: hub.Registry.Register(request.ConnID),
  71. clientIPPort: proxyGetIPPort(request.ClientConn.RemoteAddr()),
  72. ourIPPort: proxyGetIPPort(request.ClientConn.LocalAddr()),
  73. }
  74. }
  75. func proxyGetIPPort(addr *net.TCPAddr) []byte {
  76. rv := [16 + 4]byte{}
  77. port := [4]byte{}
  78. copy(rv[:16], addr.IP.To16())
  79. binary.LittleEndian.PutUint32(port[:], uint32(addr.Port))
  80. copy(rv[16:], port[:])
  81. return rv[:]
  82. }