VLESS Encryption: Switch to "probability-from-to" format for customizable 1-RTT padding parameters

See https://github.com/XTLS/Xray-core/pull/5067#issue-3361308276 for details
pull/5074/head
RPRX 2025-08-31 11:35:38 +00:00 committed by GitHub
parent e8b02cd664
commit 6768a22f67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 21 deletions

View File

@ -22,8 +22,8 @@ type ClientInstance struct {
RelaysLength int RelaysLength int
XorMode uint32 XorMode uint32
Seconds uint32 Seconds uint32
PaddingLens [][2]int PaddingLens [][3]int
PaddingGaps [][2]int PaddingGaps [][3]int
RWLock sync.RWMutex RWLock sync.RWMutex
Expire time.Time Expire time.Time

View File

@ -220,50 +220,61 @@ func DecodeHeader(h []byte) (l int, err error) {
return return
} }
func ParsePadding(padding string, paddingLens, paddingGaps *[][2]int) (err error) { func ParsePadding(padding string, paddingLens, paddingGaps *[][3]int) (err error) {
if padding == "" { if padding == "" {
return return
} }
maxLen := 0 maxLen := 0
for i, s := range strings.Split(padding, ".") { for i, s := range strings.Split(padding, ".") {
x := strings.SplitN(s, "-", 2) x := strings.Split(s, "-")
if len(x) != 2 || x[0] == "" || x[1] == "" { if len(x) < 3 || x[0] == "" || x[1] == "" || x[2] == "" {
return errors.New("invalid padding lenth/gap parameter: " + s) return errors.New("invalid padding lenth/gap parameter: " + s)
} }
y := [2]int{} y := [3]int{}
if y[0], err = strconv.Atoi(x[0]); err != nil { if y[0], err = strconv.Atoi(x[0]); err != nil {
return return
} }
if y[1], err = strconv.Atoi(x[1]); err != nil { if y[1], err = strconv.Atoi(x[1]); err != nil {
return return
} }
if i == 0 && (y[0] < 17 || y[1] < 17) { if y[2], err = strconv.Atoi(x[2]); err != nil {
return errors.New("first padding length must be larger than 16") return
}
if i == 0 && (y[0] < 100 || y[1] < 18+17 || y[2] < 18+17) {
return errors.New("first padding length must not be smaller than 35")
} }
if i%2 == 0 { if i%2 == 0 {
*paddingLens = append(*paddingLens, y) *paddingLens = append(*paddingLens, y)
maxLen += max(y[0], y[1]) maxLen += max(y[1], y[2])
} else { } else {
*paddingGaps = append(*paddingGaps, y) *paddingGaps = append(*paddingGaps, y)
} }
} }
if maxLen > 65535 { if maxLen > 18+65535 {
return errors.New("total padding length must be smaller than 65536") return errors.New("total padding length must not be larger than 65553")
} }
return return
} }
func CreatPadding(paddingLens, paddingGaps [][2]int) (length int, lens []int, gaps []time.Duration) { func CreatPadding(paddingLens, paddingGaps [][3]int) (length int, lens []int, gaps []time.Duration) {
if len(paddingLens) == 0 { if len(paddingLens) == 0 {
paddingLens = [][2]int{{111, 1111}, {3333, -1234}} paddingLens = [][3]int{{100, 111, 1111}, {50, 0, 3333}}
paddingGaps = [][2]int{{111, -66}} paddingGaps = [][3]int{{75, 0, 111}}
} }
for _, l := range paddingLens { for _, y := range paddingLens {
lens = append(lens, int(max(0, crypto.RandBetween(int64(l[0]), int64(l[1]))))) l := 0
length += lens[len(lens)-1] if y[0] >= int(crypto.RandBetween(0, 100)) {
l = int(crypto.RandBetween(int64(y[1]), int64(y[2])))
}
lens = append(lens, l)
length += l
} }
for _, g := range paddingGaps { for _, y := range paddingGaps {
gaps = append(gaps, time.Duration(max(0, crypto.RandBetween(int64(g[0]), int64(g[1]))))*time.Millisecond) g := 0
if y[0] >= int(crypto.RandBetween(0, 100)) {
g = int(crypto.RandBetween(int64(y[1]), int64(y[2])))
}
gaps = append(gaps, time.Duration(g)*time.Millisecond)
} }
return return
} }

View File

@ -30,8 +30,8 @@ type ServerInstance struct {
RelaysLength int RelaysLength int
XorMode uint32 XorMode uint32
Seconds uint32 Seconds uint32
PaddingLens [][2]int PaddingLens [][3]int
PaddingGaps [][2]int PaddingGaps [][3]int
RWLock sync.RWMutex RWLock sync.RWMutex
Sessions map[[16]byte]*ServerSession Sessions map[[16]byte]*ServerSession