UDP noises: Add base64 and multi-packet support (#3794)

https://github.com/XTLS/Xray-core/pull/3794#issuecomment-2351329251

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
This commit is contained in:
dragonbreath2000 2024-09-16 05:46:30 -07:00 committed by GitHub
parent b1c6471eeb
commit 363e86c585
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 131 additions and 120 deletions

View file

@ -1,6 +1,7 @@
package conf
import (
"encoding/base64"
"net"
"strconv"
"strings"
@ -19,6 +20,7 @@ type FreedomConfig struct {
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
Noise *Noise `json:"noise"`
Noises []*Noise `json:"noises"`
ProxyProtocol uint32 `json:"proxyProtocol"`
}
@ -29,8 +31,9 @@ type Fragment struct {
}
type Noise struct {
Packet string `json:"packet"`
Delay string `json:"delay"`
Type string `json:"type"`
Packet string `json:"packet"`
Delay *Int32Range `json:"delay"`
}
// Build implements Buildable
@ -149,74 +152,18 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
}
}
}
if c.Noise != nil {
config.Noise = new(freedom.Noise)
var err, err2 error
p := strings.Split(strings.ToLower(c.Noise.Packet), ":")
if len(p) != 2 {
return nil, errors.New("invalid type for packet")
}
switch p[0] {
case "rand":
randValue := strings.Split(p[1], "-")
if len(randValue) > 2 {
return nil, errors.New("Only 2 values are allowed for rand")
}
if len(randValue) == 2 {
config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
config.Noise.LengthMax, err2 = strconv.ParseUint(randValue[1], 10, 64)
}
if len(randValue) == 1 {
config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
config.Noise.LengthMax = config.Noise.LengthMin
}
return nil, errors.PrintRemovedFeatureError("noise = { ... }", "noises = [ { ... } ]")
}
if c.Noises != nil {
for _, n := range c.Noises {
NConfig, err := ParseNoise(n)
if err != nil {
return nil, errors.New("invalid value for rand LengthMin").Base(err)
return nil, err
}
if err2 != nil {
return nil, errors.New("invalid value for rand LengthMax").Base(err2)
}
if config.Noise.LengthMin > config.Noise.LengthMax {
config.Noise.LengthMin, config.Noise.LengthMax = config.Noise.LengthMax, config.Noise.LengthMin
}
if config.Noise.LengthMin == 0 {
return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
}
case "str":
//user input string
config.Noise.StrNoise = strings.TrimSpace(p[1])
default:
return nil, errors.New("Invalid packet,only rand and str are supported")
}
if c.Noise.Delay != "" {
d := strings.Split(strings.ToLower(c.Noise.Delay), "-")
if len(d) > 2 {
return nil, errors.New("Invalid delay value")
}
if len(d) == 2 {
config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64)
config.Noise.DelayMax, err2 = strconv.ParseUint(d[1], 10, 64)
} else {
config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64)
config.Noise.DelayMax = config.Noise.DelayMin
}
if err != nil {
return nil, errors.New("Invalid value for DelayMin").Base(err)
}
if err2 != nil {
return nil, errors.New("Invalid value for DelayMax").Base(err2)
}
if config.Noise.DelayMin > config.Noise.DelayMax {
config.Noise.DelayMin, config.Noise.DelayMax = config.Noise.DelayMax, config.Noise.DelayMin
}
if config.Noise.DelayMin == 0 {
return nil, errors.New("DelayMin or DelayMax cannot be 0")
}
} else {
config.Noise.DelayMin = 0
config.Noises = append(config.Noises, NConfig)
}
}
@ -248,3 +195,67 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
}
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
}