1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-07 10:46:31 -05:00

accounts in protobuf

This commit is contained in:
Darien Raymond 2016-09-18 00:41:21 +02:00
parent 3423adaea4
commit d08cba000f
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
40 changed files with 790 additions and 224 deletions

View File

@ -2,5 +2,12 @@
{
"editor.tabSize": 2,
"go.buildTags": "json"
"go.buildTags": "json",
"protoc": {
"options": [
"--proto_path=$GOPATH/src/",
"--proto_path=$GOPATH/src/github.com/google/protobuf/src"
]
}
}

View File

@ -3,3 +3,9 @@ package protocol
type Account interface {
Equals(Account) bool
}
type AsAccount interface {
AsAccount() (Account, error)
}
type NewAccountFactory func() AsAccount

View File

@ -77,6 +77,6 @@ type CommandSwitchAccount struct {
Port v2net.Port
ID *uuid.UUID
AlterIds uint16
Level UserLevel
Level uint32
ValidMin byte
}

View File

@ -13,9 +13,9 @@ func TestServerList(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
assert.Uint32(list.Size()).Equals(1)
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
assert.Uint32(list.Size()).Equals(2)
server := list.GetServer(1)
@ -32,9 +32,9 @@ func TestServerPicker(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
picker := NewRoundRobinServerPicker(list)
server := picker.PickServer()

View File

@ -45,19 +45,26 @@ func (this *TimeoutValidStrategy) Invalidate() {
type ServerSpec struct {
sync.RWMutex
dest v2net.Destination
users []*User
valid ValidationStrategy
dest v2net.Destination
users []*User
valid ValidationStrategy
newAccount NewAccountFactory
}
func NewServerSpec(dest v2net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {
func NewServerSpec(newAccount NewAccountFactory, dest v2net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {
return &ServerSpec{
dest: dest,
users: users,
valid: valid,
dest: dest,
users: users,
valid: valid,
newAccount: newAccount,
}
}
func NewServerSpecFromPB(newAccount NewAccountFactory, spec ServerSpecPB) *ServerSpec {
dest := v2net.TCPDestination(spec.Address.AsAddress(), v2net.Port(spec.Port))
return NewServerSpec(newAccount, dest, AlwaysValid(), spec.Users...)
}
func (this *ServerSpec) Destination() v2net.Destination {
return this.dest
}
@ -66,9 +73,13 @@ func (this *ServerSpec) HasUser(user *User) bool {
this.RLock()
defer this.RUnlock()
account := user.Account
accountA, err := user.GetTypedAccount(this.newAccount())
if err != nil {
return false
}
for _, u := range this.users {
if u.Account.Equals(account) {
accountB, err := u.GetTypedAccount(this.newAccount())
if err == nil && accountA.Equals(accountB) {
return true
}
}

View File

@ -0,0 +1,81 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/common/protocol/server_spec.proto
// DO NOT EDIT!
/*
Package protocol is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/common/protocol/server_spec.proto
v2ray.com/core/common/protocol/user.proto
It has these top-level messages:
ServerSpecPB
User
*/
package protocol
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import com_v2ray_core_common_net "v2ray.com/core/common/net"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ServerSpecPB struct {
Address *com_v2ray_core_common_net.AddressPB `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
Port uint32 `protobuf:"varint,2,opt,name=port" json:"port,omitempty"`
Users []*User `protobuf:"bytes,3,rep,name=users" json:"users,omitempty"`
}
func (m *ServerSpecPB) Reset() { *m = ServerSpecPB{} }
func (m *ServerSpecPB) String() string { return proto.CompactTextString(m) }
func (*ServerSpecPB) ProtoMessage() {}
func (*ServerSpecPB) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *ServerSpecPB) GetAddress() *com_v2ray_core_common_net.AddressPB {
if m != nil {
return m.Address
}
return nil
}
func (m *ServerSpecPB) GetUsers() []*User {
if m != nil {
return m.Users
}
return nil
}
func init() {
proto.RegisterType((*ServerSpecPB)(nil), "com.v2ray.core.common.protocol.ServerSpecPB")
}
func init() { proto.RegisterFile("v2ray.com/core/common/protocol/server_spec.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8e, 0x3f, 0x4b, 0xc5, 0x30,
0x14, 0xc5, 0x89, 0xf5, 0x1f, 0x51, 0x97, 0x4c, 0xa5, 0x83, 0x14, 0x11, 0xac, 0xcb, 0x8d, 0xd4,
0xcd, 0x41, 0xb0, 0x9f, 0xa0, 0xb4, 0xb8, 0xb8, 0x48, 0x4d, 0xef, 0x66, 0x7a, 0xc3, 0x4d, 0x2c,
0xf8, 0x65, 0xfc, 0xac, 0xf2, 0x92, 0x97, 0xad, 0xbc, 0xb7, 0x1d, 0x0e, 0xe7, 0x77, 0xce, 0x91,
0x4f, 0x6b, 0xcb, 0xd3, 0x2f, 0x18, 0xb2, 0xda, 0x10, 0xa3, 0x36, 0x64, 0x2d, 0x2d, 0xda, 0x31,
0x05, 0x32, 0xf4, 0xad, 0x3d, 0xf2, 0x8a, 0xfc, 0xe9, 0x1d, 0x1a, 0x88, 0xa6, 0xba, 0x35, 0x64,
0x21, 0x53, 0x8c, 0x90, 0x08, 0xc8, 0x44, 0xf5, 0xb0, 0xdd, 0xb8, 0x60, 0xd0, 0xd3, 0x3c, 0x33,
0x7a, 0x9f, 0xb2, 0xd5, 0xe3, 0x91, 0xe9, 0x1f, 0x8f, 0x9c, 0xa2, 0x77, 0x7f, 0x42, 0x5e, 0x8f,
0xf1, 0xc9, 0xe8, 0xd0, 0xf4, 0x9d, 0x7a, 0x95, 0x17, 0xfb, 0xb2, 0x52, 0xd4, 0xa2, 0xb9, 0x6a,
0xef, 0x61, 0xfb, 0xd6, 0x82, 0x01, 0xde, 0x52, 0xb2, 0xef, 0x86, 0x0c, 0x29, 0x25, 0x4f, 0x1d,
0x71, 0x28, 0x4f, 0x6a, 0xd1, 0xdc, 0x0c, 0x51, 0xab, 0x17, 0x79, 0xb6, 0x9b, 0xf4, 0x65, 0x51,
0x17, 0x07, 0x1a, 0xf3, 0x3f, 0x78, 0xf7, 0xc8, 0x43, 0x42, 0x3a, 0xf9, 0x71, 0x99, 0xfd, 0xaf,
0xf3, 0xa8, 0x9e, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xde, 0x92, 0x28, 0x40, 0x5b, 0x01, 0x00,
0x00,
}

View File

@ -0,0 +1,13 @@
syntax = "proto3";
import "v2ray.com/core/common/net/address.proto";
import "v2ray.com/core/common/protocol/user.proto";
package com.v2ray.core.common.protocol;
option go_package = "protocol";
message ServerSpecPB {
com.v2ray.core.common.net.AddressPB address = 1;
uint32 port = 2;
repeated com.v2ray.core.common.protocol.User users = 3;
}

View File

@ -4,41 +4,10 @@ import (
"testing"
"time"
v2net "v2ray.com/core/common/net"
. "v2ray.com/core/common/protocol"
"v2ray.com/core/testing/assert"
)
type TestAccount struct {
id int
}
func (this *TestAccount) Equals(account Account) bool {
return account.(*TestAccount).id == this.id
}
func TestServerSpecUser(t *testing.T) {
assert := assert.On(t)
account := &TestAccount{
id: 0,
}
user := NewUser(UserLevel(0), "")
user.Account = account
rec := NewServerSpec(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80), AlwaysValid(), user)
assert.Bool(rec.HasUser(user)).IsTrue()
account2 := &TestAccount{
id: 1,
}
user2 := NewUser(UserLevel(0), "")
user2.Account = account2
assert.Bool(rec.HasUser(user2)).IsFalse()
rec.AddUser(user2)
assert.Bool(rec.HasUser(user2)).IsTrue()
}
func TestAlwaysValidStrategy(t *testing.T) {
assert := assert.On(t)

View File

@ -1,35 +1,44 @@
package protocol
type UserLevel byte
import (
"errors"
const (
UserLevelAdmin = UserLevel(255)
UserLevelUntrusted = UserLevel(0)
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
)
type User struct {
Account Account
Level UserLevel
Email string
var (
ErrUserMissing = errors.New("User is not specified.")
ErrAccountMissing = errors.New("Account is not specified.")
ErrNonMessageType = errors.New("Not a protobuf message.")
)
func (this *User) GetTypedAccount(account AsAccount) (Account, error) {
anyAccount := this.GetAccount()
if anyAccount == nil {
return nil, ErrAccountMissing
}
protoAccount, ok := account.(proto.Message)
if !ok {
return nil, ErrNonMessageType
}
err := ptypes.UnmarshalAny(anyAccount, protoAccount)
if err != nil {
return nil, err
}
return account.AsAccount()
}
func NewUser(level UserLevel, email string) *User {
return &User{
Level: level,
Email: email,
func (this *User) GetSettings() UserSettings {
settings := UserSettings{
PayloadReadTimeout: 120,
}
if this.Level > 0 {
settings.PayloadReadTimeout = 0
}
return settings
}
type UserSettings struct {
PayloadReadTimeout uint32
}
func GetUserSettings(level UserLevel) UserSettings {
settings := UserSettings{
PayloadReadTimeout: 120,
}
if level > 0 {
settings.PayloadReadTimeout = 0
}
return settings
}

View File

@ -0,0 +1,55 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/common/protocol/user.proto
// DO NOT EDIT!
package protocol
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/any"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type User struct {
Level uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
Email string `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"`
Account *google_protobuf.Any `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"`
}
func (m *User) Reset() { *m = User{} }
func (m *User) String() string { return proto.CompactTextString(m) }
func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (m *User) GetAccount() *google_protobuf.Any {
if m != nil {
return m.Account
}
return nil
}
func init() {
proto.RegisterType((*User)(nil), "com.v2ray.core.common.protocol.User")
}
func init() { proto.RegisterFile("v2ray.com/core/common/protocol/user.proto", fileDescriptor1) }
var fileDescriptor1 = []byte{
// 179 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x34, 0x8e, 0xcb, 0xaa, 0xc2, 0x30,
0x10, 0x86, 0xc9, 0x39, 0x5e, 0x23, 0x6e, 0x4a, 0x17, 0xd5, 0x85, 0x14, 0x57, 0x75, 0x33, 0x81,
0xfa, 0x04, 0xfa, 0x08, 0x05, 0x37, 0xee, 0xd2, 0x61, 0x2c, 0x42, 0x92, 0x91, 0xf4, 0x02, 0x79,
0x7b, 0xb1, 0x21, 0xbb, 0xf9, 0x66, 0xbe, 0xe1, 0xff, 0xe5, 0x65, 0xaa, 0xbd, 0x0e, 0x80, 0x6c,
0x15, 0xb2, 0x27, 0x85, 0x6c, 0x2d, 0x3b, 0xf5, 0xf1, 0x3c, 0x30, 0xb2, 0x51, 0x63, 0x4f, 0x1e,
0x66, 0xca, 0x4e, 0xc8, 0x16, 0x92, 0xee, 0x09, 0xa2, 0x0a, 0x49, 0x3d, 0x1e, 0x3a, 0xe6, 0xce,
0x50, 0xfc, 0x6d, 0xc7, 0x97, 0xd2, 0x2e, 0xc4, 0xeb, 0xb9, 0x95, 0x8b, 0x47, 0x4f, 0x3e, 0xcb,
0xe5, 0xd2, 0xd0, 0x44, 0xa6, 0x10, 0xa5, 0xa8, 0xf6, 0x4d, 0x84, 0xdf, 0x96, 0xac, 0x7e, 0x9b,
0xe2, 0xaf, 0x14, 0xd5, 0xb6, 0x89, 0x90, 0x81, 0x5c, 0x6b, 0x44, 0x1e, 0xdd, 0x50, 0xfc, 0x97,
0xa2, 0xda, 0xd5, 0x39, 0xc4, 0x00, 0x48, 0x01, 0x70, 0x73, 0xa1, 0x49, 0xd2, 0x5d, 0x3e, 0x37,
0xa9, 0x4a, 0xbb, 0x9a, 0xa7, 0xeb, 0x37, 0x00, 0x00, 0xff, 0xff, 0xfa, 0x7e, 0xbf, 0xfa, 0xde,
0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,12 @@
syntax = "proto3";
import "google/protobuf/any.proto";
package com.v2ray.core.common.protocol;
option go_package = "protocol";
message User {
uint32 level = 1;
string email = 2;
google.protobuf.Any account = 3;
}

View File

@ -15,7 +15,7 @@ func (u *User) UnmarshalJSON(data []byte) error {
}
u.Email = rawUserValue.EmailString
u.Level = UserLevel(rawUserValue.LevelByte)
u.Level = uint32(rawUserValue.LevelByte)
return nil
}

View File

@ -8,6 +8,35 @@ import (
"v2ray.com/core/common/protocol"
)
func (this *Config) GetCipher() Cipher {
switch this.Cipher {
case Config_AES_128_CFB:
return &AesCfb{KeyBytes: 16}
case Config_AES_256_CFB:
return &AesCfb{KeyBytes: 32}
case Config_CHACHA20:
return &ChaCha20{IVBytes: 8}
case Config_CHACHA20_IEFT:
return &ChaCha20{IVBytes: 12}
}
panic("Failed to create Cipher. Should not happen.")
}
func (this *Account) Equals(another protocol.Account) bool {
if account, ok := another.(*Account); ok {
return account.Password == this.Password
}
return false
}
func (this *Account) AsAccount() (protocol.Account, error) {
return this, nil
}
func (this *Account) GetCipherKey(size int) []byte {
return PasswordToCipherKey(this.Password, size)
}
type Cipher interface {
KeySize() int
IVSize() int
@ -57,14 +86,6 @@ func (this *ChaCha20) NewDecodingStream(key []byte, iv []byte) (cipher.Stream, e
return crypto.NewChaCha20Stream(key, iv), nil
}
type Config struct {
Cipher Cipher
Key []byte
UDP bool
Level protocol.UserLevel
Email string
}
func PasswordToCipherKey(password string, keySize int) []byte {
pwdBytes := []byte(password)
key := make([]byte, 0, keySize)

View File

@ -0,0 +1,120 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/proxy/shadowsocks/config.proto
// DO NOT EDIT!
/*
Package shadowsocks is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/proxy/shadowsocks/config.proto
It has these top-level messages:
Account
Config
*/
package shadowsocks
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import com_v2ray_core_common_protocol "v2ray.com/core/common/protocol"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Config_Cipher int32
const (
Config_UNKNOWN Config_Cipher = 0
Config_AES_128_CFB Config_Cipher = 1
Config_AES_256_CFB Config_Cipher = 2
Config_CHACHA20 Config_Cipher = 3
Config_CHACHA20_IEFT Config_Cipher = 4
)
var Config_Cipher_name = map[int32]string{
0: "UNKNOWN",
1: "AES_128_CFB",
2: "AES_256_CFB",
3: "CHACHA20",
4: "CHACHA20_IEFT",
}
var Config_Cipher_value = map[string]int32{
"UNKNOWN": 0,
"AES_128_CFB": 1,
"AES_256_CFB": 2,
"CHACHA20": 3,
"CHACHA20_IEFT": 4,
}
func (x Config_Cipher) String() string {
return proto.EnumName(Config_Cipher_name, int32(x))
}
func (Config_Cipher) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} }
type Account struct {
Password string `protobuf:"bytes,1,opt,name=password" json:"password,omitempty"`
}
func (m *Account) Reset() { *m = Account{} }
func (m *Account) String() string { return proto.CompactTextString(m) }
func (*Account) ProtoMessage() {}
func (*Account) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Config struct {
Cipher Config_Cipher `protobuf:"varint,1,opt,name=cipher,enum=com.v2ray.core.proxy.shadowsocks.Config_Cipher" json:"cipher,omitempty"`
UdpEnabled bool `protobuf:"varint,2,opt,name=udp_enabled,json=udpEnabled" json:"udp_enabled,omitempty"`
User *com_v2ray_core_common_protocol.User `protobuf:"bytes,3,opt,name=user" json:"user,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Config) GetUser() *com_v2ray_core_common_protocol.User {
if m != nil {
return m.User
}
return nil
}
func init() {
proto.RegisterType((*Account)(nil), "com.v2ray.core.proxy.shadowsocks.Account")
proto.RegisterType((*Config)(nil), "com.v2ray.core.proxy.shadowsocks.Config")
proto.RegisterEnum("com.v2ray.core.proxy.shadowsocks.Config_Cipher", Config_Cipher_name, Config_Cipher_value)
}
func init() { proto.RegisterFile("v2ray.com/core/proxy/shadowsocks/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 308 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x41, 0x4f, 0xc2, 0x40,
0x14, 0x84, 0x2d, 0x90, 0x82, 0xaf, 0xa2, 0x75, 0x4f, 0x84, 0x8b, 0x0d, 0xd1, 0x04, 0x0f, 0xee,
0x6a, 0x8d, 0x86, 0x6b, 0x69, 0x40, 0x8c, 0x09, 0x26, 0x55, 0xa2, 0xf1, 0xd2, 0x94, 0xed, 0x2a,
0x44, 0xda, 0xd7, 0xec, 0x52, 0x91, 0x3f, 0xe0, 0xef, 0x36, 0x6e, 0xad, 0x21, 0x5c, 0x3c, 0xbe,
0xc9, 0x7c, 0x6f, 0x66, 0xe0, 0xec, 0xc3, 0x95, 0xd1, 0x9a, 0x72, 0x4c, 0x18, 0x47, 0x29, 0x58,
0x26, 0xf1, 0x73, 0xcd, 0xd4, 0x2c, 0x8a, 0x71, 0xa5, 0x90, 0xbf, 0x2b, 0xc6, 0x31, 0x7d, 0x9d,
0xbf, 0xd1, 0x4c, 0xe2, 0x12, 0x89, 0xc3, 0x31, 0xa1, 0x25, 0x22, 0x05, 0xd5, 0x76, 0xba, 0x61,
0x6f, 0x9f, 0x6e, 0x3d, 0xe4, 0x98, 0x24, 0x98, 0x32, 0x8d, 0x73, 0x5c, 0xb0, 0x5c, 0x09, 0x59,
0x3c, 0xeb, 0x9c, 0x40, 0xdd, 0xe3, 0x1c, 0xf3, 0x74, 0x49, 0xda, 0xd0, 0xc8, 0x22, 0xa5, 0x56,
0x28, 0xe3, 0x96, 0xe1, 0x18, 0xdd, 0xdd, 0xe0, 0xef, 0xee, 0x7c, 0x55, 0xc0, 0xf4, 0x75, 0x09,
0x72, 0x03, 0x26, 0x9f, 0x67, 0x33, 0x21, 0xb5, 0x69, 0xdf, 0x65, 0xf4, 0xbf, 0x3e, 0xb4, 0x20,
0xa9, 0xaf, 0xb1, 0xe0, 0x17, 0x27, 0x47, 0x60, 0xe5, 0x71, 0x16, 0x8a, 0x34, 0x9a, 0x2e, 0x44,
0xdc, 0xaa, 0x38, 0x46, 0xb7, 0x11, 0x40, 0x1e, 0x67, 0x83, 0x42, 0x21, 0x3d, 0xa8, 0xfd, 0x34,
0x6d, 0x55, 0x1d, 0xa3, 0x6b, 0xb9, 0xc7, 0xdb, 0x39, 0xc5, 0x2a, 0x5a, 0xae, 0xa2, 0x13, 0x25,
0x64, 0xa0, 0x89, 0xce, 0x33, 0x98, 0x45, 0x18, 0xb1, 0xa0, 0x3e, 0x19, 0xdf, 0x8d, 0xef, 0x9f,
0xc6, 0xf6, 0x0e, 0x39, 0x00, 0xcb, 0x1b, 0x3c, 0x84, 0x17, 0x6e, 0x2f, 0xf4, 0x87, 0x7d, 0xdb,
0x28, 0x05, 0xf7, 0xea, 0x5a, 0x0b, 0x15, 0xb2, 0x07, 0x0d, 0x7f, 0xe4, 0xf9, 0x23, 0xcf, 0x3d,
0xb7, 0xab, 0xe4, 0x10, 0x9a, 0xe5, 0x15, 0xde, 0x0e, 0x86, 0x8f, 0x76, 0xad, 0xdf, 0x7c, 0xb1,
0x36, 0x96, 0x4d, 0x4d, 0x9d, 0x7e, 0xf9, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xee, 0x41, 0x94,
0xc3, 0x01, 0x00, 0x00,
}

View File

@ -0,0 +1,23 @@
syntax = "proto3";
import "v2ray.com/core/common/protocol/user.proto";
package com.v2ray.core.proxy.shadowsocks;
option go_package = "shadowsocks";
message Account {
string password = 1;
}
message Config {
enum Cipher {
UNKNOWN = 0;
AES_128_CFB = 1;
AES_256_CFB = 2;
CHACHA20 = 3;
CHACHA20_IEFT = 4;
}
Cipher cipher = 1;
bool udp_enabled = 2;
com.v2ray.core.common.protocol.User user = 3;
}

View File

@ -11,6 +11,8 @@ import (
"v2ray.com/core/common/log"
"v2ray.com/core/common/protocol"
"v2ray.com/core/proxy/registry"
"github.com/golang/protobuf/ptypes"
)
func (this *Config) UnmarshalJSON(data []byte) error {
@ -26,25 +28,17 @@ func (this *Config) UnmarshalJSON(data []byte) error {
return errors.New("Shadowsocks: Failed to parse config: " + err.Error())
}
this.UDP = jsonConfig.UDP
this.UdpEnabled = jsonConfig.UDP
jsonConfig.Cipher = strings.ToLower(jsonConfig.Cipher)
switch jsonConfig.Cipher {
case "aes-256-cfb":
this.Cipher = &AesCfb{
KeyBytes: 32,
}
this.Cipher = Config_AES_256_CFB
case "aes-128-cfb":
this.Cipher = &AesCfb{
KeyBytes: 16,
}
this.Cipher = Config_AES_128_CFB
case "chacha20":
this.Cipher = &ChaCha20{
IVBytes: 8,
}
this.Cipher = Config_CHACHA20
case "chacha20-ietf":
this.Cipher = &ChaCha20{
IVBytes: 12,
}
this.Cipher = Config_CHACHA20_IEFT
default:
log.Error("Shadowsocks: Unknown cipher method: ", jsonConfig.Cipher)
return common.ErrBadConfiguration
@ -54,10 +48,18 @@ func (this *Config) UnmarshalJSON(data []byte) error {
log.Error("Shadowsocks: Password is not specified.")
return common.ErrBadConfiguration
}
this.Key = PasswordToCipherKey(jsonConfig.Password, this.Cipher.KeySize())
this.Level = protocol.UserLevel(jsonConfig.Level)
this.Email = jsonConfig.Email
account, err := ptypes.MarshalAny(&Account{
Password: jsonConfig.Password,
})
if err != nil {
log.Error("Shadowsocks: Failed to create account: ", err)
return common.ErrBadConfiguration
}
this.User = &protocol.User{
Email: jsonConfig.Email,
Level: uint32(jsonConfig.Level),
Account: account,
}
return nil
}

View File

@ -21,6 +21,8 @@ func TestConfigParsing(t *testing.T) {
err := json.Unmarshal([]byte(rawJson), config)
assert.Error(err).IsNil()
assert.Int(config.Cipher.KeySize()).Equals(16)
assert.Bytes(config.Key).Equals([]byte{160, 224, 26, 2, 22, 110, 9, 80, 65, 52, 80, 20, 38, 243, 224, 241})
assert.Int(config.GetCipher().KeySize()).Equals(16)
account, err := config.User.GetTypedAccount(&Account{})
assert.Error(err).IsNil()
assert.Bytes(account.(*Account).GetCipherKey(config.GetCipher().KeySize())).Equals([]byte{160, 224, 26, 2, 22, 110, 9, 80, 65, 52, 80, 20, 38, 243, 224, 241})
}

View File

@ -24,6 +24,8 @@ import (
type Server struct {
packetDispatcher dispatcher.PacketDispatcher
config *Config
cipher Cipher
cipherKey []byte
meta *proxy.InboundHandlerMeta
accepting bool
tcpHub *internet.TCPHub
@ -31,12 +33,31 @@ type Server struct {
udpServer *udp.UDPServer
}
func NewServer(config *Config, packetDispatcher dispatcher.PacketDispatcher, meta *proxy.InboundHandlerMeta) *Server {
return &Server{
config: config,
packetDispatcher: packetDispatcher,
meta: meta,
func NewServer(config *Config, space app.Space, meta *proxy.InboundHandlerMeta) (*Server, error) {
if config.GetUser() == nil {
return nil, protocol.ErrUserMissing
}
account := new(Account)
if _, err := config.GetUser().GetTypedAccount(account); err != nil {
return nil, err
}
cipher := config.GetCipher()
s := &Server{
config: config,
meta: meta,
cipher: cipher,
cipherKey: account.GetCipherKey(cipher.KeySize()),
}
space.InitializeApplication(func() error {
if !space.HasApp(dispatcher.APP_ID) {
return app.ErrMissingApplication
}
s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
return nil
})
return s, nil
}
func (this *Server) Port() v2net.Port {
@ -70,7 +91,7 @@ func (this *Server) Start() error {
}
this.tcpHub = tcpHub
if this.config.UDP {
if this.config.UdpEnabled {
this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher)
udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, udp.ListenOption{Callback: this.handlerUDPPayload})
if err != nil {
@ -89,12 +110,11 @@ func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.Sess
defer payload.Release()
source := session.Source
ivLen := this.config.Cipher.IVSize()
ivLen := this.cipher.IVSize()
iv := payload.Value[:ivLen]
key := this.config.Key
payload.SliceFrom(ivLen)
stream, err := this.config.Cipher.NewDecodingStream(key, iv)
stream, err := this.cipher.NewDecodingStream(this.cipherKey, iv)
if err != nil {
log.Error("Shadowsocks: Failed to create decoding stream: ", err)
return
@ -102,7 +122,7 @@ func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.Sess
reader := crypto.NewCryptionReader(stream, payload)
request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), true)
request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(this.cipherKey, iv)), true)
if err != nil {
if err != io.EOF {
log.Access(source, "", log.AccessRejected, err)
@ -125,7 +145,7 @@ func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.Sess
rand.Read(response.Value)
respIv := response.Value
stream, err := this.config.Cipher.NewEncodingStream(key, respIv)
stream, err := this.cipher.NewEncodingStream(this.cipherKey, respIv)
if err != nil {
log.Error("Shadowsocks: Failed to create encoding stream: ", err)
return
@ -149,7 +169,7 @@ func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.Sess
writer.Write(payload.Value)
if request.OTA {
respAuth := NewAuthenticator(HeaderKeyGenerator(key, respIv))
respAuth := NewAuthenticator(HeaderKeyGenerator(this.cipherKey, respIv))
respAuth.Authenticate(response.Value, response.Value[ivLen:])
}
@ -169,7 +189,7 @@ func (this *Server) handleConnection(conn internet.Connection) {
bufferedReader := v2io.NewBufferedReader(timedReader)
defer bufferedReader.Release()
ivLen := this.config.Cipher.IVSize()
ivLen := this.cipher.IVSize()
_, err := io.ReadFull(bufferedReader, buffer.Value[:ivLen])
if err != nil {
if err != io.EOF {
@ -180,9 +200,8 @@ func (this *Server) handleConnection(conn internet.Connection) {
}
iv := buffer.Value[:ivLen]
key := this.config.Key
stream, err := this.config.Cipher.NewDecodingStream(key, iv)
stream, err := this.cipher.NewDecodingStream(this.cipherKey, iv)
if err != nil {
log.Error("Shadowsocks: Failed to create decoding stream: ", err)
return
@ -190,7 +209,7 @@ func (this *Server) handleConnection(conn internet.Connection) {
reader := crypto.NewCryptionReader(stream, bufferedReader)
request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), false)
request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(this.cipherKey, iv)), false)
if err != nil {
log.Access(conn.RemoteAddr(), "", log.AccessRejected, err)
log.Warning("Shadowsocks: Invalid request from ", conn.RemoteAddr(), ": ", err)
@ -199,7 +218,7 @@ func (this *Server) handleConnection(conn internet.Connection) {
defer request.Release()
bufferedReader.SetCached(false)
userSettings := protocol.GetUserSettings(this.config.Level)
userSettings := this.config.GetUser().GetSettings()
timedReader.SetTimeOut(userSettings.PayloadReadTimeout)
dest := v2net.TCPDestination(request.Address, request.Port)
@ -219,7 +238,7 @@ func (this *Server) handleConnection(conn internet.Connection) {
payload.SliceBack(ivLen)
rand.Read(payload.Value[:ivLen])
stream, err := this.config.Cipher.NewEncodingStream(key, payload.Value[:ivLen])
stream, err := this.cipher.NewEncodingStream(this.cipherKey, payload.Value[:ivLen])
if err != nil {
log.Error("Shadowsocks: Failed to create encoding stream: ", err)
return
@ -264,10 +283,7 @@ func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *
if !space.HasApp(dispatcher.APP_ID) {
return nil, common.ErrBadConfiguration
}
return NewServer(
rawConfig.(*Config),
space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
meta), nil
return NewServer(rawConfig.(*Config), space, meta)
}
func init() {

View File

@ -4,15 +4,17 @@ import (
"v2ray.com/core/common/protocol"
)
type Account struct {
Username string `json:"user"`
Password string `json:"pass"`
func (this *Account) Equals(another protocol.Account) bool {
if account, ok := another.(*Account); ok {
return this.Username == account.Username
}
return false
}
func (this *Account) Equals(another protocol.Account) bool {
socksAccount, ok := another.(*Account)
if !ok {
return false
}
return this.Username == socksAccount.Username
func (this *Account) AsAccount() (protocol.Account, error) {
return this, nil
}
func NewAccount() protocol.AsAccount {
return &Account{}
}

View File

@ -2,8 +2,27 @@ package socks
import (
"v2ray.com/core/common/protocol"
"github.com/golang/protobuf/ptypes"
google_protobuf "github.com/golang/protobuf/ptypes/any"
)
func AccountEquals(a, b *google_protobuf.Any) bool {
accountA := new(Account)
if err := ptypes.UnmarshalAny(a, accountA); err != nil {
return false
}
accountB := new(Account)
if err := ptypes.UnmarshalAny(b, accountB); err != nil {
return false
}
return accountA.Equals(accountB)
}
func (this *Account) AsAny() (*google_protobuf.Any, error) {
return ptypes.MarshalAny(this)
}
type ClientConfig struct {
Servers []*protocol.ServerSpec
}

View File

@ -0,0 +1,61 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/proxy/socks/client_config.proto
// DO NOT EDIT!
/*
Package socks is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/proxy/socks/client_config.proto
v2ray.com/core/proxy/socks/server_config.proto
It has these top-level messages:
Account
ServerConfig
*/
package socks
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Account struct {
Username string `protobuf:"bytes,1,opt,name=username" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password" json:"password,omitempty"`
}
func (m *Account) Reset() { *m = Account{} }
func (m *Account) String() string { return proto.CompactTextString(m) }
func (*Account) ProtoMessage() {}
func (*Account) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func init() {
proto.RegisterType((*Account)(nil), "com.v2ray.core.proxy.socks.Account")
}
func init() { proto.RegisterFile("v2ray.com/core/proxy/socks/client_config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 146 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x2b, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x28, 0xca, 0xaf, 0xa8,
0xd4, 0x2f, 0xce, 0x4f, 0xce, 0x2e, 0xd6, 0x4f, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x89, 0x4f, 0xce,
0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x4a, 0xce, 0xcf, 0x85,
0xeb, 0x29, 0x4a, 0xd5, 0x03, 0xab, 0xd7, 0x03, 0xab, 0x57, 0x72, 0xe4, 0x62, 0x77, 0x4c, 0x4e,
0xce, 0x2f, 0xcd, 0x2b, 0x11, 0x92, 0xe2, 0xe2, 0x28, 0x2d, 0x4e, 0x2d, 0xca, 0x4b, 0xcc, 0x4d,
0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0xf3, 0x41, 0x72, 0x05, 0x89, 0xc5, 0xc5, 0xe5,
0xf9, 0x45, 0x29, 0x12, 0x4c, 0x10, 0x39, 0x18, 0xdf, 0x89, 0x3d, 0x8a, 0x15, 0x6c, 0x56, 0x12,
0x1b, 0xd8, 0x3a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe9, 0xf0, 0x36, 0x26, 0xa0, 0x00,
0x00, 0x00,
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package com.v2ray.core.proxy.socks;
option go_package = "socks";
message Account {
string username = 1;
string password = 2;
}

View File

@ -11,6 +11,20 @@ import (
"v2ray.com/core/proxy/registry"
)
func (this *Account) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Username string `json:"user"`
Password string `json:"pass"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Socks: Failed to parse account: " + err.Error())
}
this.Username = jsonConfig.Username
this.Password = jsonConfig.Password
return nil
}
func (this *ClientConfig) UnmarshalJSON(data []byte) error {
type ServerConfig struct {
Address *v2net.AddressPB `json:"address"`
@ -26,7 +40,7 @@ func (this *ClientConfig) UnmarshalJSON(data []byte) error {
}
this.Servers = make([]*protocol.ServerSpec, len(jsonConfig.Servers))
for idx, serverConfig := range jsonConfig.Servers {
server := protocol.NewServerSpec(v2net.TCPDestination(serverConfig.Address.AsAddress(), serverConfig.Port), protocol.AlwaysValid())
server := protocol.NewServerSpec(NewAccount, v2net.TCPDestination(serverConfig.Address.AsAddress(), serverConfig.Port), protocol.AlwaysValid())
for _, rawUser := range serverConfig.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
@ -36,7 +50,11 @@ func (this *ClientConfig) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(rawUser, account); err != nil {
return errors.New("Socks|Client: Failed to parse socks account: " + err.Error())
}
user.Account = account
anyAccount, err := account.AsAny()
if err != nil {
return err
}
user.Account = anyAccount
server.AddUser(user)
}
this.Servers[idx] = server

View File

@ -2,15 +2,6 @@
// source: v2ray.com/core/proxy/socks/server_config.proto
// DO NOT EDIT!
/*
Package socks is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/proxy/socks/server_config.proto
It has these top-level messages:
ServerConfig
*/
package socks
import proto "github.com/golang/protobuf/proto"
@ -23,12 +14,6 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ServerConfig_AuthType int32
const (
@ -48,7 +33,7 @@ var ServerConfig_AuthType_value = map[string]int32{
func (x ServerConfig_AuthType) String() string {
return proto.EnumName(ServerConfig_AuthType_name, int32(x))
}
func (ServerConfig_AuthType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
func (ServerConfig_AuthType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0, 0} }
type ServerConfig struct {
AuthType ServerConfig_AuthType `protobuf:"varint,1,opt,name=auth_type,json=authType,enum=com.v2ray.core.proxy.socks.ServerConfig_AuthType" json:"auth_type,omitempty"`
@ -61,7 +46,7 @@ type ServerConfig struct {
func (m *ServerConfig) Reset() { *m = ServerConfig{} }
func (m *ServerConfig) String() string { return proto.CompactTextString(m) }
func (*ServerConfig) ProtoMessage() {}
func (*ServerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*ServerConfig) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (m *ServerConfig) GetAccounts() map[string]string {
if m != nil {
@ -82,9 +67,9 @@ func init() {
proto.RegisterEnum("com.v2ray.core.proxy.socks.ServerConfig_AuthType", ServerConfig_AuthType_name, ServerConfig_AuthType_value)
}
func init() { proto.RegisterFile("v2ray.com/core/proxy/socks/server_config.proto", fileDescriptor0) }
func init() { proto.RegisterFile("v2ray.com/core/proxy/socks/server_config.proto", fileDescriptor1) }
var fileDescriptor0 = []byte{
var fileDescriptor1 = []byte{
// 345 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x91, 0xd1, 0x4b, 0xeb, 0x30,
0x14, 0xc6, 0x6f, 0xd7, 0xbb, 0xdb, 0x2e, 0xdd, 0x2e, 0x23, 0xf8, 0x50, 0xf6, 0x62, 0x19, 0x8a,

46
proxy/vmess/account.go Normal file
View File

@ -0,0 +1,46 @@
package vmess
import (
"v2ray.com/core/common/dice"
"v2ray.com/core/common/log"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/uuid"
)
type Account struct {
ID *protocol.ID
AlterIDs []*protocol.ID
}
func NewAccount() protocol.AsAccount {
return &AccountPB{}
}
func (this *Account) AnyValidID() *protocol.ID {
if len(this.AlterIDs) == 0 {
return this.ID
}
return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
}
func (this *Account) Equals(account protocol.Account) bool {
vmessAccount, ok := account.(*Account)
if !ok {
return false
}
// TODO: handle AlterIds difference
return this.ID.Equals(vmessAccount.ID)
}
func (this *AccountPB) AsAccount() (protocol.Account, error) {
id, err := uuid.ParseString(this.Id)
if err != nil {
log.Error("VMess: Failed to parse ID: ", err)
return nil, err
}
protoId := protocol.NewID(id)
return &Account{
ID: protoId,
AlterIDs: protocol.NewAlterIDs(protoId, uint16(this.AlterId)),
}, nil
}

58
proxy/vmess/account.pb.go Normal file
View File

@ -0,0 +1,58 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/proxy/vmess/account.proto
// DO NOT EDIT!
/*
Package vmess is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/proxy/vmess/account.proto
It has these top-level messages:
AccountPB
*/
package vmess
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type AccountPB struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
AlterId uint32 `protobuf:"varint,2,opt,name=alterId" json:"alterId,omitempty"`
}
func (m *AccountPB) Reset() { *m = AccountPB{} }
func (m *AccountPB) String() string { return proto.CompactTextString(m) }
func (*AccountPB) ProtoMessage() {}
func (*AccountPB) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func init() {
proto.RegisterType((*AccountPB)(nil), "com.v2ray.core.proxy.vmess.AccountPB")
}
func init() { proto.RegisterFile("v2ray.com/core/proxy/vmess/account.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 138 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x28, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x28, 0xca, 0xaf, 0xa8,
0xd4, 0x2f, 0xcb, 0x4d, 0x2d, 0x2e, 0xd6, 0x4f, 0x4c, 0x4e, 0xce, 0x2f, 0xcd, 0x2b, 0xd1, 0x2b,
0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x4a, 0xce, 0xcf, 0xd5, 0x83, 0xa9, 0x2e, 0x4a, 0xd5, 0x03,
0xab, 0xd4, 0x03, 0xab, 0x54, 0x32, 0xe5, 0xe2, 0x74, 0x84, 0x28, 0x0e, 0x70, 0x12, 0xe2, 0xe3,
0x62, 0xca, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x62, 0xca, 0x4c, 0x11, 0x92, 0xe0,
0x62, 0x4f, 0xcc, 0x29, 0x49, 0x2d, 0xf2, 0x4c, 0x91, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x0d, 0x82,
0x71, 0x9d, 0xd8, 0xa3, 0x58, 0xc1, 0xfa, 0x93, 0xd8, 0xc0, 0x56, 0x18, 0x03, 0x02, 0x00, 0x00,
0xff, 0xff, 0xe4, 0xea, 0x97, 0xa3, 0x8e, 0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package com.v2ray.core.proxy.vmess;
option go_package = "vmess";
message AccountPB {
string id = 1;
uint32 alterId = 2;
}

View File

@ -4,13 +4,9 @@ package vmess
import (
"encoding/json"
"v2ray.com/core/common/log"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/uuid"
)
func (u *Account) UnmarshalJSON(data []byte) error {
func (u *AccountPB) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
ID string `json:"id"`
AlterIds uint16 `json:"alterId"`
@ -19,13 +15,8 @@ func (u *Account) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &rawConfig); err != nil {
return err
}
id, err := uuid.ParseString(rawConfig.ID)
if err != nil {
log.Error("VMess: Failed to parse ID: ", err)
return err
}
u.ID = protocol.NewID(id)
u.AlterIDs = protocol.NewAlterIDs(u.ID, rawConfig.AlterIds)
u.Id = rawConfig.ID
u.AlterId = uint32(rawConfig.AlterIds)
return nil
}

View File

@ -52,7 +52,12 @@ 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.Account.(*vmess.Account).AnyValidID().Bytes())
account, err := header.User.GetTypedAccount(&vmess.AccountPB{})
if err != nil {
log.Error("VMess: Failed to get user account: ", err)
return
}
idHash := this.idHash(account.(*vmess.Account).AnyValidID().Bytes())
idHash.Write(timestamp.Bytes(nil))
writer.Write(idHash.Sum(nil))
@ -83,8 +88,7 @@ func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, w
timestampHash := md5.New()
timestampHash.Write(hashTimestamp(timestamp))
iv := timestampHash.Sum(nil)
account := header.User.Account.(*vmess.Account)
aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(