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_test.go 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package mtglib_test
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "encoding/hex"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "net"
  10. "net/http"
  11. "testing"
  12. "time"
  13. "github.com/9seconds/mtg/v2/antireplay"
  14. "github.com/9seconds/mtg/v2/events"
  15. "github.com/9seconds/mtg/v2/ipblocklist"
  16. "github.com/9seconds/mtg/v2/ipblocklist/files"
  17. "github.com/9seconds/mtg/v2/logger"
  18. "github.com/9seconds/mtg/v2/mtglib"
  19. "github.com/9seconds/mtg/v2/network"
  20. "github.com/gotd/td/telegram"
  21. "github.com/gotd/td/telegram/dcs"
  22. "github.com/gotd/td/tg"
  23. "github.com/stretchr/testify/suite"
  24. "github.com/yl2chen/cidranger"
  25. )
  26. type ProxyTestSuite struct {
  27. suite.Suite
  28. opts *mtglib.ProxyOpts
  29. p *mtglib.Proxy
  30. listener net.Listener
  31. }
  32. func (suite *ProxyTestSuite) ProxyAddress() string {
  33. _, port, _ := net.SplitHostPort(suite.listener.Addr().String())
  34. return net.JoinHostPort("127.0.0.1", port)
  35. }
  36. func (suite *ProxyTestSuite) ProxySecret() string {
  37. return suite.opts.Secret.Hex()
  38. }
  39. func (suite *ProxyTestSuite) SetupSuite() {
  40. dialer, err := network.NewDefaultDialer(0, 0)
  41. suite.NoError(err)
  42. ntw, err := network.NewNetwork(dialer, "mtgtest", "1.1.1.1", 0)
  43. suite.NoError(err)
  44. allowlist, _ := ipblocklist.NewFireholFromFiles(
  45. logger.NewNoopLogger(),
  46. 1,
  47. []files.File{
  48. files.NewMem([]*net.IPNet{
  49. cidranger.AllIPv4,
  50. cidranger.AllIPv6,
  51. }),
  52. },
  53. nil,
  54. )
  55. go allowlist.Run(time.Second)
  56. suite.opts = &mtglib.ProxyOpts{
  57. Secret: mtglib.GenerateSecret("httpbin.org"),
  58. Network: ntw,
  59. AntiReplayCache: antireplay.NewNoop(),
  60. IPBlocklist: ipblocklist.NewNoop(),
  61. IPAllowlist: allowlist,
  62. EventStream: events.NewNoopStream(),
  63. Logger: logger.NewNoopLogger(),
  64. UseTestDCs: true,
  65. }
  66. proxy, err := mtglib.NewProxy(*suite.opts)
  67. suite.NoError(err)
  68. suite.p = proxy
  69. listener, err := net.Listen("tcp", ":0")
  70. suite.NoError(err)
  71. suite.listener = listener
  72. go suite.p.Serve(suite.listener) // nolint: errcheck
  73. }
  74. func (suite *ProxyTestSuite) TearDownSuite() {
  75. if suite.listener != nil {
  76. suite.listener.Close()
  77. }
  78. if suite.p != nil {
  79. suite.p.Shutdown()
  80. }
  81. }
  82. func (suite *ProxyTestSuite) TestCannotInitNoSecret() {
  83. opts := *suite.opts
  84. opts.Secret = mtglib.Secret{}
  85. _, err := mtglib.NewProxy(opts)
  86. suite.Error(err)
  87. }
  88. func (suite *ProxyTestSuite) TestCannotInitNoNetwork() {
  89. opts := *suite.opts
  90. opts.Network = nil
  91. _, err := mtglib.NewProxy(opts)
  92. suite.Error(err)
  93. }
  94. func (suite *ProxyTestSuite) TestCannotInitNoAntiReplayCache() {
  95. opts := *suite.opts
  96. opts.AntiReplayCache = nil
  97. _, err := mtglib.NewProxy(opts)
  98. suite.Error(err)
  99. }
  100. func (suite *ProxyTestSuite) TestCannotInitNoIPBlocklist() {
  101. opts := *suite.opts
  102. opts.IPBlocklist = nil
  103. _, err := mtglib.NewProxy(opts)
  104. suite.Error(err)
  105. }
  106. func (suite *ProxyTestSuite) TestCannotInitNoIPAllowlist() {
  107. opts := *suite.opts
  108. opts.IPAllowlist = nil
  109. _, err := mtglib.NewProxy(opts)
  110. suite.Error(err)
  111. }
  112. func (suite *ProxyTestSuite) TestCannotInitNoEventStream() {
  113. opts := *suite.opts
  114. opts.EventStream = nil
  115. _, err := mtglib.NewProxy(opts)
  116. suite.Error(err)
  117. }
  118. func (suite *ProxyTestSuite) TestCannotInitNoLogger() {
  119. opts := *suite.opts
  120. opts.Logger = nil
  121. _, err := mtglib.NewProxy(opts)
  122. suite.Error(err)
  123. }
  124. func (suite *ProxyTestSuite) TestCannotInitIncorrectPreferIP() {
  125. opts := *suite.opts
  126. opts.PreferIP = "xxx"
  127. _, err := mtglib.NewProxy(opts)
  128. suite.Error(err)
  129. }
  130. func (suite *ProxyTestSuite) TestDomainFrontingAddress() {
  131. suite.Equal("httpbin.org:443", suite.p.DomainFrontingAddress())
  132. }
  133. func (suite *ProxyTestSuite) TestHTTPSRequest() {
  134. client := &http.Client{
  135. Transport: &http.Transport{
  136. TLSClientConfig: &tls.Config{
  137. InsecureSkipVerify: true,
  138. },
  139. },
  140. Timeout: 5 * time.Second,
  141. }
  142. addr := fmt.Sprintf("https://%s/headers", suite.ProxyAddress())
  143. resp, err := client.Get(addr) // nolint: noctx
  144. suite.NoError(err)
  145. defer resp.Body.Close()
  146. suite.Equal(http.StatusOK, resp.StatusCode)
  147. data, err := io.ReadAll(resp.Body)
  148. suite.NoError(err)
  149. jsonStruct := struct {
  150. Headers struct {
  151. TraceID string `json:"X-Amzn-Trace-Id"` // nolint: tagliatelle
  152. } `json:"headers"`
  153. }{}
  154. suite.NoError(json.Unmarshal(data, &jsonStruct))
  155. suite.NotEmpty(jsonStruct.Headers.TraceID)
  156. }
  157. func (suite *ProxyTestSuite) TestMakeRealRequest() {
  158. secret, _ := hex.DecodeString(suite.opts.Secret.Hex())
  159. resolver, err := dcs.MTProxyResolver(
  160. suite.ProxyAddress(),
  161. secret,
  162. dcs.MTProxyOptions{},
  163. )
  164. suite.NoError(err)
  165. tgClient := telegram.NewClient(telegram.TestAppID,
  166. telegram.TestAppHash,
  167. telegram.Options{
  168. Resolver: resolver,
  169. })
  170. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  171. defer cancel()
  172. suite.NoError(tgClient.Run(ctx, func(ctx context.Context) error {
  173. _, err := tg.NewClient(tgClient).HelpGetConfig(ctx)
  174. suite.NoError(err)
  175. return err // nolint: wrapcheck
  176. }))
  177. }
  178. func TestProxy(t *testing.T) {
  179. t.Parallel()
  180. suite.Run(t, &ProxyTestSuite{})
  181. }