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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package mtglib_test
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "net"
  8. "net/http"
  9. "testing"
  10. "time"
  11. "github.com/9seconds/mtg/v2/antireplay"
  12. "github.com/9seconds/mtg/v2/events"
  13. "github.com/9seconds/mtg/v2/ipblocklist"
  14. "github.com/9seconds/mtg/v2/logger"
  15. "github.com/9seconds/mtg/v2/mtglib"
  16. "github.com/9seconds/mtg/v2/network"
  17. "github.com/9seconds/mtg/v2/timeattack"
  18. "github.com/stretchr/testify/suite"
  19. )
  20. type ProxyTestSuite struct {
  21. suite.Suite
  22. opts *mtglib.ProxyOpts
  23. p *mtglib.Proxy
  24. listener net.Listener
  25. }
  26. func (suite *ProxyTestSuite) ProxyAddress() string {
  27. _, port, _ := net.SplitHostPort(suite.listener.Addr().String())
  28. return net.JoinHostPort("127.0.0.1", port)
  29. }
  30. func (suite *ProxyTestSuite) ProxySecret() string {
  31. return suite.opts.Secret.Hex()
  32. }
  33. func (suite *ProxyTestSuite) SetupSuite() {
  34. dialer, err := network.NewDefaultDialer(0, 0)
  35. suite.NoError(err)
  36. ntw, err := network.NewNetwork(dialer, "mtgtest", "1.1.1.1", 0)
  37. suite.NoError(err)
  38. suite.opts = &mtglib.ProxyOpts{
  39. Secret: mtglib.GenerateSecret("httpbin.org"),
  40. Network: ntw,
  41. AntiReplayCache: antireplay.NewNoop(),
  42. TimeAttackDetector: timeattack.NewNoop(),
  43. IPBlocklist: ipblocklist.NewNoop(),
  44. EventStream: events.NewNoopStream(),
  45. Logger: logger.NewNoopLogger(),
  46. }
  47. proxy, err := mtglib.NewProxy(*suite.opts)
  48. suite.NoError(err)
  49. suite.p = proxy
  50. listener, err := net.Listen("tcp", ":0")
  51. suite.NoError(err)
  52. suite.listener = listener
  53. go suite.p.Serve(suite.listener) // nolint: errcheck
  54. }
  55. func (suite *ProxyTestSuite) TearDownSuite() {
  56. if suite.listener != nil {
  57. suite.listener.Close()
  58. }
  59. if suite.p != nil {
  60. suite.p.Shutdown()
  61. }
  62. }
  63. func (suite *ProxyTestSuite) TestCannotInitNoSecret() {
  64. opts := *suite.opts
  65. opts.Secret = mtglib.Secret{}
  66. _, err := mtglib.NewProxy(opts)
  67. suite.Error(err)
  68. }
  69. func (suite *ProxyTestSuite) TestCannotInitNoNetwork() {
  70. opts := *suite.opts
  71. opts.Network = nil
  72. _, err := mtglib.NewProxy(opts)
  73. suite.Error(err)
  74. }
  75. func (suite *ProxyTestSuite) TestCannotInitNoAntiReplayCache() {
  76. opts := *suite.opts
  77. opts.AntiReplayCache = nil
  78. _, err := mtglib.NewProxy(opts)
  79. suite.Error(err)
  80. }
  81. func (suite *ProxyTestSuite) TestCannotInitNoIPBlocklist() {
  82. opts := *suite.opts
  83. opts.IPBlocklist = nil
  84. _, err := mtglib.NewProxy(opts)
  85. suite.Error(err)
  86. }
  87. func (suite *ProxyTestSuite) TestCannotInitNoEventStream() {
  88. opts := *suite.opts
  89. opts.EventStream = nil
  90. _, err := mtglib.NewProxy(opts)
  91. suite.Error(err)
  92. }
  93. func (suite *ProxyTestSuite) TestCannotInitNoTimeAttackDetector() {
  94. opts := *suite.opts
  95. opts.TimeAttackDetector = nil
  96. _, err := mtglib.NewProxy(opts)
  97. suite.Error(err)
  98. }
  99. func (suite *ProxyTestSuite) TestCannotInitNoLogger() {
  100. opts := *suite.opts
  101. opts.Logger = nil
  102. _, err := mtglib.NewProxy(opts)
  103. suite.Error(err)
  104. }
  105. func (suite *ProxyTestSuite) TestCannotInitIncorrectPreferIP() {
  106. opts := *suite.opts
  107. opts.PreferIP = "xxx"
  108. _, err := mtglib.NewProxy(opts)
  109. suite.Error(err)
  110. }
  111. func (suite *ProxyTestSuite) TestDomainFrontingAddress() {
  112. suite.Equal("httpbin.org:443", suite.p.DomainFrontingAddress())
  113. }
  114. func (suite *ProxyTestSuite) TestHTTPSRequest() {
  115. client := &http.Client{
  116. Transport: &http.Transport{
  117. TLSClientConfig: &tls.Config{
  118. InsecureSkipVerify: true,
  119. },
  120. },
  121. Timeout: 5 * time.Second,
  122. }
  123. addr := fmt.Sprintf("https://%s/headers", suite.ProxyAddress())
  124. resp, err := client.Get(addr) // nolint: noctx
  125. suite.NoError(err)
  126. defer resp.Body.Close()
  127. suite.Equal(http.StatusOK, resp.StatusCode)
  128. data, err := io.ReadAll(resp.Body)
  129. suite.NoError(err)
  130. jsonStruct := struct {
  131. Headers struct {
  132. TraceID string `json:"X-Amzn-Trace-Id"`
  133. } `json:"headers"`
  134. }{}
  135. suite.NoError(json.Unmarshal(data, &jsonStruct))
  136. suite.NotEmpty(jsonStruct.Headers.TraceID)
  137. }
  138. func TestProxy(t *testing.T) {
  139. t.Parallel()
  140. suite.Run(t, &ProxyTestSuite{})
  141. }