Bladeren bron

allow dynamic type of user accounts

v2ray 9 jaren geleden
bovenliggende
commit
3f9cb1136a

+ 2 - 0
.vscode/settings.json

@@ -1,5 +1,7 @@
 // Place your settings in this file to overwrite default and user settings.
 {
+  "editor.tabSize": 2,
+  
   "go.buildFlags": ["-tags", "json"],
   "go.lintFlags": ["-tags", "json"],
   "go.vetFlags": ["-tags", "json"]

+ 16 - 0
common/protocol/account.go

@@ -1,4 +1,20 @@
 package protocol
 
+import (
+	"github.com/v2ray/v2ray-core/common/dice"
+)
+
 type Account interface {
 }
+
+type VMessAccount struct {
+	ID       *ID
+	AlterIDs []*ID
+}
+
+func (this *VMessAccount) AnyValidID() *ID {
+	if len(this.AlterIDs) == 0 {
+		return this.ID
+	}
+	return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
+}

+ 36 - 0
common/protocol/account_json.go

@@ -0,0 +1,36 @@
+// +build json
+
+package protocol
+
+import (
+	"errors"
+
+	"github.com/v2ray/v2ray-core/common/uuid"
+)
+
+type AccountJson struct {
+	ID       string `json:"id"`
+	AlterIds uint16 `json:"alterId"`
+
+	Username string `json:"user"`
+	Password string `json:"pass"`
+}
+
+func (this *AccountJson) GetAccount() (Account, error) {
+	if len(this.ID) > 0 {
+		id, err := uuid.ParseString(this.ID)
+		if err != nil {
+			return nil, err
+		}
+
+		primaryID := NewID(id)
+		alterIDs := NewAlterIDs(primaryID, this.AlterIds)
+
+		return &VMessAccount{
+			ID:       primaryID,
+			AlterIDs: alterIDs,
+		}, nil
+	}
+
+	return nil, errors.New("Protocol: Malformed account.")
+}

+ 3 - 2
common/protocol/raw/client.go

@@ -52,7 +52,7 @@ func NewClientSession(idHash protocol.IDHash) *ClientSession {
 
 func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) {
 	timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)()
-	idHash := this.idHash(header.User.AnyValidID().Bytes())
+	idHash := this.idHash(header.User.Account.(*protocol.VMessAccount).AnyValidID().Bytes())
 	idHash.Write(timestamp.Bytes())
 	writer.Write(idHash.Sum(nil))
 
@@ -87,7 +87,8 @@ func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, w
 	timestampHash := md5.New()
 	timestampHash.Write(hashTimestamp(timestamp))
 	iv := timestampHash.Sum(nil)
-	aesStream := crypto.NewAesEncryptionStream(header.User.ID.CmdKey(), iv)
+	account := header.User.Account.(*protocol.VMessAccount)
+	aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(), iv)
 	aesStream.XORKeyStream(buffer.Value, buffer.Value)
 	writer.Write(buffer.Value)
 

+ 4 - 2
common/protocol/raw/encoding_test.go

@@ -15,8 +15,10 @@ func TestRequestSerialization(t *testing.T) {
 	assert := assert.On(t)
 
 	user := protocol.NewUser(
-		protocol.NewID(uuid.New()),
-		nil,
+		&protocol.VMessAccount{
+			ID:       protocol.NewID(uuid.New()),
+			AlterIDs: nil,
+		},
 		protocol.UserLevelUntrusted,
 		"test@v2ray.com")
 

+ 2 - 1
common/protocol/raw/server.go

@@ -60,7 +60,8 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
 	timestampHash := md5.New()
 	timestampHash.Write(hashTimestamp(timestamp))
 	iv := timestampHash.Sum(nil)
-	aesStream := crypto.NewAesDecryptionStream(user.ID.CmdKey(), iv)
+	account := user.Account.(*protocol.VMessAccount)
+	aesStream := crypto.NewAesDecryptionStream(account.ID.CmdKey(), iv)
 	decryptor := crypto.NewCryptionReader(aesStream, reader)
 
 	nBytes, err := io.ReadFull(decryptor, buffer.Value[:41])

+ 7 - 20
common/protocol/user.go

@@ -1,9 +1,5 @@
 package protocol
 
-import (
-	"github.com/v2ray/v2ray-core/common/dice"
-)
-
 type UserLevel byte
 
 const (
@@ -12,26 +8,17 @@ const (
 )
 
 type User struct {
-	ID       *ID
-	AlterIDs []*ID
-	Level    UserLevel
-	Email    string
+	Account Account
+	Level   UserLevel
+	Email   string
 }
 
-func NewUser(primary *ID, secondary []*ID, level UserLevel, email string) *User {
+func NewUser(account Account, level UserLevel, email string) *User {
 	return &User{
-		ID:       primary,
-		AlterIDs: secondary,
-		Level:    level,
-		Email:    email,
-	}
-}
-
-func (this *User) AnyValidID() *ID {
-	if len(this.AlterIDs) == 0 {
-		return this.ID
+		Account: account,
+		Level:   level,
+		Email:   email,
 	}
-	return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
 }
 
 type UserSettings struct {

+ 11 - 13
common/protocol/user_json.go

@@ -2,30 +2,28 @@
 
 package protocol
 
-import (
-	"encoding/json"
-
-	"github.com/v2ray/v2ray-core/common/uuid"
-)
+import "encoding/json"
 
 func (u *User) UnmarshalJSON(data []byte) error {
 	type rawUser struct {
-		IdString     string `json:"id"`
-		EmailString  string `json:"email"`
-		LevelByte    byte   `json:"level"`
-		AlterIdCount uint16 `json:"alterId"`
+		EmailString string `json:"email"`
+		LevelByte   byte   `json:"level"`
 	}
 	var rawUserValue rawUser
 	if err := json.Unmarshal(data, &rawUserValue); err != nil {
 		return err
 	}
-	id, err := uuid.ParseString(rawUserValue.IdString)
+
+	var rawAccount AccountJson
+	if err := json.Unmarshal(data, &rawAccount); err != nil {
+		return err
+	}
+	account, err := rawAccount.GetAccount()
 	if err != nil {
 		return err
 	}
-	primaryID := NewID(id)
-	alterIDs := NewAlterIDs(primaryID, rawUserValue.AlterIdCount)
-	*u = *NewUser(primaryID, alterIDs, UserLevel(rawUserValue.LevelByte), rawUserValue.EmailString)
+
+	*u = *NewUser(account, UserLevel(rawUserValue.LevelByte), rawUserValue.EmailString)
 
 	return nil
 }

+ 4 - 1
common/protocol/user_json_test.go

@@ -21,8 +21,11 @@ func TestUserParsing(t *testing.T) {
     "alterId": 100
   }`), user)
 	assert.Error(err).IsNil()
-	assert.String(user.ID.String()).Equals("96edb838-6d68-42ef-a933-25f7ac3a9d09")
 	assert.Byte(byte(user.Level)).Equals(1)
+
+	account, ok := user.Account.(*VMessAccount)
+	assert.Bool(ok).IsTrue()
+	assert.String(account.ID.String()).Equals("96edb838-6d68-42ef-a933-25f7ac3a9d09")
 }
 
 func TestInvalidUserJson(t *testing.T) {

+ 3 - 2
common/protocol/user_validator.go

@@ -107,18 +107,19 @@ L:
 func (this *TimedUserValidator) Add(user *User) error {
 	idx := len(this.validUsers)
 	this.validUsers = append(this.validUsers, user)
+	account := user.Account.(*VMessAccount)
 
 	nowSec := time.Now().Unix()
 
 	entry := &idEntry{
-		id:             user.ID,
+		id:             account.ID,
 		userIdx:        idx,
 		lastSec:        Timestamp(nowSec - cacheDurationSec),
 		lastSecRemoval: Timestamp(nowSec - cacheDurationSec*3),
 	}
 	this.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry)
 	this.ids = append(this.ids, entry)
-	for _, alterid := range user.AlterIDs {
+	for _, alterid := range account.AlterIDs {
 		entry := &idEntry{
 			id:             alterid,
 			userIdx:        idx,

+ 3 - 0
proxy/http/client.go

@@ -1 +1,4 @@
 package http
+
+type Client struct {
+}

+ 3 - 0
proxy/http/config.go

@@ -48,3 +48,6 @@ func (this *Config) IsOwnHost(host v2net.Address) bool {
 	}
 	return false
 }
+
+type ClientConfig struct {
+}

+ 2 - 2
proxy/vmess/inbound/command.go

@@ -21,8 +21,8 @@ func (this *VMessInboundHandler) generateCommand(request *protocol.RequestHeader
 				user := inboundHandler.GetUser(request.User.Email)
 				return &protocol.CommandSwitchAccount{
 					Port:     inboundHandler.Port(),
-					ID:       user.ID.UUID(),
-					AlterIds: uint16(len(user.AlterIDs)),
+					ID:       user.Account.(*protocol.VMessAccount).ID.UUID(),
+					AlterIds: uint16(len(user.Account.(*protocol.VMessAccount).AlterIDs)),
 					Level:    user.Level,
 					ValidMin: byte(availableMin),
 				}

+ 5 - 1
proxy/vmess/inbound/inbound.go

@@ -50,7 +50,11 @@ func (this *userByEmail) Get(email string) (*protocol.User, bool) {
 		if !found {
 			id := protocol.NewID(uuid.New())
 			alterIDs := protocol.NewAlterIDs(id, this.defaultAlterIDs)
-			user = protocol.NewUser(id, alterIDs, this.defaultLevel, email)
+			account := &protocol.VMessAccount{
+				ID:       id,
+				AlterIDs: alterIDs,
+			}
+			user = protocol.NewUser(account, this.defaultLevel, email)
 			this.cache[email] = user
 		}
 		this.Unlock()

+ 5 - 1
proxy/vmess/outbound/command.go

@@ -8,7 +8,11 @@ import (
 func (this *VMessOutboundHandler) handleSwitchAccount(cmd *protocol.CommandSwitchAccount) {
 	primary := protocol.NewID(cmd.ID)
 	alters := protocol.NewAlterIDs(primary, cmd.AlterIds)
-	user := protocol.NewUser(primary, alters, cmd.Level, "")
+	account := &protocol.VMessAccount{
+		ID:       primary,
+		AlterIDs: alters,
+	}
+	user := protocol.NewUser(account, cmd.Level, "")
 	dest := v2net.TCPDestination(cmd.Host, cmd.Port)
 	this.receiverManager.AddDetour(NewReceiver(dest, user), cmd.ValidMin)
 }

+ 3 - 1
proxy/vmess/outbound/receiver.go

@@ -25,9 +25,11 @@ func NewReceiver(dest v2net.Destination, users ...*protocol.User) *Receiver {
 func (this *Receiver) HasUser(user *protocol.User) bool {
 	this.RLock()
 	defer this.RUnlock()
+	account := user.Account.(*protocol.VMessAccount)
 	for _, u := range this.Accounts {
 		// TODO: handle AlterIds difference.
-		if u.ID.Equals(user.ID) {
+		uAccount := u.Account.(*protocol.VMessAccount)
+		if uAccount.ID.Equals(account.ID) {
 			return true
 		}
 	}

+ 4 - 1
proxy/vmess/outbound/receiver_json_test.go

@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"testing"
 
+	"github.com/v2ray/v2ray-core/common/protocol"
 	. "github.com/v2ray/v2ray-core/proxy/vmess/outbound"
 	"github.com/v2ray/v2ray-core/testing/assert"
 )
@@ -30,5 +31,7 @@ func TestConfigTargetParsing(t *testing.T) {
 	assert.Error(err).IsNil()
 	assert.Destination(receiver.Destination).EqualsString("tcp:127.0.0.1:80")
 	assert.Int(len(receiver.Accounts)).Equals(1)
-	assert.String(receiver.Accounts[0].ID.String()).Equals("e641f5ad-9397-41e3-bf1a-e8740dfed019")
+
+	account := receiver.Accounts[0].Account.(*protocol.VMessAccount)
+	assert.String(account.ID.String()).Equals("e641f5ad-9397-41e3-bf1a-e8740dfed019")
 }

+ 10 - 2
proxy/vmess/outbound/receiver_test.go

@@ -15,14 +15,22 @@ func TestReceiverUser(t *testing.T) {
 
 	id := protocol.NewID(uuid.New())
 	alters := protocol.NewAlterIDs(id, 100)
-	user := protocol.NewUser(id, alters, protocol.UserLevel(0), "")
+	account := &protocol.VMessAccount{
+		ID:       id,
+		AlterIDs: alters,
+	}
+	user := protocol.NewUser(account, protocol.UserLevel(0), "")
 	rec := NewReceiver(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80), user)
 	assert.Bool(rec.HasUser(user)).IsTrue()
 	assert.Int(len(rec.Accounts)).Equals(1)
 
 	id2 := protocol.NewID(uuid.New())
 	alters2 := protocol.NewAlterIDs(id2, 100)
-	user2 := protocol.NewUser(id2, alters2, protocol.UserLevel(0), "")
+	account2 := &protocol.VMessAccount{
+		ID:       id2,
+		AlterIDs: alters2,
+	}
+	user2 := protocol.NewUser(account2, protocol.UserLevel(0), "")
 	assert.Bool(rec.HasUser(user2)).IsFalse()
 
 	rec.AddUser(user2)