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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package config2
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "net"
  7. "strconv"
  8. "sync"
  9. "time"
  10. "github.com/juju/errors"
  11. statsd "gopkg.in/alexcesaro/statsd.v2"
  12. )
  13. type SecretType byte
  14. func (s SecretType) String() string {
  15. switch s {
  16. case SecretTypeMain:
  17. return "main"
  18. case SecretTypeSecured:
  19. return "secured"
  20. default:
  21. return "tls"
  22. }
  23. }
  24. const (
  25. SecretTypeMain = 1 << iota
  26. SecretTypeSecured
  27. SecretTypeTLS
  28. )
  29. const (
  30. FlagDebug = "debug"
  31. FlagVerbose = "verbose"
  32. FlagBindIP = "bind-ip"
  33. FlagBindPort = "bind-port"
  34. FlagPublicIPv4 = "public-ipv4"
  35. FlagPublicIPv4Port = "public-ipv4-port"
  36. FlagPublicIPv6 = "public-ipv6"
  37. FlagPublicIPv6Port = "public-ipv6-port"
  38. FlagStatsIP = "stats-ip"
  39. FlagStatsPort = "stats-port"
  40. FlagStatsdIP = "statsd-ip"
  41. FlagStatsdPort = "statsd-port"
  42. FlagStatsdNetwork = "statsd-network"
  43. FlagStatsdPrefix = "statsd-prefix"
  44. FlagStatsdTagsFormat = "statsd-tags-format"
  45. FlagStatsdTags = "statsd-tags"
  46. FlagPrometheusPrefix = "prometheus-prefix"
  47. FlagWriteBufferSize = "write-buffer"
  48. FlagReadBufferSize = "read-buffer"
  49. FlagSecureOnly = "secure-only"
  50. FlagAntiReplayMaxSize = "anti-replay-max-size"
  51. FlagAntiReplayEvictionTime = "anti-replay-eviction-time"
  52. FlagSecret = "secret"
  53. FlagAdtag = "adtag"
  54. )
  55. type BufferSize struct {
  56. Read int `json:"read"`
  57. Write int `json:"write"`
  58. }
  59. type AntiReplay struct {
  60. MaxSize int `json:"max_size"`
  61. EvictionTime time.Duration `json:"duration"`
  62. }
  63. type Stats struct {
  64. Prefix string `json:"prefix"`
  65. Enabled bool `json:"enabled"`
  66. }
  67. type StatsdStats struct {
  68. Stats
  69. Addr Addr `json:"addr"`
  70. Tags map[string]string `json:"tags"`
  71. TagsFormat statsd.TagFormat `json:"format"`
  72. }
  73. type PrometheusStats struct {
  74. Stats
  75. }
  76. type Addr struct {
  77. IP net.IP `json:"ip"`
  78. Port int `json:"port"`
  79. net string
  80. }
  81. func (a Addr) Network() string {
  82. if a.net == "" {
  83. return "tcp"
  84. }
  85. return a.net
  86. }
  87. func (a Addr) String() string {
  88. return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
  89. }
  90. func (a Addr) MarshalJSON() ([]byte, error) {
  91. data := map[string]string{
  92. "network": a.Network(),
  93. "addr": a.String(),
  94. }
  95. return json.Marshal(data)
  96. }
  97. type Config struct {
  98. BufferSize BufferSize `json:"buffer_size"`
  99. AntiReplay AntiReplay `json:"anti_replay"`
  100. ListenAddr Addr `json:"listen_addr"`
  101. PublicIPv4Addr Addr `json:"public_ipv4_addr"`
  102. PublicIPv6Addr Addr `json:"public_ipv6_addr"`
  103. StatsAddr Addr `json:"stats_addr"`
  104. StatsdStats StatsdStats `json:"stats_statsd"`
  105. PrometheusStats PrometheusStats `json:"stats_prometheus"`
  106. Debug bool `json:"debug"`
  107. Verbose bool `json:"verbose"`
  108. SecureOnly bool `json:"secure_only"`
  109. SecretType SecretType `json:"secret_type"`
  110. Secret []byte `json:"secret"`
  111. AdTag []byte `json:"adtag"`
  112. }
  113. func (c Config) String() string {
  114. data, _ := json.Marshal(c)
  115. return string(data)
  116. }
  117. type ConfigOpt struct {
  118. Name string
  119. Value interface{}
  120. }
  121. var C = Config{}
  122. func Init(options ...ConfigOpt) error { // nolint: gocyclo
  123. for _, opt := range options {
  124. switch opt.Name {
  125. case FlagDebug:
  126. C.Debug = opt.Value.(bool)
  127. case FlagVerbose:
  128. C.Verbose = opt.Value.(bool)
  129. case FlagBindIP:
  130. C.ListenAddr.IP = opt.Value.(net.IP)
  131. case FlagBindPort:
  132. C.ListenAddr.Port = opt.Value.(int)
  133. case FlagPublicIPv4:
  134. C.PublicIPv4Addr.IP = opt.Value.(net.IP)
  135. case FlagPublicIPv4Port:
  136. C.PublicIPv4Addr.Port = opt.Value.(int)
  137. case FlagPublicIPv6:
  138. C.PublicIPv6Addr.IP = opt.Value.(net.IP)
  139. case FlagPublicIPv6Port:
  140. C.PublicIPv6Addr.Port = opt.Value.(int)
  141. case FlagStatsIP:
  142. C.StatsAddr.IP = opt.Value.(net.IP)
  143. case FlagStatsPort:
  144. C.StatsAddr.Port = opt.Value.(int)
  145. case FlagStatsdIP:
  146. C.StatsdStats.Addr.IP = opt.Value.(net.IP)
  147. case FlagStatsdPort:
  148. C.StatsdStats.Addr.Port = opt.Value.(int)
  149. case FlagStatsdNetwork:
  150. C.StatsdStats.Addr.net = opt.Value.(string)
  151. case FlagStatsdPrefix:
  152. C.StatsdStats.Prefix = opt.Value.(string)
  153. case FlagStatsdTagsFormat:
  154. value := opt.Value.(string)
  155. switch value {
  156. case "datadog":
  157. C.StatsdStats.TagsFormat = statsd.Datadog
  158. case "influxdb":
  159. C.StatsdStats.TagsFormat = statsd.InfluxDB
  160. default:
  161. return errors.Errorf("Incorrect statsd tag %s", value)
  162. }
  163. case FlagStatsdTags:
  164. C.StatsdStats.Tags = opt.Value.(map[string]string)
  165. case FlagPrometheusPrefix:
  166. C.PrometheusStats.Prefix = opt.Value.(string)
  167. case FlagWriteBufferSize:
  168. C.BufferSize.Write = opt.Value.(int)
  169. case FlagReadBufferSize:
  170. C.BufferSize.Read = opt.Value.(int)
  171. case FlagAntiReplayMaxSize:
  172. C.AntiReplay.MaxSize = opt.Value.(int)
  173. case FlagAntiReplayEvictionTime:
  174. C.AntiReplay.EvictionTime = opt.Value.(time.Duration)
  175. case FlagSecureOnly:
  176. C.SecureOnly = opt.Value.(bool)
  177. case FlagSecret:
  178. C.Secret = opt.Value.([]byte)
  179. case FlagAdtag:
  180. C.AdTag = opt.Value.([]byte)
  181. }
  182. }
  183. var defaultStatsdTags statsd.TagFormat
  184. if C.StatsdStats.TagsFormat == defaultStatsdTags {
  185. C.StatsdStats.TagsFormat = statsd.Datadog
  186. }
  187. if C.StatsdStats.Addr.net == "" {
  188. C.StatsdStats.Addr.net = "udp"
  189. }
  190. switch {
  191. case len(C.Secret) == 17 && bytes.HasPrefix(C.Secret, []byte{0xdd}):
  192. C.SecretType = SecretTypeSecured
  193. C.Secret = bytes.TrimPrefix(C.Secret, []byte{0xdd})
  194. case len(C.Secret) == 16:
  195. C.SecretType = SecretTypeMain
  196. default:
  197. return errors.New("Incorrect secret")
  198. }
  199. return nil
  200. }
  201. func InitPublicAddress() error {
  202. if C.PublicIPv4Addr.Port == 0 {
  203. C.PublicIPv4Addr.Port = C.ListenAddr.Port
  204. }
  205. if C.PublicIPv6Addr.Port == 0 {
  206. C.PublicIPv6Addr.Port = C.ListenAddr.Port
  207. }
  208. ctx, cancel := context.WithCancel(context.Background())
  209. defer cancel()
  210. wg := &sync.WaitGroup{}
  211. done := make(chan struct{})
  212. if C.PublicIPv4Addr.IP == nil {
  213. wg.Add(1)
  214. go func() {
  215. getGlobalIPv4(ctx, cancel)
  216. wg.Done()
  217. }()
  218. }
  219. if C.PublicIPv6Addr.IP == nil {
  220. wg.Add(1)
  221. go func() {
  222. getGlobalIPv6(ctx, cancel)
  223. wg.Done()
  224. }()
  225. }
  226. go func() {
  227. wg.Wait()
  228. close(done)
  229. }()
  230. select {
  231. case <-done:
  232. return nil
  233. case <-ctx.Done():
  234. return ctx.Err()
  235. }
  236. }