freedom.go 6.2 KB

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