mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 15:36:41 -05:00
auto user creation for dynamic port
This commit is contained in:
parent
b3f547dc90
commit
9f50692d15
@ -15,12 +15,14 @@ type User struct {
|
|||||||
ID *ID
|
ID *ID
|
||||||
AlterIDs []*ID
|
AlterIDs []*ID
|
||||||
Level UserLevel
|
Level UserLevel
|
||||||
|
Email string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUser(id *ID, level UserLevel, alterIdCount uint16) *User {
|
func NewUser(id *ID, level UserLevel, alterIdCount uint16, email string) *User {
|
||||||
u := &User{
|
u := &User{
|
||||||
ID: id,
|
ID: id,
|
||||||
Level: level,
|
Level: level,
|
||||||
|
Email: email,
|
||||||
}
|
}
|
||||||
if alterIdCount > 0 {
|
if alterIdCount > 0 {
|
||||||
u.AlterIDs = make([]*ID, alterIdCount)
|
u.AlterIDs = make([]*ID, alterIdCount)
|
||||||
|
@ -23,7 +23,7 @@ func (u *User) UnmarshalJSON(data []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*u = *NewUser(NewID(id), UserLevel(rawUserValue.LevelByte), rawUserValue.AlterIdCount)
|
*u = *NewUser(NewID(id), UserLevel(rawUserValue.LevelByte), rawUserValue.AlterIdCount, rawUserValue.EmailString)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,10 @@ import (
|
|||||||
"github.com/v2ray/v2ray-core/common/log"
|
"github.com/v2ray/v2ray-core/common/log"
|
||||||
"github.com/v2ray/v2ray-core/common/serial"
|
"github.com/v2ray/v2ray-core/common/serial"
|
||||||
"github.com/v2ray/v2ray-core/proxy/vmess/command"
|
"github.com/v2ray/v2ray-core/proxy/vmess/command"
|
||||||
|
"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) {
|
func (this *VMessInboundHandler) generateCommand(request *protocol.VMessRequest, buffer *alloc.Buffer) {
|
||||||
cmd := byte(0)
|
cmd := byte(0)
|
||||||
commandBytes := alloc.NewSmallBuffer().Clear()
|
commandBytes := alloc.NewSmallBuffer().Clear()
|
||||||
defer commandBytes.Release()
|
defer commandBytes.Release()
|
||||||
@ -26,7 +27,7 @@ func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) {
|
|||||||
}
|
}
|
||||||
cmd = byte(1)
|
cmd = byte(1)
|
||||||
log.Info("VMessIn: Pick detour handler for port ", inboundHandler.Port(), " for ", availableMin, " minutes.")
|
log.Info("VMessIn: Pick detour handler for port ", inboundHandler.Port(), " for ", availableMin, " minutes.")
|
||||||
user := inboundHandler.GetUser()
|
user := inboundHandler.GetUser(request.User.Email)
|
||||||
saCmd := &command.SwitchAccount{
|
saCmd := &command.SwitchAccount{
|
||||||
Port: inboundHandler.Port(),
|
Port: inboundHandler.Port(),
|
||||||
ID: user.ID.UUID(),
|
ID: user.ID.UUID(),
|
||||||
|
@ -12,7 +12,13 @@ type FeaturesConfig struct {
|
|||||||
Detour *DetourConfig
|
Detour *DetourConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DefaultConfig struct {
|
||||||
|
AlterIDs uint16
|
||||||
|
Level proto.UserLevel
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AllowedUsers []*proto.User
|
AllowedUsers []*proto.User
|
||||||
Features *FeaturesConfig
|
Features *FeaturesConfig
|
||||||
|
Defaults *DefaultConfig
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,28 @@ func (this *FeaturesConfig) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *DefaultConfig) UnmarshalJSON(data []byte) error {
|
||||||
|
type JsonDefaultConfig struct {
|
||||||
|
AlterIDs uint16 `json:"alterId"`
|
||||||
|
Level byte `json:"level"`
|
||||||
|
}
|
||||||
|
jsonConfig := new(JsonDefaultConfig)
|
||||||
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
this.AlterIDs = jsonConfig.AlterIDs
|
||||||
|
if this.AlterIDs == 0 {
|
||||||
|
this.AlterIDs = 32
|
||||||
|
}
|
||||||
|
this.Level = proto.UserLevel(jsonConfig.Level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Config) UnmarshalJSON(data []byte) error {
|
func (this *Config) UnmarshalJSON(data []byte) error {
|
||||||
type JsonConfig struct {
|
type JsonConfig struct {
|
||||||
Users []*proto.User `json:"clients"`
|
Users []*proto.User `json:"clients"`
|
||||||
Features *FeaturesConfig `json:"features"`
|
Features *FeaturesConfig `json:"features"`
|
||||||
|
Defaults *DefaultConfig `json:"default"`
|
||||||
}
|
}
|
||||||
jsonConfig := new(JsonConfig)
|
jsonConfig := new(JsonConfig)
|
||||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||||
@ -44,6 +62,13 @@ func (this *Config) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
this.AllowedUsers = jsonConfig.Users
|
this.AllowedUsers = jsonConfig.Users
|
||||||
this.Features = jsonConfig.Features
|
this.Features = jsonConfig.Features
|
||||||
|
this.Defaults = jsonConfig.Defaults
|
||||||
|
if this.Defaults == nil {
|
||||||
|
this.Defaults = &DefaultConfig{
|
||||||
|
Level: proto.UserLevel(0),
|
||||||
|
AlterIDs: 32,
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
proto "github.com/v2ray/v2ray-core/common/protocol"
|
proto "github.com/v2ray/v2ray-core/common/protocol"
|
||||||
"github.com/v2ray/v2ray-core/common/serial"
|
"github.com/v2ray/v2ray-core/common/serial"
|
||||||
|
"github.com/v2ray/v2ray-core/common/uuid"
|
||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
"github.com/v2ray/v2ray-core/proxy/internal"
|
"github.com/v2ray/v2ray-core/proxy/internal"
|
||||||
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
||||||
@ -22,13 +23,51 @@ import (
|
|||||||
"github.com/v2ray/v2ray-core/transport/hub"
|
"github.com/v2ray/v2ray-core/transport/hub"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type userByEmail struct {
|
||||||
|
sync.RWMutex
|
||||||
|
cache map[string]*proto.User
|
||||||
|
defaultLevel proto.UserLevel
|
||||||
|
defaultAlterIDs uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserByEmail(users []*proto.User, config *DefaultConfig) *userByEmail {
|
||||||
|
cache := make(map[string]*proto.User)
|
||||||
|
for _, user := range users {
|
||||||
|
cache[user.Email] = user
|
||||||
|
}
|
||||||
|
return &userByEmail{
|
||||||
|
cache: cache,
|
||||||
|
defaultLevel: config.Level,
|
||||||
|
defaultAlterIDs: config.AlterIDs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *userByEmail) Get(email string) (*proto.User, bool) {
|
||||||
|
var user *proto.User
|
||||||
|
var found bool
|
||||||
|
this.RLock()
|
||||||
|
user, found = this.cache[email]
|
||||||
|
this.RUnlock()
|
||||||
|
if !found {
|
||||||
|
this.Lock()
|
||||||
|
user, found = this.cache[email]
|
||||||
|
if !found {
|
||||||
|
id := proto.NewID(uuid.New())
|
||||||
|
user = proto.NewUser(id, this.defaultLevel, this.defaultAlterIDs, email)
|
||||||
|
this.cache[email] = user
|
||||||
|
}
|
||||||
|
this.Unlock()
|
||||||
|
}
|
||||||
|
return user, found
|
||||||
|
}
|
||||||
|
|
||||||
// Inbound connection handler that handles messages in VMess format.
|
// Inbound connection handler that handles messages in VMess format.
|
||||||
type VMessInboundHandler struct {
|
type VMessInboundHandler struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
packetDispatcher dispatcher.PacketDispatcher
|
packetDispatcher dispatcher.PacketDispatcher
|
||||||
inboundHandlerManager proxyman.InboundHandlerManager
|
inboundHandlerManager proxyman.InboundHandlerManager
|
||||||
clients protocol.UserSet
|
clients protocol.UserSet
|
||||||
user *proto.User
|
usersByEmail *userByEmail
|
||||||
accepting bool
|
accepting bool
|
||||||
listener *hub.TCPHub
|
listener *hub.TCPHub
|
||||||
features *FeaturesConfig
|
features *FeaturesConfig
|
||||||
@ -49,8 +88,12 @@ func (this *VMessInboundHandler) Close() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *VMessInboundHandler) GetUser() *proto.User {
|
func (this *VMessInboundHandler) GetUser(email string) *proto.User {
|
||||||
return this.user
|
user, existing := this.usersByEmail.Get(email)
|
||||||
|
if !existing {
|
||||||
|
this.clients.AddUser(user)
|
||||||
|
}
|
||||||
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *VMessInboundHandler) Listen(port v2net.Port) error {
|
func (this *VMessInboundHandler) Listen(port v2net.Port) error {
|
||||||
@ -117,7 +160,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.TCPConn) {
|
|||||||
buffer := alloc.NewLargeBuffer().Clear()
|
buffer := alloc.NewLargeBuffer().Clear()
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
buffer.AppendBytes(request.ResponseHeader, byte(0))
|
buffer.AppendBytes(request.ResponseHeader, byte(0))
|
||||||
this.generateCommand(buffer)
|
this.generateCommand(request, buffer)
|
||||||
|
|
||||||
if data, open := <-output; open {
|
if data, open := <-output; open {
|
||||||
if request.IsChunkStream() {
|
if request.IsChunkStream() {
|
||||||
@ -177,7 +220,7 @@ func init() {
|
|||||||
packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
|
packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
|
||||||
clients: allowedClients,
|
clients: allowedClients,
|
||||||
features: config.Features,
|
features: config.Features,
|
||||||
user: config.AllowedUsers[0],
|
usersByEmail: NewUserByEmail(config.AllowedUsers, config.Defaults),
|
||||||
}
|
}
|
||||||
|
|
||||||
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
|
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (this *VMessOutboundHandler) handleSwitchAccount(cmd *command.SwitchAccount) {
|
func (this *VMessOutboundHandler) handleSwitchAccount(cmd *command.SwitchAccount) {
|
||||||
user := proto.NewUser(proto.NewID(cmd.ID), cmd.Level, cmd.AlterIds.Value())
|
user := proto.NewUser(proto.NewID(cmd.ID), cmd.Level, cmd.AlterIds.Value(), "")
|
||||||
dest := v2net.TCPDestination(cmd.Host, cmd.Port)
|
dest := v2net.TCPDestination(cmd.Host, cmd.Port)
|
||||||
this.receiverManager.AddDetour(NewReceiver(dest, user), cmd.ValidMin)
|
this.receiverManager.AddDetour(NewReceiver(dest, user), cmd.ValidMin)
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ func TestReceiverUser(t *testing.T) {
|
|||||||
v2testing.Current(t)
|
v2testing.Current(t)
|
||||||
|
|
||||||
id := proto.NewID(uuid.New())
|
id := proto.NewID(uuid.New())
|
||||||
user := proto.NewUser(id, proto.UserLevel(0), 100)
|
user := proto.NewUser(id, proto.UserLevel(0), 100, "")
|
||||||
rec := NewReceiver(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80), user)
|
rec := NewReceiver(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80), user)
|
||||||
assert.Bool(rec.HasUser(user)).IsTrue()
|
assert.Bool(rec.HasUser(user)).IsTrue()
|
||||||
assert.Int(len(rec.Accounts)).Equals(1)
|
assert.Int(len(rec.Accounts)).Equals(1)
|
||||||
|
|
||||||
id2 := proto.NewID(uuid.New())
|
id2 := proto.NewID(uuid.New())
|
||||||
user2 := proto.NewUser(id2, proto.UserLevel(0), 100)
|
user2 := proto.NewUser(id2, proto.UserLevel(0), 100, "")
|
||||||
assert.Bool(rec.HasUser(user2)).IsFalse()
|
assert.Bool(rec.HasUser(user2)).IsFalse()
|
||||||
|
|
||||||
rec.AddUser(user2)
|
rec.AddUser(user2)
|
||||||
|
@ -29,15 +29,7 @@
|
|||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"port": "50035-50039",
|
"port": "50035-50039",
|
||||||
"tag": "detour",
|
"tag": "detour",
|
||||||
"settings": {
|
"settings": {},
|
||||||
"clients": [
|
|
||||||
{
|
|
||||||
"id": "a12f49ba-466c-4dd5-8438-5c315143bc96",
|
|
||||||
"alterId": 100,
|
|
||||||
"level": 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"allocate": {
|
"allocate": {
|
||||||
"strategy": "random",
|
"strategy": "random",
|
||||||
"concurrency": 2,
|
"concurrency": 2,
|
||||||
|
Loading…
Reference in New Issue
Block a user