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 7.8KB

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