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.

main.go 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package main
  2. import (
  3. "math/rand"
  4. "os"
  5. "runtime/debug"
  6. "strings"
  7. "time"
  8. kingpin "gopkg.in/alecthomas/kingpin.v2"
  9. "github.com/9seconds/mtg/cli"
  10. "github.com/9seconds/mtg/config"
  11. "github.com/9seconds/mtg/utils"
  12. )
  13. var version = "dev" // has to be set by ldflags
  14. var (
  15. app = kingpin.New("mtg", "Simple MTPROTO proxy.")
  16. generateSecretCommand = app.Command("generate-secret",
  17. "Generate new secret")
  18. generateCloakHost = generateSecretCommand.Flag("cloak-host",
  19. "A host to use for TLS cloaking.").
  20. Short('c').
  21. Default("storage.googleapis.com").
  22. String()
  23. generateSecretType = generateSecretCommand.Arg("type",
  24. "A type of secret to generate. Valid options are 'simple', 'secured' and 'tls'").
  25. Required().
  26. Enum("simple", "secured", "tls")
  27. runCommand = app.Command("run",
  28. "Run new proxy instance")
  29. runDebug = runCommand.Flag("debug",
  30. "Run in debug mode.").
  31. Short('d').
  32. Envar("MTG_DEBUG").
  33. Bool()
  34. runVerbose = runCommand.Flag("verbose",
  35. "Run in verbose mode.").
  36. Short('v').
  37. Envar("MTG_VERBOSE").
  38. Bool()
  39. runBind = runCommand.Flag("bind",
  40. "Host:Port to bind proxy to.").
  41. Short('b').
  42. Envar("MTG_BIND").
  43. Default("0.0.0.0:3128").
  44. TCP()
  45. runPublicIPv4 = runCommand.Flag("public-ipv4",
  46. "Which IPv4 host:port to use.").
  47. Short('4').
  48. Envar("MTG_IPV4").
  49. TCP()
  50. runPublicIPv6 = runCommand.Flag("public-ipv6",
  51. "Which IPv6 host:port to use.").
  52. Short('6').
  53. Envar("MTG_IPV6").
  54. TCP()
  55. runStatsBind = runCommand.Flag("stats-bind",
  56. "Which Host:Port to bind stats server to.").
  57. Short('t').
  58. Envar("MTG_STATS_BIND").
  59. Default("127.0.0.1:3129").
  60. TCP()
  61. runStatsNamespace = runCommand.Flag("stats-namespace",
  62. "Which namespace to use for Prometheus.").
  63. Envar("MTG_STATS_NAMESPACE").
  64. Default("mtg").
  65. String()
  66. runStatsdAddress = runCommand.Flag("statsd-addr",
  67. "Host:port of statsd server").
  68. Envar("MTG_STATSD_ADDR").
  69. TCP()
  70. runStatsdTagsFormat = runCommand.Flag("statsd-tags-format",
  71. "Which tag format should we use to send stats metrics. Valid options are 'datadog' and 'influxdb'.").
  72. Envar("MTG_STATSD_TAGS_FORMAT").
  73. Default("influxdb").
  74. Enum("datadog", "influxdb")
  75. runStatsdTags = runCommand.Flag("statsd-tags",
  76. "Tags to use for working with statsd (specified as 'key=value').").
  77. Envar("MTG_STATSD_TAGS").
  78. StringMap()
  79. runWriteBufferSize = runCommand.Flag("write-buffer",
  80. "Write buffer size. You can think about it as a buffer from client to Telegram.").
  81. Short('w').
  82. Envar("MTG_BUFFER_WRITE").
  83. Default("64KB").
  84. Bytes()
  85. runReadBufferSize = runCommand.Flag("read-buffer",
  86. "Read buffer size. You can think about it as a buffer from Telegram to client.").
  87. Short('r').
  88. Envar("MTG_BUFFER_READ").
  89. Default("128KB").
  90. Bytes()
  91. runTLSCloakPort = runCommand.Flag("cloak-port",
  92. "Port which should be used for host cloaking.").
  93. Envar("MTG_CLOAK_PORT").
  94. Default("443").
  95. Uint16()
  96. runAntiReplayMaxSize = runCommand.Flag("anti-replay-max-size",
  97. "Max size of antireplay cache.").
  98. Envar("MTG_ANTIREPLAY_MAXSIZE").
  99. Default("128MB").
  100. Bytes()
  101. runMultiplexPerConnection = runCommand.Flag("multiplex-per-connection",
  102. "How many clients can share a single connection to Telegram.").
  103. Envar("MTG_MULTIPLEX_PERCONNECTION").
  104. Default("50").
  105. Uint()
  106. runSecret = runCommand.Arg("secret", "Secret of this proxy.").Required().HexBytes()
  107. runAdtag = runCommand.Arg("adtag", "ADTag of the proxy.").HexBytes()
  108. )
  109. func main() {
  110. rand.Seed(time.Now().UTC().UnixNano())
  111. app.Version(getVersion())
  112. app.HelpFlag.Short('h')
  113. if err := utils.SetLimits(); err != nil {
  114. cli.Fatal(err)
  115. }
  116. switch kingpin.MustParse(app.Parse(os.Args[1:])) {
  117. case generateSecretCommand.FullCommand():
  118. cli.Generate(*generateSecretType, *generateCloakHost)
  119. case runCommand.FullCommand():
  120. err := config.Init(
  121. config.Opt{Option: config.OptionTypeDebug, Value: *runDebug},
  122. config.Opt{Option: config.OptionTypeVerbose, Value: *runVerbose},
  123. config.Opt{Option: config.OptionTypeBind, Value: *runBind},
  124. config.Opt{Option: config.OptionTypePublicIPv4, Value: *runPublicIPv4},
  125. config.Opt{Option: config.OptionTypePublicIPv6, Value: *runPublicIPv6},
  126. config.Opt{Option: config.OptionTypeStatsBind, Value: *runStatsBind},
  127. config.Opt{Option: config.OptionTypeStatsNamespace, Value: *runStatsNamespace},
  128. config.Opt{Option: config.OptionTypeStatsdAddress, Value: *runStatsdAddress},
  129. config.Opt{Option: config.OptionTypeStatsdTagsFormat, Value: *runStatsdTagsFormat},
  130. config.Opt{Option: config.OptionTypeStatsdTags, Value: *runStatsdTags},
  131. config.Opt{Option: config.OptionTypeWriteBufferSize, Value: *runWriteBufferSize},
  132. config.Opt{Option: config.OptionTypeReadBufferSize, Value: *runReadBufferSize},
  133. config.Opt{Option: config.OptionTypeCloakPort, Value: *runTLSCloakPort},
  134. config.Opt{Option: config.OptionTypeAntiReplayMaxSize, Value: *runAntiReplayMaxSize},
  135. config.Opt{Option: config.OptionTypeMultiplexPerConnection, Value: *runMultiplexPerConnection},
  136. config.Opt{Option: config.OptionTypeSecret, Value: *runSecret},
  137. config.Opt{Option: config.OptionTypeAdtag, Value: *runAdtag},
  138. )
  139. if err != nil {
  140. cli.Fatal(err)
  141. }
  142. if err := cli.Proxy(); err != nil {
  143. cli.Fatal(err)
  144. }
  145. }
  146. }
  147. func getVersion() string {
  148. if version != "dev" {
  149. return version
  150. }
  151. info, ok := debug.ReadBuildInfo()
  152. if !ok {
  153. return version
  154. }
  155. builder := strings.Builder{}
  156. builder.WriteString(info.Main.Version)
  157. if info.Main.Sum != "" {
  158. builder.WriteString(" (checksum: ")
  159. builder.WriteString(info.Main.Sum)
  160. builder.WriteRune(')')
  161. }
  162. return builder.String()
  163. }