VLESS practice: Use user-sent VLESS UUID's last byte as vlessRoute for routing rules

https://github.com/XTLS/Xray-core/pull/5009#issuecomment-3194262087
This commit is contained in:
RPRX
2025-08-17 13:55:18 +00:00
parent de23e51077
commit 105b306d07
15 changed files with 146 additions and 89 deletions

View File

@@ -62,7 +62,7 @@ func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requ
}
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator vless.Validator) (byte, *protocol.RequestHeader, *Addons, bool, error) {
buffer := buf.StackNew()
defer buffer.Release()
@@ -72,7 +72,7 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
request.Version = first.Byte(0)
} else {
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
return nil, nil, false, errors.New("failed to read request version").Base(err)
return 0, nil, nil, false, errors.New("failed to read request version").Base(err)
}
request.Version = buffer.Byte(0)
}
@@ -87,13 +87,13 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
} else {
buffer.Clear()
if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
return nil, nil, false, errors.New("failed to read request user id").Base(err)
return 0, nil, nil, false, errors.New("failed to read request user id").Base(err)
}
copy(id[:], buffer.Bytes())
}
if request.User = validator.Get(id); request.User == nil {
return nil, nil, isfb, errors.New("invalid request user id")
return 0, nil, nil, isfb, errors.New("invalid request user id")
}
if isfb {
@@ -102,12 +102,12 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
requestAddons, err := DecodeHeaderAddons(&buffer, reader)
if err != nil {
return nil, nil, false, errors.New("failed to decode request header addons").Base(err)
return 0, nil, nil, false, errors.New("failed to decode request header addons").Base(err)
}
buffer.Clear()
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
return nil, nil, false, errors.New("failed to read request command").Base(err)
return 0, nil, nil, false, errors.New("failed to read request command").Base(err)
}
request.Command = protocol.RequestCommand(buffer.Byte(0))
@@ -122,11 +122,11 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
}
}
if request.Address == nil {
return nil, nil, false, errors.New("invalid request address")
return 0, nil, nil, false, errors.New("invalid request address")
}
return request, requestAddons, false, nil
return id[15], request, requestAddons, false, nil
default:
return nil, nil, isfb, errors.New("invalid request version")
return 0, nil, nil, isfb, errors.New("invalid request version")
}
}

View File

@@ -45,7 +45,7 @@ func TestRequestSerialization(t *testing.T) {
Validator := new(vless.MemoryValidator)
Validator.Add(user)
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
_, actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
common.Must(err)
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
@@ -86,7 +86,7 @@ func TestInvalidRequest(t *testing.T) {
Validator := new(vless.MemoryValidator)
Validator.Add(user)
_, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
_, _, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
if err == nil {
t.Error("nil error")
}
@@ -117,7 +117,7 @@ func TestMuxRequest(t *testing.T) {
Validator := new(vless.MemoryValidator)
Validator.Add(user)
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
_, actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
common.Must(err)
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {

View File

@@ -217,6 +217,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
Buffer: buf.MultiBuffer{first},
}
var vlessRoute byte
var request *protocol.RequestHeader
var requestAddons *encoding.Addons
var err error
@@ -227,7 +228,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if isfb && firstLen < 18 {
err = errors.New("fallback directly")
} else {
request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
vlessRoute, request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
}
if err != nil {
@@ -455,6 +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(vlessRoute)
account := request.User.Account.(*vless.MemoryAccount)

View File

@@ -33,7 +33,7 @@ func (v *MemoryValidator) Add(u *protocol.MemoryUser) error {
return errors.New("User ", u.Email, " already exists.")
}
}
v.users.Store(u.Account.(*MemoryAccount).ID.UUID(), u)
v.users.Store([15]byte(u.Account.(*MemoryAccount).ID.Bytes()), u)
return nil
}
@@ -48,13 +48,13 @@ func (v *MemoryValidator) Del(e string) error {
return errors.New("User ", e, " not found.")
}
v.email.Delete(le)
v.users.Delete(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.UUID())
v.users.Delete([15]byte(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.Bytes()))
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(id)
u, _ := v.users.Load([15]byte(id[:]))
if u != nil {
return u.(*protocol.MemoryUser)
}