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.

config.go 5.4KB

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