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

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"`
  62. PublicIPv6 *net.TCPAddr `json:"public_ipv6"`
  63. StatsBind *net.TCPAddr `json:"stats_bind"`
  64. StatsdAddr *net.TCPAddr `json:"stats_addr"`
  65. StatsdTagsFormat *statsd.TagFormat `json:"statsd_tags_format"`
  66. StatsNamespace string `json:"stats_namespace"`
  67. CloakHost string `json:"cloak_host"`
  68. StatsdTags map[string]string `json:"statsd_tags"`
  69. WriteBuffer int `json:"write_buffer"`
  70. ReadBuffer int `json:"read_buffer"`
  71. CloakPort int `json:"cloak_port"`
  72. AntiReplayMaxSize int `json:"anti_replay_max_size"`
  73. MultiplexPerConnection int `json:"multiplex_per_connection"`
  74. Debug bool `json:"debug"`
  75. Verbose bool `json:"verbose"`
  76. SecretMode SecretMode `json:"secret_mode"`
  77. PreferIP PreferIP `json:"prefer_ip"`
  78. NTPServers []string `json:"ntp_servers"`
  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))
  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
  121. for _, opt := range options {
  122. switch opt.Option {
  123. case OptionTypeDebug:
  124. C.Debug = opt.Value.(bool)
  125. case OptionTypeVerbose:
  126. C.Verbose = opt.Value.(bool)
  127. case OptionTypePreferIP:
  128. value := opt.Value.(string)
  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)
  139. case OptionTypePublicIPv4:
  140. C.PublicIPv4 = opt.Value.(*net.TCPAddr)
  141. if C.PublicIPv4 == nil {
  142. C.PublicIPv4 = &net.TCPAddr{}
  143. }
  144. case OptionTypePublicIPv6:
  145. C.PublicIPv6 = opt.Value.(*net.TCPAddr)
  146. if C.PublicIPv6 == nil {
  147. C.PublicIPv6 = &net.TCPAddr{}
  148. }
  149. case OptionTypeStatsBind:
  150. C.StatsBind = opt.Value.(*net.TCPAddr)
  151. case OptionTypeStatsNamespace:
  152. C.StatsNamespace = opt.Value.(string)
  153. case OptionTypeStatsdAddress:
  154. C.StatsdAddr = opt.Value.(*net.TCPAddr)
  155. case OptionTypeStatsdTagsFormat:
  156. value := opt.Value.(string)
  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)
  167. case OptionTypeWriteBufferSize:
  168. C.WriteBuffer = int(opt.Value.(units.Base2Bytes))
  169. case OptionTypeReadBufferSize:
  170. C.ReadBuffer = int(opt.Value.(units.Base2Bytes))
  171. case OptionTypeCloakPort:
  172. C.CloakPort = int(opt.Value.(uint16))
  173. case OptionTypeAntiReplayMaxSize:
  174. C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes))
  175. case OptionTypeMultiplexPerConnection:
  176. C.MultiplexPerConnection = int(opt.Value.(uint))
  177. case OptionTypeNTPServers:
  178. C.NTPServers = opt.Value.([]string)
  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)
  184. case OptionTypeAdtag:
  185. C.AdTag = opt.Value.([]byte)
  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. }