From 7f300dbf0c1d520cb6e03c6e88b9b727f6777fd4 Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Mon, 18 Aug 2025 08:50:43 +0000 Subject: [PATCH] VLESS practice: Use user-sent VLESS UUID's 7th<<8 | 8th bytes as `vlessRoute` instead https://github.com/XTLS/Xray-core/pull/5009#issuecomment-3195718690 Replaces https://github.com/XTLS/Xray-core/commit/105b306d07de292ca4807e443bb050b9719e691d --- common/session/session.go | 2 +- features/routing/context.go | 2 +- proxy/vless/inbound/inbound.go | 2 +- proxy/vless/validator.go | 12 +++++++++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/common/session/session.go b/common/session/session.go index aad31cdf..7e0c0369 100644 --- a/common/session/session.go +++ b/common/session/session.go @@ -46,7 +46,7 @@ type Inbound struct { Name string // User is the user that authenticates for the inbound. May be nil if the protocol allows anonymous traffic. User *protocol.MemoryUser - // VlessRoute is the user-sent VLESS UUID's last byte. + // VlessRoute is the user-sent VLESS UUID's 7th<<8 | 8th bytes. VlessRoute net.Port // Used by splice copy. Conn is actually internet.Connection. May be nil. Conn net.Conn diff --git a/features/routing/context.go b/features/routing/context.go index d876e5bb..6b38d175 100644 --- a/features/routing/context.go +++ b/features/routing/context.go @@ -41,7 +41,7 @@ type Context interface { // GetUser returns the user email from the connection content, if exists. GetUser() string - // GetVlessRoute returns the user-sent VLESS UUID's last byte, if exists. + // GetVlessRoute returns the user-sent VLESS UUID's 7th<<8 | 8th bytes, if exists. GetVlessRoute() net.Port // GetAttributes returns extra attributes from the conneciont content. diff --git a/proxy/vless/inbound/inbound.go b/proxy/vless/inbound/inbound.go index 5359405e..dfa8d470 100644 --- a/proxy/vless/inbound/inbound.go +++ b/proxy/vless/inbound/inbound.go @@ -456,7 +456,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s } inbound.Name = "vless" inbound.User = request.User - inbound.VlessRoute = net.Port(userSentID[15]) + inbound.VlessRoute = net.PortFromBytes(userSentID[6:8]) account := request.User.Account.(*vless.MemoryAccount) diff --git a/proxy/vless/validator.go b/proxy/vless/validator.go index 61d5e025..35a4469a 100644 --- a/proxy/vless/validator.go +++ b/proxy/vless/validator.go @@ -18,6 +18,12 @@ type Validator interface { GetCount() int64 } +func ProcessUUID(id [16]byte) [16]byte { + id[6] = 0 + id[7] = 0 + return id +} + // MemoryValidator stores valid VLESS users. type MemoryValidator struct { // Considering email's usage here, map + sync.Mutex/RWMutex may have better performance. @@ -33,7 +39,7 @@ func (v *MemoryValidator) Add(u *protocol.MemoryUser) error { return errors.New("User ", u.Email, " already exists.") } } - v.users.Store([15]byte(u.Account.(*MemoryAccount).ID.Bytes()), u) + v.users.Store(ProcessUUID(u.Account.(*MemoryAccount).ID.UUID()), u) return nil } @@ -48,13 +54,13 @@ func (v *MemoryValidator) Del(e string) error { return errors.New("User ", e, " not found.") } v.email.Delete(le) - v.users.Delete([15]byte(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.Bytes())) + v.users.Delete(ProcessUUID(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.UUID())) return nil } // Get a VLESS user with UUID, nil if user doesn't exist. func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser { - u, _ := v.users.Load([15]byte(id[:])) + u, _ := v.users.Load(ProcessUUID(id)) if u != nil { return u.(*protocol.MemoryUser) }