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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package config
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "net"
  9. "github.com/alecthomas/units"
  10. statsd "github.com/smira/go-statsd"
  11. "go.uber.org/zap"
  12. )
  13. type SecretMode uint8
  14. func (s SecretMode) String() string {
  15. switch s {
  16. case SecretModeSimple:
  17. return "simple"
  18. case SecretModeSecured:
  19. return "secured"
  20. }
  21. return "tls"
  22. }
  23. const (
  24. SecretModeSimple SecretMode = iota
  25. SecretModeSecured
  26. SecretModeTLS
  27. )
  28. const SimpleSecretLength = 16
  29. type OptionType uint8
  30. const (
  31. OptionTypeDebug OptionType = iota
  32. OptionTypeVerbose
  33. OptionTypeBind
  34. OptionTypePublicIPv4
  35. OptionTypePublicIPv6
  36. OptionTypeStatsBind
  37. OptionTypeStatsNamespace
  38. OptionTypeStatsdAddress
  39. OptionTypeStatsdTagsFormat
  40. OptionTypeStatsdTags
  41. OptionTypeWriteBufferSize
  42. OptionTypeReadBufferSize
  43. OptionTypeCloakPort
  44. OptionTypeAntiReplayMaxSize
  45. OptionTypeMultiplexPerConnection
  46. OptionTypeSecret
  47. OptionTypeAdtag
  48. )
  49. type Config struct {
  50. Bind *net.TCPAddr `json:"bind"`
  51. PublicIPv4 *net.TCPAddr `json:"public_ipv4"`
  52. PublicIPv6 *net.TCPAddr `json:"public_ipv6"`
  53. StatsBind *net.TCPAddr `json:"stats_bind"`
  54. StatsdAddr *net.TCPAddr `json:"stats_addr"`
  55. StatsdTagsFormat *statsd.TagFormat `json:"statsd_tags_format"`
  56. StatsNamespace string `json:"stats_namespace"`
  57. CloakHost string `json:"cloak_host"`
  58. StatsdTags map[string]string `json:"statsd_tags"`
  59. WriteBuffer int `json:"write_buffer"`
  60. ReadBuffer int `json:"read_buffer"`
  61. CloakPort int `json:"cloak_port"`
  62. AntiReplayMaxSize int `json:"anti_replay_max_size"`
  63. MultiplexPerConnection int `json:"multiplex_per_connection"`
  64. Debug bool `json:"debug"`
  65. Verbose bool `json:"verbose"`
  66. SecretMode SecretMode `json:"secret_mode"`
  67. Secret []byte `json:"secret"`
  68. AdTag []byte `json:"adtag"`
  69. }
  70. type Opt struct {
  71. Option OptionType
  72. Value interface{}
  73. }
  74. var C = Config{}
  75. func Init(options ...Opt) error { // nolint: gocyclo, funlen
  76. for _, opt := range options {
  77. switch opt.Option {
  78. case OptionTypeDebug:
  79. C.Debug = opt.Value.(bool)
  80. case OptionTypeVerbose:
  81. C.Verbose = opt.Value.(bool)
  82. case OptionTypeBind:
  83. C.Bind = opt.Value.(*net.TCPAddr)
  84. case OptionTypePublicIPv4:
  85. C.PublicIPv4 = opt.Value.(*net.TCPAddr)
  86. if C.PublicIPv4 == nil {
  87. C.PublicIPv4 = &net.TCPAddr{}
  88. }
  89. case OptionTypePublicIPv6:
  90. C.PublicIPv6 = opt.Value.(*net.TCPAddr)
  91. if C.PublicIPv6 == nil {
  92. C.PublicIPv6 = &net.TCPAddr{}
  93. }
  94. case OptionTypeStatsBind:
  95. C.StatsBind = opt.Value.(*net.TCPAddr)
  96. case OptionTypeStatsNamespace:
  97. C.StatsNamespace = opt.Value.(string)
  98. case OptionTypeStatsdAddress:
  99. C.StatsdAddr = opt.Value.(*net.TCPAddr)
  100. case OptionTypeStatsdTagsFormat:
  101. value := opt.Value.(string)
  102. switch value {
  103. case "datadog":
  104. C.StatsdTagsFormat = statsd.TagFormatDatadog
  105. case "influxdb":
  106. C.StatsdTagsFormat = statsd.TagFormatInfluxDB
  107. default:
  108. return fmt.Errorf("incorrect statsd tag %s", value)
  109. }
  110. case OptionTypeStatsdTags:
  111. C.StatsdTags = opt.Value.(map[string]string)
  112. case OptionTypeWriteBufferSize:
  113. C.WriteBuffer = int(opt.Value.(units.Base2Bytes))
  114. case OptionTypeReadBufferSize:
  115. C.ReadBuffer = int(opt.Value.(units.Base2Bytes))
  116. case OptionTypeCloakPort:
  117. C.CloakPort = int(opt.Value.(uint16))
  118. case OptionTypeAntiReplayMaxSize:
  119. C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes))
  120. case OptionTypeMultiplexPerConnection:
  121. C.MultiplexPerConnection = int(opt.Value.(uint))
  122. case OptionTypeSecret:
  123. C.Secret = opt.Value.([]byte)
  124. case OptionTypeAdtag:
  125. C.AdTag = opt.Value.([]byte)
  126. default:
  127. return fmt.Errorf("unknown tag %v", opt.Option)
  128. }
  129. }
  130. switch {
  131. case len(C.Secret) == 1+SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xdd}):
  132. C.SecretMode = SecretModeSecured
  133. C.Secret = bytes.TrimPrefix(C.Secret, []byte{0xdd})
  134. case len(C.Secret) > SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xee}):
  135. C.SecretMode = SecretModeTLS
  136. secret := bytes.TrimPrefix(C.Secret, []byte{0xee})
  137. C.Secret = secret[:SimpleSecretLength]
  138. C.CloakHost = string(secret[SimpleSecretLength:])
  139. case len(C.Secret) == SimpleSecretLength:
  140. C.SecretMode = SecretModeSimple
  141. default:
  142. return errors.New("incorrect secret")
  143. }
  144. if C.MultiplexPerConnection == 0 {
  145. return errors.New("cannot use 0 clients per connection for multiplexing")
  146. }
  147. if C.CloakHost != "" {
  148. if _, err := net.LookupHost(C.CloakHost); err != nil {
  149. zap.S().Warnw("Cannot resolve address of host", "hostname", C.CloakHost, "error", err)
  150. }
  151. }
  152. return nil
  153. }
  154. func InitPublicAddress(ctx context.Context) error {
  155. if C.PublicIPv4.Port == 0 {
  156. C.PublicIPv4.Port = C.Bind.Port
  157. }
  158. if C.PublicIPv6.Port == 0 {
  159. C.PublicIPv6.Port = C.Bind.Port
  160. }
  161. foundAddress := C.PublicIPv4.IP != nil || C.PublicIPv6.IP != nil
  162. if C.PublicIPv4.IP == nil {
  163. ip, err := getGlobalIPv4(ctx)
  164. if err != nil {
  165. zap.S().Warnw("Cannot resolve public address", "error", err)
  166. } else {
  167. C.PublicIPv4.IP = ip
  168. foundAddress = true
  169. }
  170. }
  171. if C.PublicIPv6.IP == nil {
  172. ip, err := getGlobalIPv6(ctx)
  173. if err != nil {
  174. zap.S().Warnw("Cannot resolve public address", "error", err)
  175. } else {
  176. C.PublicIPv6.IP = ip
  177. foundAddress = true
  178. }
  179. }
  180. if !foundAddress {
  181. return errors.New("cannot resolve any public address")
  182. }
  183. return nil
  184. }
  185. func Printable() interface{} {
  186. data, err := json.Marshal(C)
  187. if err != nil {
  188. panic(err)
  189. }
  190. rv := map[string]interface{}{}
  191. if err := json.Unmarshal(data, &rv); err != nil {
  192. panic(err)
  193. }
  194. return rv
  195. }