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
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package mtproto
  2. import (
  3. "fmt"
  4. "github.com/9seconds/mtg/conntypes"
  5. "github.com/9seconds/mtg/mtproto/rpc"
  6. "github.com/9seconds/mtg/protocol"
  7. "github.com/9seconds/mtg/telegram"
  8. "github.com/9seconds/mtg/wrappers"
  9. )
  10. func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteCloser, error) {
  11. conn, err := telegram.Middle.Dial(req.ClientProtocol.DC(),
  12. req.ClientProtocol.ConnectionProtocol())
  13. if err != nil {
  14. return nil, fmt.Errorf("cannot connect to telegram: %w", err)
  15. }
  16. rpcNonceConn := wrappers.NewMtprotoFrame(conn, rpc.SeqNoNonce)
  17. rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
  18. if err != nil {
  19. return nil, fmt.Errorf("cannot do nonce request: %w", err)
  20. }
  21. rpcNonceResp, err := getRPCNonceResponse(rpcNonceConn, rpcNonceReq)
  22. if err != nil {
  23. return nil, fmt.Errorf("cannot get nonce response: %w", err)
  24. }
  25. secureConn := wrappers.NewMiddleProxyCipher(conn, rpcNonceReq, rpcNonceResp, telegram.Middle.Secret())
  26. frameConn := wrappers.NewMtprotoFrame(secureConn, rpc.SeqNoHandshake)
  27. if err := doRPCHandshakeRequest(frameConn); err != nil {
  28. return nil, fmt.Errorf("cannot do handshake request: %w", err)
  29. }
  30. if err := getRPCHandshakeResponse(frameConn); err != nil {
  31. return nil, fmt.Errorf("cannot get handshake response: %w", err)
  32. }
  33. return frameConn, nil
  34. }
  35. func doRPCNonceRequest(conn conntypes.PacketWriter) (*rpc.NonceRequest, error) {
  36. rpcNonceReq, err := rpc.NewNonceRequest(telegram.Middle.Secret())
  37. if err != nil {
  38. panic(err)
  39. }
  40. if err := conn.Write(rpcNonceReq.Bytes()); err != nil {
  41. return nil, err
  42. }
  43. return rpcNonceReq, nil
  44. }
  45. func getRPCNonceResponse(conn conntypes.PacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) {
  46. packet, err := conn.Read()
  47. if err != nil {
  48. return nil, fmt.Errorf("cannot read from connection: %w", err)
  49. }
  50. resp, err := rpc.NewNonceResponse(packet)
  51. if err != nil {
  52. return nil, fmt.Errorf("cannot build rpc nonce responce: %w", err)
  53. }
  54. if err = resp.Valid(req); err != nil {
  55. return nil, fmt.Errorf("invalid nonce response: %w", err)
  56. }
  57. return resp, nil
  58. }
  59. func doRPCHandshakeRequest(conn conntypes.PacketWriter) error {
  60. if err := conn.Write(rpc.HandshakeRequest); err != nil {
  61. return fmt.Errorf("cannot make a request: %w", err)
  62. }
  63. return nil
  64. }
  65. func getRPCHandshakeResponse(conn conntypes.PacketReader) error {
  66. packet, err := conn.Read()
  67. if err != nil {
  68. return fmt.Errorf("cannot read a response: %w", err)
  69. }
  70. resp, err := rpc.NewHandshakeResponse(packet)
  71. if err != nil {
  72. return fmt.Errorf("cannot build a handshake response: %w", err)
  73. }
  74. if err := resp.Valid(); err != nil {
  75. return fmt.Errorf("invalid handshake response: %w", err)
  76. }
  77. return nil
  78. }