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.

base.go 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package telegram
  2. import (
  3. "errors"
  4. "math/rand"
  5. "net"
  6. "github.com/9seconds/mtg/config"
  7. "github.com/9seconds/mtg/conntypes"
  8. "github.com/9seconds/mtg/utils"
  9. "github.com/9seconds/mtg/wrappers/stream"
  10. "go.uber.org/zap"
  11. )
  12. type baseTelegram struct {
  13. dialer net.Dialer
  14. logger *zap.SugaredLogger
  15. secret []byte
  16. v4DefaultDC conntypes.DC
  17. v6DefaultDC conntypes.DC
  18. v4Addresses map[conntypes.DC][]string
  19. v6Addresses map[conntypes.DC][]string
  20. }
  21. func (b *baseTelegram) Secret() []byte {
  22. return b.secret
  23. }
  24. func (b *baseTelegram) dial(dc conntypes.DC,
  25. protocol conntypes.ConnectionProtocol,
  26. ) (conntypes.StreamReadWriteCloser, error) {
  27. for _, addr := range b.getAddresses(dc, protocol) {
  28. conn, err := b.dialer.Dial("tcp", addr)
  29. if err != nil {
  30. b.logger.Infow("Cannot dial to Telegram", "address", addr, "error", err)
  31. continue
  32. }
  33. if err := utils.InitTCP(conn, config.C.ProxyReadBuffer(), config.C.ProxyWriteBuffer()); err != nil {
  34. b.logger.Infow("Cannot initialize TCP socket", "address", addr, "error", err)
  35. continue
  36. }
  37. return stream.NewTelegramConn(dc, conn), nil
  38. }
  39. return nil, errors.New("cannot dial to the chosen DC")
  40. }
  41. func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.ConnectionProtocol) []string {
  42. addresses := make([]string, 0, 2) // nolint: gomnd
  43. protos := []conntypes.ConnectionProtocol{
  44. conntypes.ConnectionProtocolIPv6,
  45. conntypes.ConnectionProtocolIPv4,
  46. }
  47. if config.C.PreferIP == config.PreferIPv4 {
  48. protos[0], protos[1] = protos[1], protos[0]
  49. }
  50. for _, proto := range protos {
  51. switch {
  52. case proto&protocol == 0:
  53. case proto&conntypes.ConnectionProtocolIPv6 != 0:
  54. addresses = append(addresses, b.chooseAddress(b.v6Addresses, dc, b.v6DefaultDC))
  55. case proto&conntypes.ConnectionProtocolIPv4 != 0:
  56. addresses = append(addresses, b.chooseAddress(b.v4Addresses, dc, b.v4DefaultDC))
  57. }
  58. }
  59. return addresses
  60. }
  61. func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,
  62. dc, defaultDC conntypes.DC,
  63. ) string {
  64. addrs, ok := addresses[dc]
  65. if !ok {
  66. addrs = addresses[defaultDC]
  67. }
  68. switch {
  69. case len(addrs) == 1:
  70. return addrs[0]
  71. case len(addrs) > 1:
  72. return addrs[rand.Intn(len(addrs))] // nolint: gosec
  73. }
  74. return ""
  75. }