1
0
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:
v2ray 2016-02-25 14:38:41 +01:00
parent b3f547dc90
commit 9f50692d15
9 changed files with 90 additions and 21 deletions

View File

@ -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)

View File

@ -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
} }

View File

@ -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(),

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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) {

View File

@ -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)
} }

View File

@ -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)

View File

@ -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,