github.com/xtls/xray-core@v1.8.3/infra/conf/freedom.go (about) 1 package conf 2 3 import ( 4 "net" 5 "strconv" 6 "strings" 7 8 "github.com/golang/protobuf/proto" 9 v2net "github.com/xtls/xray-core/common/net" 10 "github.com/xtls/xray-core/common/protocol" 11 "github.com/xtls/xray-core/proxy/freedom" 12 ) 13 14 type FreedomConfig struct { 15 DomainStrategy string `json:"domainStrategy"` 16 Timeout *uint32 `json:"timeout"` 17 Redirect string `json:"redirect"` 18 UserLevel uint32 `json:"userLevel"` 19 Fragment *Fragment `json:"fragment"` 20 } 21 22 type Fragment struct { 23 Packets string `json:"packets"` 24 Length string `json:"length"` 25 Interval string `json:"interval"` 26 } 27 28 // Build implements Buildable 29 func (c *FreedomConfig) Build() (proto.Message, error) { 30 config := new(freedom.Config) 31 config.DomainStrategy = freedom.Config_AS_IS 32 switch strings.ToLower(c.DomainStrategy) { 33 case "useip", "use_ip", "use-ip": 34 config.DomainStrategy = freedom.Config_USE_IP 35 case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4": 36 config.DomainStrategy = freedom.Config_USE_IP4 37 case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": 38 config.DomainStrategy = freedom.Config_USE_IP6 39 } 40 41 if c.Fragment != nil { 42 if len(c.Fragment.Interval) == 0 || len(c.Fragment.Length) == 0 { 43 return nil, newError("Invalid interval or length") 44 } 45 intervalMinMax := strings.Split(c.Fragment.Interval, "-") 46 var minInterval, maxInterval int64 47 var err, err2 error 48 if len(intervalMinMax) == 2 { 49 minInterval, err = strconv.ParseInt(intervalMinMax[0], 10, 64) 50 maxInterval, err2 = strconv.ParseInt(intervalMinMax[1], 10, 64) 51 } else { 52 minInterval, err = strconv.ParseInt(intervalMinMax[0], 10, 64) 53 maxInterval = minInterval 54 } 55 if err != nil { 56 return nil, newError("Invalid minimum interval: ", err).Base(err) 57 } 58 if err2 != nil { 59 return nil, newError("Invalid maximum interval: ", err2).Base(err2) 60 } 61 62 lengthMinMax := strings.Split(c.Fragment.Length, "-") 63 var minLength, maxLength int64 64 if len(lengthMinMax) == 2 { 65 minLength, err = strconv.ParseInt(lengthMinMax[0], 10, 64) 66 maxLength, err2 = strconv.ParseInt(lengthMinMax[1], 10, 64) 67 68 } else { 69 minLength, err = strconv.ParseInt(lengthMinMax[0], 10, 64) 70 maxLength = minLength 71 } 72 if err != nil { 73 return nil, newError("Invalid minimum length: ", err).Base(err) 74 } 75 if err2 != nil { 76 return nil, newError("Invalid maximum length: ", err2).Base(err2) 77 } 78 79 if minInterval > maxInterval { 80 minInterval, maxInterval = maxInterval, minInterval 81 } 82 if minLength > maxLength { 83 minLength, maxLength = maxLength, minLength 84 } 85 86 config.Fragment = &freedom.Fragment{ 87 MinInterval: int32(minInterval), 88 MaxInterval: int32(maxInterval), 89 MinLength: int32(minLength), 90 MaxLength: int32(maxLength), 91 } 92 93 switch strings.ToLower(c.Fragment.Packets) { 94 case "tlshello": 95 // TLS Hello Fragmentation (into multiple handshake messages) 96 config.Fragment.StartPacket = 0 97 config.Fragment.EndPacket = 1 98 case "": 99 // TCP Segmentation (all packets) 100 config.Fragment.StartPacket = 0 101 config.Fragment.EndPacket = 0 102 default: 103 // TCP Segmentation (range) 104 packetRange := strings.Split(c.Fragment.Packets, "-") 105 var startPacket, endPacket int64 106 if len(packetRange) == 2 { 107 startPacket, err = strconv.ParseInt(packetRange[0], 10, 64) 108 endPacket, err2 = strconv.ParseInt(packetRange[1], 10, 64) 109 } else { 110 startPacket, err = strconv.ParseInt(packetRange[0], 10, 64) 111 endPacket = startPacket 112 } 113 if err != nil { 114 return nil, newError("Invalid start packet: ", err).Base(err) 115 } 116 if err2 != nil { 117 return nil, newError("Invalid end packet: ", err2).Base(err2) 118 } 119 if startPacket > endPacket { 120 return nil, newError("Invalid packet range: ", c.Fragment.Packets) 121 } 122 if startPacket < 1 { 123 return nil, newError("Cannot start from packet 0") 124 } 125 config.Fragment.StartPacket = int32(startPacket) 126 config.Fragment.EndPacket = int32(endPacket) 127 } 128 } 129 130 if c.Timeout != nil { 131 config.Timeout = *c.Timeout 132 } 133 config.UserLevel = c.UserLevel 134 if len(c.Redirect) > 0 { 135 host, portStr, err := net.SplitHostPort(c.Redirect) 136 if err != nil { 137 return nil, newError("invalid redirect address: ", c.Redirect, ": ", err).Base(err) 138 } 139 port, err := v2net.PortFromString(portStr) 140 if err != nil { 141 return nil, newError("invalid redirect port: ", c.Redirect, ": ", err).Base(err) 142 } 143 config.DestinationOverride = &freedom.DestinationOverride{ 144 Server: &protocol.ServerEndpoint{ 145 Port: uint32(port), 146 }, 147 } 148 149 if len(host) > 0 { 150 config.DestinationOverride.Server.Address = v2net.NewIPOrDomain(v2net.ParseAddress(host)) 151 } 152 } 153 return config, nil 154 }