1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-14 03:40:43 +00: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
AlterIDs []*ID
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{
ID: id,
Level: level,
Email: email,
}
if alterIdCount > 0 {
u.AlterIDs = make([]*ID, alterIdCount)

View File

@ -23,7 +23,7 @@ func (u *User) UnmarshalJSON(data []byte) error {
if err != nil {
return err
}
*u = *NewUser(NewID(id), UserLevel(rawUserValue.LevelByte), rawUserValue.AlterIdCount)
*u = *NewUser(NewID(id), UserLevel(rawUserValue.LevelByte), rawUserValue.AlterIdCount, rawUserValue.EmailString)
return nil
}

View File

@ -7,9 +7,10 @@ import (
"github.com/v2ray/v2ray-core/common/log"
"github.com/v2ray/v2ray-core/common/serial"
"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)
commandBytes := alloc.NewSmallBuffer().Clear()
defer commandBytes.Release()
@ -26,7 +27,7 @@ func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) {
}
cmd = byte(1)
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{
Port: inboundHandler.Port(),
ID: user.ID.UUID(),

View File

@ -12,7 +12,13 @@ type FeaturesConfig struct {
Detour *DetourConfig
}
type DefaultConfig struct {
AlterIDs uint16
Level proto.UserLevel
}
type Config struct {
AllowedUsers []*proto.User
Features *FeaturesConfig
Defaults *DefaultConfig
}

View File

@ -33,10 +33,28 @@ func (this *FeaturesConfig) UnmarshalJSON(data []byte) error {
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 {
type JsonConfig struct {
Users []*proto.User `json:"clients"`
Features *FeaturesConfig `json:"features"`
Defaults *DefaultConfig `json:"default"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
@ -44,6 +62,13 @@ func (this *Config) UnmarshalJSON(data []byte) error {
}
this.AllowedUsers = jsonConfig.Users
this.Features = jsonConfig.Features
this.Defaults = jsonConfig.Defaults
if this.Defaults == nil {
this.Defaults = &DefaultConfig{
Level: proto.UserLevel(0),
AlterIDs: 32,
}
}
return nil
}

View File

@ -15,6 +15,7 @@ import (
v2net "github.com/v2ray/v2ray-core/common/net"
proto "github.com/v2ray/v2ray-core/common/protocol"
"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/internal"
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
@ -22,13 +23,51 @@ import (
"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.
type VMessInboundHandler struct {
sync.Mutex
packetDispatcher dispatcher.PacketDispatcher
inboundHandlerManager proxyman.InboundHandlerManager
clients protocol.UserSet
user *proto.User
usersByEmail *userByEmail
accepting bool
listener *hub.TCPHub
features *FeaturesConfig
@ -49,8 +88,12 @@ func (this *VMessInboundHandler) Close() {
}
}
func (this *VMessInboundHandler) GetUser() *proto.User {
return this.user
func (this *VMessInboundHandler) GetUser(email string) *proto.User {
user, existing := this.usersByEmail.Get(email)
if !existing {
this.clients.AddUser(user)
}
return user
}
func (this *VMessInboundHandler) Listen(port v2net.Port) error {
@ -117,7 +160,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.TCPConn) {
buffer := alloc.NewLargeBuffer().Clear()
defer buffer.Release()
buffer.AppendBytes(request.ResponseHeader, byte(0))
this.generateCommand(buffer)
this.generateCommand(request, buffer)
if data, open := <-output; open {
if request.IsChunkStream() {
@ -177,7 +220,7 @@ func init() {
packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
clients: allowedClients,
features: config.Features,
user: config.AllowedUsers[0],
usersByEmail: NewUserByEmail(config.AllowedUsers, config.Defaults),
}
if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {

View File

@ -11,7 +11,7 @@ import (
)
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)
this.receiverManager.AddDetour(NewReceiver(dest, user), cmd.ValidMin)
}

View File

@ -15,13 +15,13 @@ func TestReceiverUser(t *testing.T) {
v2testing.Current(t)
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)
assert.Bool(rec.HasUser(user)).IsTrue()
assert.Int(len(rec.Accounts)).Equals(1)
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()
rec.AddUser(user2)

View File

@ -29,15 +29,7 @@
"protocol": "vmess",
"port": "50035-50039",
"tag": "detour",
"settings": {
"clients": [
{
"id": "a12f49ba-466c-4dd5-8438-5c315143bc96",
"alterId": 100,
"level": 1
}
]
},
"settings": {},
"allocate": {
"strategy": "random",
"concurrency": 2,