freedom.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package conf
  2. import (
  3. "encoding/base64"
  4. "net"
  5. "strings"
  6. "github.com/xtls/xray-core/common/errors"
  7. v2net "github.com/xtls/xray-core/common/net"
  8. "github.com/xtls/xray-core/common/protocol"
  9. "github.com/xtls/xray-core/proxy/freedom"
  10. "google.golang.org/protobuf/proto"
  11. )
  12. type FreedomConfig struct {
  13. DomainStrategy string `json:"domainStrategy"`
  14. Redirect string `json:"redirect"`
  15. UserLevel uint32 `json:"userLevel"`
  16. Fragment *Fragment `json:"fragment"`
  17. Noise *Noise `json:"noise"`
  18. Noises []*Noise `json:"noises"`
  19. ProxyProtocol uint32 `json:"proxyProtocol"`
  20. }
  21. type Fragment struct {
  22. Packets string `json:"packets"`
  23. Length *Int32Range `json:"length"`
  24. Interval *Int32Range `json:"interval"`
  25. }
  26. type Noise struct {
  27. Type string `json:"type"`
  28. Packet string `json:"packet"`
  29. Delay *Int32Range `json:"delay"`
  30. }
  31. // Build implements Buildable
  32. func (c *FreedomConfig) Build() (proto.Message, error) {
  33. config := new(freedom.Config)
  34. switch strings.ToLower(c.DomainStrategy) {
  35. case "asis", "":
  36. config.DomainStrategy = freedom.Config_AS_IS
  37. case "useip":
  38. config.DomainStrategy = freedom.Config_USE_IP
  39. case "useipv4":
  40. config.DomainStrategy = freedom.Config_USE_IP4
  41. case "useipv6":
  42. config.DomainStrategy = freedom.Config_USE_IP6
  43. case "useipv4v6":
  44. config.DomainStrategy = freedom.Config_USE_IP46
  45. case "useipv6v4":
  46. config.DomainStrategy = freedom.Config_USE_IP64
  47. case "forceip":
  48. config.DomainStrategy = freedom.Config_FORCE_IP
  49. case "forceipv4":
  50. config.DomainStrategy = freedom.Config_FORCE_IP4
  51. case "forceipv6":
  52. config.DomainStrategy = freedom.Config_FORCE_IP6
  53. case "forceipv4v6":
  54. config.DomainStrategy = freedom.Config_FORCE_IP46
  55. case "forceipv6v4":
  56. config.DomainStrategy = freedom.Config_FORCE_IP64
  57. default:
  58. return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
  59. }
  60. if c.Fragment != nil {
  61. config.Fragment = new(freedom.Fragment)
  62. switch strings.ToLower(c.Fragment.Packets) {
  63. case "tlshello":
  64. // TLS Hello Fragmentation (into multiple handshake messages)
  65. config.Fragment.PacketsFrom = 0
  66. config.Fragment.PacketsTo = 1
  67. case "":
  68. // TCP Segmentation (all packets)
  69. config.Fragment.PacketsFrom = 0
  70. config.Fragment.PacketsTo = 0
  71. default:
  72. // TCP Segmentation (range)
  73. from, to, err := ParseRangeString(c.Fragment.Packets)
  74. if err != nil {
  75. return nil, errors.New("Invalid PacketsFrom").Base(err)
  76. }
  77. config.Fragment.PacketsFrom = uint64(from)
  78. config.Fragment.PacketsTo = uint64(to)
  79. if config.Fragment.PacketsFrom == 0 {
  80. return nil, errors.New("PacketsFrom can't be 0")
  81. }
  82. }
  83. {
  84. if c.Fragment.Length == nil {
  85. return nil, errors.New("Length can't be empty")
  86. }
  87. config.Fragment.LengthMin = uint64(c.Fragment.Length.From)
  88. config.Fragment.LengthMax = uint64(c.Fragment.Length.To)
  89. if config.Fragment.LengthMin == 0 {
  90. return nil, errors.New("LengthMin can't be 0")
  91. }
  92. }
  93. {
  94. if c.Fragment.Interval == nil {
  95. return nil, errors.New("Interval can't be empty")
  96. }
  97. config.Fragment.IntervalMin = uint64(c.Fragment.Interval.From)
  98. config.Fragment.IntervalMax = uint64(c.Fragment.Interval.To)
  99. }
  100. }
  101. if c.Noise != nil {
  102. return nil, errors.PrintRemovedFeatureError("noise = { ... }", "noises = [ { ... } ]")
  103. }
  104. if c.Noises != nil {
  105. for _, n := range c.Noises {
  106. NConfig, err := ParseNoise(n)
  107. if err != nil {
  108. return nil, err
  109. }
  110. config.Noises = append(config.Noises, NConfig)
  111. }
  112. }
  113. config.UserLevel = c.UserLevel
  114. if len(c.Redirect) > 0 {
  115. host, portStr, err := net.SplitHostPort(c.Redirect)
  116. if err != nil {
  117. return nil, errors.New("invalid redirect address: ", c.Redirect, ": ", err).Base(err)
  118. }
  119. port, err := v2net.PortFromString(portStr)
  120. if err != nil {
  121. return nil, errors.New("invalid redirect port: ", c.Redirect, ": ", err).Base(err)
  122. }
  123. config.DestinationOverride = &freedom.DestinationOverride{
  124. Server: &protocol.ServerEndpoint{
  125. Port: uint32(port),
  126. },
  127. }
  128. if len(host) > 0 {
  129. config.DestinationOverride.Server.Address = v2net.NewIPOrDomain(v2net.ParseAddress(host))
  130. }
  131. }
  132. if c.ProxyProtocol > 0 && c.ProxyProtocol <= 2 {
  133. config.ProxyProtocol = c.ProxyProtocol
  134. }
  135. return config, nil
  136. }
  137. func ParseNoise(noise *Noise) (*freedom.Noise, error) {
  138. var err error
  139. NConfig := new(freedom.Noise)
  140. switch strings.ToLower(noise.Type) {
  141. case "rand":
  142. min, max, err := ParseRangeString(noise.Packet)
  143. if err != nil {
  144. return nil, errors.New("invalid value for rand Length").Base(err)
  145. }
  146. NConfig.LengthMin = uint64(min)
  147. NConfig.LengthMax = uint64(max)
  148. if NConfig.LengthMin > NConfig.LengthMax {
  149. NConfig.LengthMin, NConfig.LengthMax = NConfig.LengthMax, NConfig.LengthMin
  150. }
  151. if NConfig.LengthMin == 0 {
  152. return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
  153. }
  154. case "str":
  155. //user input string
  156. NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
  157. case "base64":
  158. //user input base64
  159. NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
  160. if err != nil {
  161. return nil, errors.New("Invalid base64 string")
  162. }
  163. default:
  164. return nil, errors.New("Invalid packet,only rand,str,base64 are supported")
  165. }
  166. if noise.Delay != nil {
  167. if noise.Delay.From != 0 && noise.Delay.To != 0 {
  168. NConfig.DelayMin = uint64(noise.Delay.From)
  169. NConfig.DelayMax = uint64(noise.Delay.To)
  170. if NConfig.DelayMin > NConfig.LengthMax {
  171. NConfig.DelayMin, NConfig.DelayMax = NConfig.LengthMax, NConfig.DelayMin
  172. }
  173. } else {
  174. return nil, errors.New("DelayMin or DelayMax cannot be zero")
  175. }
  176. } else {
  177. NConfig.DelayMin = 0
  178. NConfig.DelayMax = 0
  179. }
  180. return NConfig, nil
  181. }