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

rpc_proxy_request.go 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package rpc
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/binary"
  6. "net"
  7. "github.com/juju/errors"
  8. "github.com/9seconds/mtg/mtproto"
  9. )
  10. const (
  11. rpcProxyRequestConnectionIDLength = 8
  12. rpcProxyRequestIPPortLength = 16 + 4
  13. )
  14. var (
  15. rpcProxyRequestTag = []byte{0xee, 0xf1, 0xce, 0x36}
  16. rpcProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00}
  17. rpcProxyRequestProxyTag = []byte{0xae, 0x26, 0x1e, 0xdb}
  18. )
  19. type RPCProxyRequest struct {
  20. Flags RPCProxyRequestFlags
  21. ConnectionID [rpcProxyRequestConnectionIDLength]byte
  22. RemoteIPPort [rpcProxyRequestIPPortLength]byte
  23. LocalIPPort [rpcProxyRequestIPPortLength]byte
  24. ADTag []byte
  25. Extras Extras
  26. }
  27. func (r *RPCProxyRequest) Bytes(message []byte) []byte {
  28. buf := &bytes.Buffer{}
  29. flags := r.Flags
  30. if r.Extras.QuickAck {
  31. flags |= RPCProxyRequestFlagsQuickAck
  32. }
  33. if bytes.HasPrefix(message, rpcProxyRequestFlagsEncryptedPrefix[:]) {
  34. flags |= RPCProxyRequestFlagsEncrypted
  35. }
  36. buf.Write(rpcProxyRequestTag)
  37. buf.Write(flags.Bytes())
  38. buf.Write(r.ConnectionID[:])
  39. buf.Write(r.RemoteIPPort[:])
  40. buf.Write(r.LocalIPPort[:])
  41. buf.Write(rpcProxyRequestExtraSize)
  42. buf.Write(rpcProxyRequestProxyTag)
  43. buf.WriteByte(byte(len(r.ADTag)))
  44. buf.Write(r.ADTag)
  45. for i := 0; i < (buf.Len() % 4); i++ {
  46. buf.WriteByte(0x00)
  47. }
  48. buf.Write(message)
  49. return buf.Bytes()
  50. }
  51. func NewRPCProxyRequest(connectionType mtproto.ConnectionType, local, remote *net.TCPAddr, adTag []byte, extras Extras) (*RPCProxyRequest, error) {
  52. flags := RPCProxyRequestFlagsHasAdTag | RPCProxyRequestFlagsMagic | RPCProxyRequestFlagsExtMode2
  53. switch connectionType {
  54. case mtproto.ConnectionTypeAbridged:
  55. flags |= RPCProxyRequestFlagsAbdridged
  56. case mtproto.ConnectionTypeIntermediate:
  57. flags |= RPCProxyRequestFlagsIntermediate
  58. }
  59. request := RPCProxyRequest{
  60. Flags: flags,
  61. ADTag: adTag,
  62. Extras: extras,
  63. }
  64. if _, err := rand.Read(request.ConnectionID[:]); err != nil {
  65. return nil, errors.Annotate(err, "Cannot generate connection ID")
  66. }
  67. port := make([]byte, 4)
  68. copy(request.LocalIPPort[:], local.IP.To16())
  69. binary.LittleEndian.PutUint32(port, uint32(local.Port))
  70. copy(request.LocalIPPort[16:], port)
  71. copy(request.RemoteIPPort[:], remote.IP.To16())
  72. binary.LittleEndian.PutUint32(port, uint32(remote.Port))
  73. copy(request.RemoteIPPort[16:], port)
  74. return &request, nil
  75. }