Skip to content

Commit e10347b

Browse files
XHTTP transport: Add sessionIDTable and sessionIDLength; Rename session* to sessionID* (#6258)
#6258 (comment) #6253 (comment) #6251 (comment) Usage: #6258 (comment) Closes #6264 --------- Co-authored-by: XXcipherX <knazevvv6514@gmail.com>
1 parent 26a022c commit e10347b

6 files changed

Lines changed: 159 additions & 71 deletions

File tree

infra/conf/transport_internet.go

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/hex"
77
"encoding/json"
88
"math"
9+
"math/big"
910
"net/netip"
1011
"net/url"
1112
"os"
@@ -219,8 +220,10 @@ type SplitHTTPConfig struct {
219220
XPaddingPlacement string `json:"xPaddingPlacement"`
220221
XPaddingMethod string `json:"xPaddingMethod"`
221222
UplinkHTTPMethod string `json:"uplinkHTTPMethod"`
222-
SessionPlacement string `json:"sessionPlacement"`
223-
SessionKey string `json:"sessionKey"`
223+
SessionIDPlacement string `json:"sessionIDPlacement"`
224+
SessionIDKey string `json:"sessionIDKey"`
225+
SessionIDTable string `json:"sessionIDTable"`
226+
SessionIDLength Int32Range `json:"sessionIDLength"`
224227
SeqPlacement string `json:"seqPlacement"`
225228
SeqKey string `json:"seqKey"`
226229
UplinkDataPlacement string `json:"uplinkDataPlacement"`
@@ -331,12 +334,12 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
331334
return nil, errors.New("uplinkHTTPMethod can be GET only in packet-up mode")
332335
}
333336

334-
switch c.SessionPlacement {
337+
switch c.SessionIDPlacement {
335338
case "":
336-
c.SessionPlacement = "path"
339+
c.SessionIDPlacement = "path"
337340
case "path", "cookie", "header", "query":
338341
default:
339-
return nil, errors.New("unsupported session placement: " + c.SessionPlacement)
342+
return nil, errors.New("unsupported session placement: " + c.SessionIDPlacement)
340343
}
341344

342345
switch c.SeqPlacement {
@@ -347,12 +350,31 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
347350
return nil, errors.New("unsupported seq placement: " + c.SeqPlacement)
348351
}
349352

350-
if c.SessionPlacement != "path" && c.SessionKey == "" {
351-
switch c.SessionPlacement {
353+
if c.SessionIDPlacement != "path" && c.SessionIDKey == "" {
354+
switch c.SessionIDPlacement {
352355
case "cookie", "query":
353-
c.SessionKey = "x_session"
356+
c.SessionIDKey = "x_session"
354357
case "header":
355-
c.SessionKey = "X-Session"
358+
c.SessionIDKey = "X-Session"
359+
}
360+
}
361+
362+
if c.SessionIDTable != "" {
363+
if predefined, ok := splithttp.PredefinedTable[c.SessionIDTable]; ok {
364+
c.SessionIDTable = predefined
365+
}
366+
room := roomSize(len(c.SessionIDTable), c.SessionIDLength.From, c.SessionIDLength.To)
367+
// 2.1B possiblities should be enough
368+
if room.Cmp(big.NewInt(2<<30)) < 0 {
369+
return nil, errors.New("sessionIDTable or sessionIDLength is too small")
370+
}
371+
if c.SessionIDLength.From <= 0 {
372+
return nil, errors.New("sessionIDLength.from must be greater than 0")
373+
}
374+
for i := 0; i < len(c.SessionIDTable); i++ {
375+
if c.SessionIDTable[i] >= 0x80 {
376+
return nil, errors.New("sessionIDTable must contain only ASCII characters")
377+
}
356378
}
357379
}
358380

@@ -402,9 +424,9 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
402424
XPaddingPlacement: c.XPaddingPlacement,
403425
XPaddingMethod: c.XPaddingMethod,
404426
UplinkHTTPMethod: c.UplinkHTTPMethod,
405-
SessionPlacement: c.SessionPlacement,
427+
SessionIDPlacement: c.SessionIDPlacement,
406428
SeqPlacement: c.SeqPlacement,
407-
SessionKey: c.SessionKey,
429+
SessionIDKey: c.SessionIDKey,
408430
SeqKey: c.SeqKey,
409431
UplinkDataPlacement: c.UplinkDataPlacement,
410432
UplinkDataKey: c.UplinkDataKey,
@@ -416,6 +438,8 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
416438
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
417439
ScStreamUpServerSecs: newRangeConfig(c.ScStreamUpServerSecs),
418440
ServerMaxHeaderBytes: c.ServerMaxHeaderBytes,
441+
SessionIDTable: c.SessionIDTable,
442+
SessionIDLength: newRangeConfig(c.SessionIDLength),
419443
Xmux: &splithttp.XmuxConfig{
420444
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
421445
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
@@ -439,6 +463,17 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
439463
return config, nil
440464
}
441465

466+
func roomSize(tableSize int, min, max int32) *big.Int {
467+
base := big.NewInt(int64(tableSize))
468+
sum := new(big.Int)
469+
term := new(big.Int)
470+
for k := min; k <= max; k++ {
471+
term.Exp(base, big.NewInt(int64(k)), nil)
472+
sum.Add(sum, term)
473+
}
474+
return sum
475+
}
476+
442477
const (
443478
Byte = 1
444479
Kilobyte = 1024 * Byte

transport/internet/splithttp/config.go

Lines changed: 70 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import (
44
"encoding/base64"
55
"fmt"
66
"io"
7+
"math/rand/v2"
78
"net/http"
89
"strings"
910

1011
"github.com/xtls/xray-core/common"
1112
"github.com/xtls/xray-core/common/buf"
1213
"github.com/xtls/xray-core/common/crypto"
1314
"github.com/xtls/xray-core/common/utils"
15+
"github.com/xtls/xray-core/common/uuid"
1416
"github.com/xtls/xray-core/transport/internet"
1517
)
1618

@@ -131,26 +133,26 @@ func (c *Config) GetNormalizedUplinkHTTPMethod() string {
131133
return c.UplinkHTTPMethod
132134
}
133135

134-
func (c *Config) GetNormalizedScMaxEachPostBytes() RangeConfig {
136+
func (c *Config) GetNormalizedScMaxEachPostBytes() *RangeConfig {
135137
if c.ScMaxEachPostBytes == nil || c.ScMaxEachPostBytes.To == 0 {
136-
return RangeConfig{
138+
return &RangeConfig{
137139
From: 1000000,
138140
To: 1000000,
139141
}
140142
}
141143

142-
return *c.ScMaxEachPostBytes
144+
return c.ScMaxEachPostBytes
143145
}
144146

145-
func (c *Config) GetNormalizedScMinPostsIntervalMs() RangeConfig {
147+
func (c *Config) GetNormalizedScMinPostsIntervalMs() *RangeConfig {
146148
if c.ScMinPostsIntervalMs == nil || c.ScMinPostsIntervalMs.To == 0 {
147-
return RangeConfig{
149+
return &RangeConfig{
148150
From: 30,
149151
To: 30,
150152
}
151153
}
152154

153-
return *c.ScMinPostsIntervalMs
155+
return c.ScMinPostsIntervalMs
154156
}
155157

156158
func (c *Config) GetNormalizedScMaxBufferedPosts() int {
@@ -161,41 +163,41 @@ func (c *Config) GetNormalizedScMaxBufferedPosts() int {
161163
return int(c.ScMaxBufferedPosts)
162164
}
163165

164-
func (c *Config) GetNormalizedScStreamUpServerSecs() RangeConfig {
166+
func (c *Config) GetNormalizedScStreamUpServerSecs() *RangeConfig {
165167
if c.ScStreamUpServerSecs == nil || c.ScStreamUpServerSecs.To == 0 {
166-
return RangeConfig{
168+
return &RangeConfig{
167169
From: 20,
168170
To: 80,
169171
}
170172
}
171173

172-
return *c.ScStreamUpServerSecs
174+
return c.ScStreamUpServerSecs
173175
}
174176

175-
func (c *Config) GetNormalizedUplinkChunkSize() RangeConfig {
177+
func (c *Config) GetNormalizedUplinkChunkSize() *RangeConfig {
176178
if c.UplinkChunkSize == nil || c.UplinkChunkSize.To == 0 {
177179
switch c.UplinkDataPlacement {
178180
case PlacementCookie:
179-
return RangeConfig{
181+
return &RangeConfig{
180182
From: 2 * 1024, // 2 KiB
181183
To: 3 * 1024, // 3 KiB
182184
}
183185
case PlacementHeader:
184-
return RangeConfig{
186+
return &RangeConfig{
185187
From: 3 * 1000, // 3 KB
186188
To: 4 * 1000, // 4 KB
187189
}
188190
default:
189191
return c.GetNormalizedScMaxEachPostBytes()
190192
}
191193
} else if c.UplinkChunkSize.From < 64 {
192-
return RangeConfig{
194+
return &RangeConfig{
193195
From: 64,
194196
To: max(64, c.UplinkChunkSize.To),
195197
}
196198
}
197199

198-
return *c.UplinkChunkSize
200+
return c.UplinkChunkSize
199201
}
200202

201203
func (c *Config) GetNormalizedServerMaxHeaderBytes() int {
@@ -207,10 +209,10 @@ func (c *Config) GetNormalizedServerMaxHeaderBytes() int {
207209
}
208210

209211
func (c *Config) GetNormalizedSessionPlacement() string {
210-
if c.SessionPlacement == "" {
212+
if c.SessionIDPlacement == "" {
211213
return PlacementPath
212214
}
213-
return c.SessionPlacement
215+
return c.SessionIDPlacement
214216
}
215217

216218
func (c *Config) GetNormalizedSeqPlacement() string {
@@ -228,8 +230,8 @@ func (c *Config) GetNormalizedUplinkDataPlacement() string {
228230
}
229231

230232
func (c *Config) GetNormalizedSessionKey() string {
231-
if c.SessionKey != "" {
232-
return c.SessionKey
233+
if c.SessionIDKey != "" {
234+
return c.SessionIDKey
233235
}
234236
switch c.GetNormalizedSessionPlacement() {
235237
case PlacementHeader:
@@ -417,59 +419,59 @@ func (c *Config) ExtractMetaFromRequest(req *http.Request, path string) (session
417419
return sessionId, seqStr
418420
}
419421

420-
func (m *XmuxConfig) GetNormalizedMaxConcurrency() RangeConfig {
422+
func (m *XmuxConfig) GetNormalizedMaxConcurrency() *RangeConfig {
421423
if m.MaxConcurrency == nil {
422-
return RangeConfig{
424+
return &RangeConfig{
423425
From: 0,
424426
To: 0,
425427
}
426428
}
427429

428-
return *m.MaxConcurrency
430+
return m.MaxConcurrency
429431
}
430432

431-
func (m *XmuxConfig) GetNormalizedMaxConnections() RangeConfig {
433+
func (m *XmuxConfig) GetNormalizedMaxConnections() *RangeConfig {
432434
if m.MaxConnections == nil {
433-
return RangeConfig{
435+
return &RangeConfig{
434436
From: 0,
435437
To: 0,
436438
}
437439
}
438440

439-
return *m.MaxConnections
441+
return m.MaxConnections
440442
}
441443

442-
func (m *XmuxConfig) GetNormalizedCMaxReuseTimes() RangeConfig {
444+
func (m *XmuxConfig) GetNormalizedCMaxReuseTimes() *RangeConfig {
443445
if m.CMaxReuseTimes == nil {
444-
return RangeConfig{
446+
return &RangeConfig{
445447
From: 0,
446448
To: 0,
447449
}
448450
}
449451

450-
return *m.CMaxReuseTimes
452+
return m.CMaxReuseTimes
451453
}
452454

453-
func (m *XmuxConfig) GetNormalizedHMaxRequestTimes() RangeConfig {
455+
func (m *XmuxConfig) GetNormalizedHMaxRequestTimes() *RangeConfig {
454456
if m.HMaxRequestTimes == nil {
455-
return RangeConfig{
457+
return &RangeConfig{
456458
From: 0,
457459
To: 0,
458460
}
459461
}
460462

461-
return *m.HMaxRequestTimes
463+
return m.HMaxRequestTimes
462464
}
463465

464-
func (m *XmuxConfig) GetNormalizedHMaxReusableSecs() RangeConfig {
466+
func (m *XmuxConfig) GetNormalizedHMaxReusableSecs() *RangeConfig {
465467
if m.HMaxReusableSecs == nil {
466-
return RangeConfig{
468+
return &RangeConfig{
467469
From: 0,
468470
To: 0,
469471
}
470472
}
471473

472-
return *m.HMaxReusableSecs
474+
return m.HMaxReusableSecs
473475
}
474476

475477
func init() {
@@ -478,10 +480,44 @@ func init() {
478480
}))
479481
}
480482

481-
func (c RangeConfig) rand() int32 {
483+
func (c *RangeConfig) rand() int32 {
484+
if c == nil {
485+
return 0
486+
}
482487
return int32(crypto.RandBetween(int64(c.From), int64(c.To)))
483488
}
484489

490+
// predefined
491+
var PredefinedTable = map[string]string{
492+
"ALPHABET": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
493+
"Alphabet": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
494+
"BASE36": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
495+
"Base62": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
496+
"HEX": "0123456789ABCDEF",
497+
"alphabet": "abcdefghijklmnopqrstuvwxyz",
498+
"base36": "0123456789abcdefghijklmnopqrstuvwxyz",
499+
"hex": "0123456789abcdef",
500+
"number": "0123456789",
501+
}
502+
503+
func (c *Config) GenerateSessionID() string {
504+
length := c.SessionIDLength.rand()
505+
table := c.SessionIDTable
506+
if predefined, ok := PredefinedTable[table]; ok {
507+
table = predefined
508+
}
509+
if table != "" && length > 0 {
510+
id := make([]byte, length)
511+
for i := range id {
512+
id[i] = table[rand.N(len(table))]
513+
}
514+
return string(id)
515+
} else {
516+
uuid := uuid.New()
517+
return uuid.String()
518+
}
519+
}
520+
485521
func appendToPath(path, value string) string {
486522
if strings.HasSuffix(path, "/") {
487523
return path + value

0 commit comments

Comments
 (0)