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
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

config.go 5.8KB

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