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
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

config.go 6.8KB

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