Hysteria inbound: Support routing's vlessRoute as well (#6375)

https://github.com/XTLS/Xray-core/pull/6375#issuecomment-4795522284

---------

Co-authored-by: LjhAUMEM <llnu14702@gmail.com>
This commit is contained in:
seally
2026-06-27 17:04:58 +05:00
committed by GitHub
parent 345c76f9a8
commit 452b719504
3 changed files with 62 additions and 86 deletions
+51 -78
View File
@@ -3,25 +3,32 @@ package account
import ( import (
"sync" "sync"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/uuid"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func (a *Account) AsAccount() (protocol.Account, error) { func (a *Account) AsAccount() (protocol.Account, error) {
var VR net.Port
if id, err := uuid.ParseString(a.Auth); err == nil {
VR = net.PortFromBytes(id[6:8])
}
return &MemoryAccount{ return &MemoryAccount{
Auth: a.Auth, Auth: a.Auth,
VR: VR,
}, nil }, nil
} }
type MemoryAccount struct { type MemoryAccount struct {
Auth string Auth string
VR net.Port
} }
func (a *MemoryAccount) Equals(another protocol.Account) bool { func (a *MemoryAccount) Equals(other protocol.Account) bool {
if account, ok := another.(*MemoryAccount); ok { if b, ok := other.(*MemoryAccount); ok {
return a.Auth == account.Auth return a.Auth == b.Auth
} }
return false return false
} }
@@ -33,97 +40,63 @@ func (a *MemoryAccount) ToProto() proto.Message {
} }
type Validator struct { type Validator struct {
emails map[string]struct{} users sync.Map
users map[string]*protocol.MemoryUser
mutex sync.Mutex
} }
func NewValidator() *Validator { func NewValidator() *Validator {
return &Validator{ return &Validator{}
emails: make(map[string]struct{}),
users: make(map[string]*protocol.MemoryUser),
}
} }
func (v *Validator) Add(u *protocol.MemoryUser) error { func (v *Validator) Add(user *protocol.MemoryUser) error {
v.mutex.Lock() v.users.Store(user.Account.(*MemoryAccount).Auth, user)
defer v.mutex.Unlock()
if u.Email != "" {
if _, ok := v.emails[u.Email]; ok {
return errors.New("User ", u.Email, " already exists.")
}
v.emails[u.Email] = struct{}{}
}
v.users[u.Account.(*MemoryAccount).Auth] = u
return nil return nil
} }
func (v *Validator) Del(email string) error { func (v *Validator) DelByEmail(email string) error {
if email == "" { if user := v.GetByEmail(email); user != nil {
return errors.New("Email must not be empty.") v.users.Delete(user.Account.(*MemoryAccount).Auth)
} }
v.mutex.Lock()
defer v.mutex.Unlock()
if _, ok := v.emails[email]; !ok {
return errors.New("User ", email, " not found.")
}
delete(v.emails, email)
for key, user := range v.users {
if user.Email == email {
delete(v.users, key)
break
}
}
return nil return nil
} }
func (v *Validator) Get(auth string) *protocol.MemoryUser { func (v *Validator) Get(auth string) *protocol.MemoryUser {
v.mutex.Lock() if value, ok := v.users.Load(auth); ok {
defer v.mutex.Unlock() return value.(*protocol.MemoryUser)
return v.users[auth]
}
func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
if email == "" {
return nil
} }
v.mutex.Lock()
defer v.mutex.Unlock()
if _, ok := v.emails[email]; ok {
for _, user := range v.users {
if user.Email == email {
return user
}
}
}
return nil return nil
} }
func (v *Validator) GetAll() []*protocol.MemoryUser { func (v *Validator) GetByEmail(email string) (user *protocol.MemoryUser) {
v.mutex.Lock() v.users.Range(func(key, value any) bool {
defer v.mutex.Unlock() if value.(*protocol.MemoryUser).Email == email {
user = value.(*protocol.MemoryUser)
users := make([]*protocol.MemoryUser, 0, len(v.users)) return false
for _, user := range v.users { }
users = append(users, user) return true
} })
return
return users
} }
func (v *Validator) GetCount() int64 { func (v *Validator) GetAll() (users []*protocol.MemoryUser) {
v.mutex.Lock() v.users.Range(func(key, value any) bool {
defer v.mutex.Unlock() users = append(users, value.(*protocol.MemoryUser))
return true
return int64(len(v.users)) })
return
}
func (v *Validator) GetCount() (count int64) {
v.users.Range(func(key, value any) bool {
count++
return true
})
return
}
func (v *Validator) NotEmpty() (not_empty bool) {
v.users.Range(func(key, value any) bool {
not_empty = true
return false
})
return
} }
+10 -7
View File
@@ -59,12 +59,12 @@ func (s *Server) HysteriaInboundValidator() *account.Validator {
return s.validator return s.validator
} }
func (s *Server) AddUser(ctx context.Context, u *protocol.MemoryUser) error { func (s *Server) AddUser(ctx context.Context, user *protocol.MemoryUser) error {
return s.validator.Add(u) return s.validator.Add(user)
} }
func (s *Server) RemoveUser(ctx context.Context, e string) error { func (s *Server) RemoveUser(ctx context.Context, email string) error {
return s.validator.Del(e) return s.validator.DelByEmail(email)
} }
func (s *Server) GetUser(ctx context.Context, email string) *protocol.MemoryUser { func (s *Server) GetUser(ctx context.Context, email string) *protocol.MemoryUser {
@@ -91,9 +91,12 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
iConn := stat.TryUnwrapStatsConn(conn) iConn := stat.TryUnwrapStatsConn(conn)
type User interface{ User() *protocol.MemoryUser } if v, ok := iConn.(interface{ User() *protocol.MemoryUser }); ok {
if v, ok := iConn.(User); ok && v.User() != nil { user := v.User()
inbound.User = v.User() if user != nil {
inbound.User = user
inbound.VlessRoute = user.Account.(*account.MemoryAccount).VR
}
} }
if _, ok := iConn.(*hysteria.InterConn); ok { if _, ok := iConn.(*hysteria.InterConn); ok {
+1 -1
View File
@@ -58,7 +58,7 @@ func (h *httpHandler) AuthHTTP(w http.ResponseWriter, r *http.Request) bool {
var user *protocol.MemoryUser var user *protocol.MemoryUser
var ok bool var ok bool
if h.validator != nil && h.validator.GetCount() > 0 { if h.validator != nil && h.validator.NotEmpty() {
user = h.validator.Get(auth) user = h.validator.Get(auth)
} else if h.config.Auth != "" { } else if h.config.Auth != "" {
ok = auth == h.config.Auth ok = auth == h.config.Auth