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
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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 * 2 * math.Log(float64(c.MultiplexPerConnection))
  109. newValue = math.Ceil(newValue)
  110. newValue = math.Max(fvalue, newValue)
  111. return int(newValue)
  112. }
  113. type Opt struct {
  114. Option OptionType
  115. Value interface{}
  116. }
  117. var C = Config{}
  118. func Init(options ...Opt) error { // nolint: gocyclo, funlen
  119. for _, opt := range options {
  120. switch opt.Option {
  121. case OptionTypeDebug:
  122. C.Debug = opt.Value.(bool)
  123. case OptionTypeVerbose:
  124. C.Verbose = opt.Value.(bool)
  125. case OptionTypePreferIP:
  126. value := opt.Value.(string)
  127. switch value {
  128. case "ipv4":
  129. C.PreferIP = PreferIPv4
  130. case "ipv6":
  131. C.PreferIP = PreferIPv6
  132. default:
  133. return fmt.Errorf("incorrect direct IP mode %s", value)
  134. }
  135. case OptionTypeBind:
  136. C.Bind = opt.Value.(*net.TCPAddr)
  137. case OptionTypePublicIPv4:
  138. C.PublicIPv4 = opt.Value.(*net.TCPAddr)
  139. if C.PublicIPv4 == nil {
  140. C.PublicIPv4 = &net.TCPAddr{}
  141. }
  142. case OptionTypePublicIPv6:
  143. C.PublicIPv6 = opt.Value.(*net.TCPAddr)
  144. if C.PublicIPv6 == nil {
  145. C.PublicIPv6 = &net.TCPAddr{}
  146. }
  147. case OptionTypeStatsBind:
  148. C.StatsBind = opt.Value.(*net.TCPAddr)
  149. case OptionTypeStatsNamespace:
  150. C.StatsNamespace = opt.Value.(string)
  151. case OptionTypeStatsdAddress:
  152. C.StatsdAddr = opt.Value.(*net.TCPAddr)
  153. case OptionTypeStatsdTagsFormat:
  154. value := opt.Value.(string)
  155. switch value {
  156. case "datadog":
  157. C.StatsdTagsFormat = statsd.TagFormatDatadog
  158. case "influxdb":
  159. C.StatsdTagsFormat = statsd.TagFormatInfluxDB
  160. default:
  161. return fmt.Errorf("incorrect statsd tag %s", value)
  162. }
  163. case OptionTypeStatsdTags:
  164. C.StatsdTags = opt.Value.(map[string]string)
  165. case OptionTypeWriteBufferSize:
  166. C.WriteBuffer = int(opt.Value.(units.Base2Bytes))
  167. case OptionTypeReadBufferSize:
  168. C.ReadBuffer = int(opt.Value.(units.Base2Bytes))
  169. case OptionTypeCloakPort:
  170. C.CloakPort = int(opt.Value.(uint16))
  171. case OptionTypeAntiReplayMaxSize:
  172. C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes))
  173. case OptionTypeMultiplexPerConnection:
  174. C.MultiplexPerConnection = int(opt.Value.(uint))
  175. case OptionTypeNTPServers:
  176. C.NTPServers = opt.Value.([]string)
  177. if len(C.NTPServers) == 0 {
  178. return errors.New("ntp server list is empty")
  179. }
  180. case OptionTypeSecret:
  181. C.Secret = opt.Value.([]byte)
  182. case OptionTypeAdtag:
  183. C.AdTag = opt.Value.([]byte)
  184. default:
  185. return fmt.Errorf("unknown tag %v", opt.Option)
  186. }
  187. }
  188. switch {
  189. case len(C.Secret) == 1+SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xdd}):
  190. C.SecretMode = SecretModeSecured
  191. C.Secret = bytes.TrimPrefix(C.Secret, []byte{0xdd})
  192. case len(C.Secret) > SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xee}):
  193. C.SecretMode = SecretModeTLS
  194. secret := bytes.TrimPrefix(C.Secret, []byte{0xee})
  195. C.Secret = secret[:SimpleSecretLength]
  196. C.CloakHost = string(secret[SimpleSecretLength:])
  197. case len(C.Secret) == SimpleSecretLength:
  198. C.SecretMode = SecretModeSimple
  199. default:
  200. return errors.New("incorrect secret")
  201. }
  202. if C.MultiplexPerConnection == 0 {
  203. return errors.New("cannot use 0 clients per connection for multiplexing")
  204. }
  205. if C.CloakHost != "" {
  206. if _, err := net.LookupHost(C.CloakHost); err != nil {
  207. zap.S().Warnw("Cannot resolve address of host", "hostname", C.CloakHost, "error", err)
  208. }
  209. }
  210. return nil
  211. }
  212. func InitPublicAddress(ctx context.Context) error {
  213. if C.PublicIPv4.Port == 0 {
  214. C.PublicIPv4.Port = C.Bind.Port
  215. }
  216. if C.PublicIPv6.Port == 0 {
  217. C.PublicIPv6.Port = C.Bind.Port
  218. }
  219. foundAddress := C.PublicIPv4.IP != nil || C.PublicIPv6.IP != nil
  220. if C.PublicIPv4.IP == nil {
  221. ip, err := getGlobalIPv4(ctx)
  222. if err != nil {
  223. zap.S().Warnw("Cannot resolve public address", "error", err)
  224. } else {
  225. C.PublicIPv4.IP = ip
  226. foundAddress = true
  227. }
  228. }
  229. if C.PublicIPv6.IP == nil {
  230. ip, err := getGlobalIPv6(ctx)
  231. if err != nil {
  232. zap.S().Warnw("Cannot resolve public address", "error", err)
  233. } else {
  234. C.PublicIPv6.IP = ip
  235. foundAddress = true
  236. }
  237. }
  238. if !foundAddress {
  239. return errors.New("cannot resolve any public address")
  240. }
  241. return nil
  242. }
  243. func Printable() interface{} {
  244. data, err := json.Marshal(C)
  245. if err != nil {
  246. panic(err)
  247. }
  248. rv := map[string]interface{}{}
  249. if err := json.Unmarshal(data, &rv); err != nil {
  250. panic(err)
  251. }
  252. return rv
  253. }