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
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

config.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package config
  2. import (
  3. "bytes"
  4. "encoding/hex"
  5. "fmt"
  6. "net"
  7. "strconv"
  8. "time"
  9. "github.com/juju/errors"
  10. statsd "gopkg.in/alexcesaro/statsd.v2"
  11. )
  12. // Config represents common configuration of mtg.
  13. type Config struct {
  14. Debug bool
  15. Verbose bool
  16. SecureMode bool
  17. SecureOnly bool
  18. ReadBufferSize int
  19. WriteBufferSize int
  20. BindPort uint16
  21. PublicIPv4Port uint16
  22. PublicIPv6Port uint16
  23. StatsPort uint16
  24. BindIP net.IP
  25. PublicIPv4 net.IP
  26. PublicIPv6 net.IP
  27. StatsIP net.IP
  28. AntiReplayMaxSize int
  29. AntiReplayEvictionTime time.Duration
  30. StatsD struct {
  31. Addr net.Addr
  32. Prefix string
  33. Tags map[string]string
  34. TagsFormat statsd.TagFormat
  35. Enabled bool
  36. }
  37. Prometheus struct {
  38. Prefix string
  39. }
  40. Secret []byte
  41. AdTag []byte
  42. }
  43. // URLs contains links to the proxy (tg://, t.me) and their QR codes.
  44. type URLs struct {
  45. TG string `json:"tg_url"`
  46. TMe string `json:"tme_url"`
  47. TGQRCode string `json:"tg_qrcode"`
  48. TMeQRCode string `json:"tme_qrcode"`
  49. }
  50. // IPURLs contains links to both ipv4 and ipv6 of the proxy.
  51. type IPURLs struct {
  52. IPv4 URLs `json:"ipv4"`
  53. IPv6 URLs `json:"ipv6"`
  54. BotSecret string `json:"secret_for_mtproxybot"`
  55. }
  56. // BindAddr returns connection for this server to bind to.
  57. func (c *Config) BindAddr() string {
  58. return getAddr(c.BindIP, c.BindPort)
  59. }
  60. // StatAddr returns connection string to the stats API.
  61. func (c *Config) StatAddr() string {
  62. return getAddr(c.StatsIP, c.StatsPort)
  63. }
  64. // UseMiddleProxy defines if this proxy has to connect middle proxies
  65. // which supports promoted channels or directly access Telegram.
  66. func (c *Config) UseMiddleProxy() bool {
  67. return len(c.AdTag) > 0
  68. }
  69. // BotSecretString returns secret string which should work with MTProxybot.
  70. func (c *Config) BotSecretString() string {
  71. return hex.EncodeToString(c.Secret)
  72. }
  73. // SecretString returns a secret in a form entered on the start of the
  74. // application.
  75. func (c *Config) SecretString() string {
  76. secret := c.BotSecretString()
  77. if c.SecureMode {
  78. return "dd" + secret
  79. }
  80. return secret
  81. }
  82. // GetURLs returns configured IPURLs instance with links to this server.
  83. func (c *Config) GetURLs() IPURLs {
  84. urls := IPURLs{}
  85. secret := c.SecretString()
  86. if c.PublicIPv4 != nil {
  87. urls.IPv4 = getURLs(c.PublicIPv4, c.PublicIPv4Port, secret)
  88. }
  89. if c.PublicIPv6 != nil {
  90. urls.IPv6 = getURLs(c.PublicIPv6, c.PublicIPv6Port, secret)
  91. }
  92. urls.BotSecret = c.BotSecretString()
  93. return urls
  94. }
  95. func getAddr(host fmt.Stringer, port uint16) string {
  96. return net.JoinHostPort(host.String(), strconv.Itoa(int(port)))
  97. }
  98. // NewConfig returns new configuration. If required, it manages and
  99. // fetches data from external sources. Parameters passed to this
  100. // function, should come from command line arguments.
  101. func NewConfig(debug, verbose bool, // nolint: gocyclo
  102. writeBufferSize, readBufferSize uint32,
  103. bindIP, publicIPv4, publicIPv6, statsIP net.IP,
  104. bindPort, publicIPv4Port, publicIPv6Port, statsPort, statsdPort uint16,
  105. statsdIP, statsdNetwork, statsdPrefix, statsdTagsFormat string,
  106. statsdTags map[string]string, prometheusPrefix string,
  107. secureOnly bool,
  108. antiReplayMaxSize int, antiReplayEvictionTime time.Duration,
  109. secret, adtag []byte) (*Config, error) {
  110. secureMode := secureOnly
  111. if bytes.HasPrefix(secret, []byte{0xdd}) && len(secret) == 17 {
  112. secureMode = true
  113. secret = bytes.TrimPrefix(secret, []byte{0xdd})
  114. } else if len(secret) != 16 {
  115. return nil, errors.New("Telegram demands secret of length 32")
  116. }
  117. var err error
  118. if publicIPv4 == nil {
  119. publicIPv4, err = getGlobalIPv4()
  120. if err != nil {
  121. publicIPv4 = nil
  122. } else if publicIPv4.To4() == nil {
  123. return nil, errors.Errorf("IP %s is not IPv4", publicIPv4.String())
  124. }
  125. }
  126. if publicIPv4Port == 0 {
  127. publicIPv4Port = bindPort
  128. }
  129. if publicIPv6 == nil {
  130. publicIPv6, err = getGlobalIPv6()
  131. if err != nil {
  132. publicIPv6 = nil
  133. } else if publicIPv6.To4() != nil {
  134. return nil, errors.Errorf("IP %s is not IPv6", publicIPv6.String())
  135. }
  136. }
  137. if publicIPv6Port == 0 {
  138. publicIPv6Port = bindPort
  139. }
  140. if statsIP == nil {
  141. statsIP = publicIPv4
  142. }
  143. conf := &Config{
  144. Debug: debug,
  145. Verbose: verbose,
  146. SecureOnly: secureOnly,
  147. BindIP: bindIP,
  148. BindPort: bindPort,
  149. PublicIPv4: publicIPv4,
  150. PublicIPv4Port: publicIPv4Port,
  151. PublicIPv6: publicIPv6,
  152. PublicIPv6Port: publicIPv6Port,
  153. StatsIP: statsIP,
  154. StatsPort: statsPort,
  155. Secret: secret,
  156. AdTag: adtag,
  157. SecureMode: secureMode,
  158. ReadBufferSize: int(readBufferSize),
  159. WriteBufferSize: int(writeBufferSize),
  160. AntiReplayMaxSize: antiReplayMaxSize,
  161. AntiReplayEvictionTime: antiReplayEvictionTime,
  162. }
  163. conf.Prometheus.Prefix = prometheusPrefix
  164. if statsdIP != "" {
  165. conf.StatsD.Enabled = true
  166. conf.StatsD.Prefix = statsdPrefix
  167. conf.StatsD.Tags = statsdTags
  168. var (
  169. addr net.Addr
  170. err error
  171. )
  172. hostPort := net.JoinHostPort(statsdIP, strconv.Itoa(int(statsdPort)))
  173. switch statsdNetwork {
  174. case "tcp":
  175. addr, err = net.ResolveTCPAddr("tcp", hostPort)
  176. case "udp":
  177. addr, err = net.ResolveUDPAddr("udp", hostPort)
  178. default:
  179. err = errors.Errorf("Unknown network %s", statsdNetwork)
  180. }
  181. if err != nil {
  182. return nil, errors.Annotate(err, "Cannot resolve statsd address")
  183. }
  184. conf.StatsD.Addr = addr
  185. switch statsdTagsFormat {
  186. case "datadog":
  187. conf.StatsD.TagsFormat = statsd.Datadog
  188. case "influxdb":
  189. conf.StatsD.TagsFormat = statsd.InfluxDB
  190. case "":
  191. default:
  192. return nil, errors.Errorf("Unknown tags format %s", statsdTagsFormat)
  193. }
  194. }
  195. return conf, nil
  196. }