| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- package conf
- import (
- "encoding/base64"
- "net"
- "strconv"
- "strings"
- "github.com/xtls/xray-core/common/errors"
- v2net "github.com/xtls/xray-core/common/net"
- "github.com/xtls/xray-core/common/protocol"
- "github.com/xtls/xray-core/proxy/freedom"
- "google.golang.org/protobuf/proto"
- )
- type FreedomConfig struct {
- DomainStrategy string `json:"domainStrategy"`
- Timeout *uint32 `json:"timeout"`
- Redirect string `json:"redirect"`
- UserLevel uint32 `json:"userLevel"`
- Fragment *Fragment `json:"fragment"`
- Noise *Noise `json:"noise"`
- Noises []*Noise `json:"noises"`
- ProxyProtocol uint32 `json:"proxyProtocol"`
- }
- type Fragment struct {
- Packets string `json:"packets"`
- Length string `json:"length"`
- Interval string `json:"interval"`
- }
- type Noise struct {
- Type string `json:"type"`
- Packet string `json:"packet"`
- Delay *Int32Range `json:"delay"`
- }
- // Build implements Buildable
- func (c *FreedomConfig) Build() (proto.Message, error) {
- config := new(freedom.Config)
- switch strings.ToLower(c.DomainStrategy) {
- case "asis", "":
- config.DomainStrategy = freedom.Config_AS_IS
- case "useip":
- config.DomainStrategy = freedom.Config_USE_IP
- case "useipv4":
- config.DomainStrategy = freedom.Config_USE_IP4
- case "useipv6":
- config.DomainStrategy = freedom.Config_USE_IP6
- case "useipv4v6":
- config.DomainStrategy = freedom.Config_USE_IP46
- case "useipv6v4":
- config.DomainStrategy = freedom.Config_USE_IP64
- case "forceip":
- config.DomainStrategy = freedom.Config_FORCE_IP
- case "forceipv4":
- config.DomainStrategy = freedom.Config_FORCE_IP4
- case "forceipv6":
- config.DomainStrategy = freedom.Config_FORCE_IP6
- case "forceipv4v6":
- config.DomainStrategy = freedom.Config_FORCE_IP46
- case "forceipv6v4":
- config.DomainStrategy = freedom.Config_FORCE_IP64
- default:
- return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
- }
- if c.Fragment != nil {
- config.Fragment = new(freedom.Fragment)
- var err, err2 error
- switch strings.ToLower(c.Fragment.Packets) {
- case "tlshello":
- // TLS Hello Fragmentation (into multiple handshake messages)
- config.Fragment.PacketsFrom = 0
- config.Fragment.PacketsTo = 1
- case "":
- // TCP Segmentation (all packets)
- config.Fragment.PacketsFrom = 0
- config.Fragment.PacketsTo = 0
- default:
- // TCP Segmentation (range)
- packetsFromTo := strings.Split(c.Fragment.Packets, "-")
- if len(packetsFromTo) == 2 {
- config.Fragment.PacketsFrom, err = strconv.ParseUint(packetsFromTo[0], 10, 64)
- config.Fragment.PacketsTo, err2 = strconv.ParseUint(packetsFromTo[1], 10, 64)
- } else {
- config.Fragment.PacketsFrom, err = strconv.ParseUint(packetsFromTo[0], 10, 64)
- config.Fragment.PacketsTo = config.Fragment.PacketsFrom
- }
- if err != nil {
- return nil, errors.New("Invalid PacketsFrom").Base(err)
- }
- if err2 != nil {
- return nil, errors.New("Invalid PacketsTo").Base(err2)
- }
- if config.Fragment.PacketsFrom > config.Fragment.PacketsTo {
- config.Fragment.PacketsFrom, config.Fragment.PacketsTo = config.Fragment.PacketsTo, config.Fragment.PacketsFrom
- }
- if config.Fragment.PacketsFrom == 0 {
- return nil, errors.New("PacketsFrom can't be 0")
- }
- }
- {
- if c.Fragment.Length == "" {
- return nil, errors.New("Length can't be empty")
- }
- lengthMinMax := strings.Split(c.Fragment.Length, "-")
- if len(lengthMinMax) == 2 {
- config.Fragment.LengthMin, err = strconv.ParseUint(lengthMinMax[0], 10, 64)
- config.Fragment.LengthMax, err2 = strconv.ParseUint(lengthMinMax[1], 10, 64)
- } else {
- config.Fragment.LengthMin, err = strconv.ParseUint(lengthMinMax[0], 10, 64)
- config.Fragment.LengthMax = config.Fragment.LengthMin
- }
- if err != nil {
- return nil, errors.New("Invalid LengthMin").Base(err)
- }
- if err2 != nil {
- return nil, errors.New("Invalid LengthMax").Base(err2)
- }
- if config.Fragment.LengthMin > config.Fragment.LengthMax {
- config.Fragment.LengthMin, config.Fragment.LengthMax = config.Fragment.LengthMax, config.Fragment.LengthMin
- }
- if config.Fragment.LengthMin == 0 {
- return nil, errors.New("LengthMin can't be 0")
- }
- }
- {
- if c.Fragment.Interval == "" {
- return nil, errors.New("Interval can't be empty")
- }
- intervalMinMax := strings.Split(c.Fragment.Interval, "-")
- if len(intervalMinMax) == 2 {
- config.Fragment.IntervalMin, err = strconv.ParseUint(intervalMinMax[0], 10, 64)
- config.Fragment.IntervalMax, err2 = strconv.ParseUint(intervalMinMax[1], 10, 64)
- } else {
- config.Fragment.IntervalMin, err = strconv.ParseUint(intervalMinMax[0], 10, 64)
- config.Fragment.IntervalMax = config.Fragment.IntervalMin
- }
- if err != nil {
- return nil, errors.New("Invalid IntervalMin").Base(err)
- }
- if err2 != nil {
- return nil, errors.New("Invalid IntervalMax").Base(err2)
- }
- if config.Fragment.IntervalMin > config.Fragment.IntervalMax {
- config.Fragment.IntervalMin, config.Fragment.IntervalMax = config.Fragment.IntervalMax, config.Fragment.IntervalMin
- }
- }
- }
- if c.Noise != nil {
- return nil, errors.PrintRemovedFeatureError("noise = { ... }", "noises = [ { ... } ]")
- }
- if c.Noises != nil {
- for _, n := range c.Noises {
- NConfig, err := ParseNoise(n)
- if err != nil {
- return nil, err
- }
- config.Noises = append(config.Noises, NConfig)
- }
- }
- if c.Timeout != nil {
- config.Timeout = *c.Timeout
- }
- config.UserLevel = c.UserLevel
- if len(c.Redirect) > 0 {
- host, portStr, err := net.SplitHostPort(c.Redirect)
- if err != nil {
- return nil, errors.New("invalid redirect address: ", c.Redirect, ": ", err).Base(err)
- }
- port, err := v2net.PortFromString(portStr)
- if err != nil {
- return nil, errors.New("invalid redirect port: ", c.Redirect, ": ", err).Base(err)
- }
- config.DestinationOverride = &freedom.DestinationOverride{
- Server: &protocol.ServerEndpoint{
- Port: uint32(port),
- },
- }
- if len(host) > 0 {
- config.DestinationOverride.Server.Address = v2net.NewIPOrDomain(v2net.ParseAddress(host))
- }
- }
- if c.ProxyProtocol > 0 && c.ProxyProtocol <= 2 {
- config.ProxyProtocol = c.ProxyProtocol
- }
- return config, nil
- }
- func ParseNoise(noise *Noise) (*freedom.Noise, error) {
- var err, err2 error
- NConfig := new(freedom.Noise)
- switch strings.ToLower(noise.Type) {
- case "rand":
- randValue := strings.Split(noise.Packet, "-")
- if len(randValue) > 2 {
- return nil, errors.New("Only 2 values are allowed for rand")
- }
- if len(randValue) == 2 {
- NConfig.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
- NConfig.LengthMax, err2 = strconv.ParseUint(randValue[1], 10, 64)
- }
- if len(randValue) == 1 {
- NConfig.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
- NConfig.LengthMax = NConfig.LengthMin
- }
- if err != nil {
- return nil, errors.New("invalid value for rand LengthMin").Base(err)
- }
- if err2 != nil {
- return nil, errors.New("invalid value for rand LengthMax").Base(err2)
- }
- if NConfig.LengthMin > NConfig.LengthMax {
- NConfig.LengthMin, NConfig.LengthMax = NConfig.LengthMax, NConfig.LengthMin
- }
- if NConfig.LengthMin == 0 {
- return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
- }
- case "str":
- //user input string
- NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
- case "base64":
- //user input base64
- NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
- if err != nil {
- return nil, errors.New("Invalid base64 string")
- }
- default:
- return nil, errors.New("Invalid packet,only rand,str,base64 are supported")
- }
- if noise.Delay != nil {
- if noise.Delay.From != 0 && noise.Delay.To != 0 {
- NConfig.DelayMin = uint64(noise.Delay.From)
- NConfig.DelayMax = uint64(noise.Delay.To)
- if NConfig.DelayMin > NConfig.LengthMax {
- NConfig.DelayMin, NConfig.DelayMax = NConfig.LengthMax, NConfig.DelayMin
- }
- } else {
- return nil, errors.New("DelayMin or DelayMax cannot be zero")
- }
- } else {
- NConfig.DelayMin = 0
- NConfig.DelayMax = 0
- }
- return NConfig, nil
- }
|