From 3214a5078cda8c42f777e5961a154a6e9d4d5de8 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Mon, 27 Nov 2017 22:09:30 +0100 Subject: [PATCH] customizable policy --- app/dns/server/server_test.go | 3 + app/policy/config.go | 15 ++++ app/policy/config.pb.go | 140 +++++++++++++++++++++++++++++++ app/policy/config.proto | 27 ++++++ app/policy/manager/manager.go | 62 ++++++++++++++ app/policy/policy.go | 17 ++++ common/protocol/user.go | 19 ----- main/distro/all/all.go | 1 + proxy/dokodemo/config.pb.go | 48 ++++++----- proxy/dokodemo/config.proto | 3 +- proxy/dokodemo/dokodemo.go | 25 ++++-- proxy/freedom/config.pb.go | 52 +++++++----- proxy/freedom/config.proto | 3 +- proxy/freedom/freedom.go | 19 +++-- proxy/http/config.pb.go | 46 ++++++---- proxy/http/config.proto | 3 +- proxy/http/server.go | 24 ++++-- proxy/shadowsocks/client.go | 23 ++++- proxy/shadowsocks/config.proto | 2 +- proxy/shadowsocks/server.go | 26 ++++-- proxy/socks/config.pb.go | 69 ++++++++------- proxy/socks/config.proto | 5 +- proxy/socks/server.go | 24 ++++-- proxy/vmess/inbound/inbound.go | 17 +++- proxy/vmess/outbound/outbound.go | 20 ++++- v2ray.go | 20 ++++- 26 files changed, 554 insertions(+), 159 deletions(-) create mode 100644 app/policy/config.go create mode 100644 app/policy/config.pb.go create mode 100644 app/policy/config.proto create mode 100644 app/policy/manager/manager.go create mode 100644 app/policy/policy.go diff --git a/app/dns/server/server_test.go b/app/dns/server/server_test.go index 8a30b3612..daaae9db8 100644 --- a/app/dns/server/server_test.go +++ b/app/dns/server/server_test.go @@ -9,6 +9,8 @@ import ( _ "v2ray.com/core/app/dispatcher/impl" . "v2ray.com/core/app/dns" _ "v2ray.com/core/app/dns/server" + "v2ray.com/core/app/policy" + _ "v2ray.com/core/app/policy/manager" "v2ray.com/core/app/proxyman" _ "v2ray.com/core/app/proxyman/outbound" "v2ray.com/core/common" @@ -74,6 +76,7 @@ func TestUDPServer(t *testing.T) { common.Must(app.AddApplicationToSpace(ctx, config)) common.Must(app.AddApplicationToSpace(ctx, &dispatcher.Config{})) common.Must(app.AddApplicationToSpace(ctx, &proxyman.OutboundConfig{})) + common.Must(app.AddApplicationToSpace(ctx, &policy.Config{})) om := proxyman.OutboundHandlerManagerFromSpace(space) om.AddHandler(ctx, &proxyman.OutboundHandlerConfig{ diff --git a/app/policy/config.go b/app/policy/config.go new file mode 100644 index 000000000..073ce9f2e --- /dev/null +++ b/app/policy/config.go @@ -0,0 +1,15 @@ +package policy + +import ( + "time" + + "github.com/golang/protobuf/proto" +) + +func (s *Second) Duration() time.Duration { + return time.Second * time.Duration(s.Value) +} + +func (p *Policy) OverrideWith(another *Policy) { + proto.Merge(p, another) +} diff --git a/app/policy/config.pb.go b/app/policy/config.pb.go new file mode 100644 index 000000000..98063a4b9 --- /dev/null +++ b/app/policy/config.pb.go @@ -0,0 +1,140 @@ +package policy + +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 Second struct { + Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *Second) Reset() { *m = Second{} } +func (m *Second) String() string { return proto.CompactTextString(m) } +func (*Second) ProtoMessage() {} +func (*Second) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Second) GetValue() uint32 { + if m != nil { + return m.Value + } + return 0 +} + +type Policy struct { + Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout" json:"timeout,omitempty"` +} + +func (m *Policy) Reset() { *m = Policy{} } +func (m *Policy) String() string { return proto.CompactTextString(m) } +func (*Policy) ProtoMessage() {} +func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Policy) GetTimeout() *Policy_Timeout { + if m != nil { + return m.Timeout + } + return nil +} + +// Timeout is a message for timeout settings in various stages, in seconds. +type Policy_Timeout struct { + Handshake *Second `protobuf:"bytes,1,opt,name=handshake" json:"handshake,omitempty"` + ConnectionIdle *Second `protobuf:"bytes,2,opt,name=connection_idle,json=connectionIdle" json:"connection_idle,omitempty"` + UplinkOnly *Second `protobuf:"bytes,3,opt,name=uplink_only,json=uplinkOnly" json:"uplink_only,omitempty"` + DownlinkOnly *Second `protobuf:"bytes,4,opt,name=downlink_only,json=downlinkOnly" json:"downlink_only,omitempty"` +} + +func (m *Policy_Timeout) Reset() { *m = Policy_Timeout{} } +func (m *Policy_Timeout) String() string { return proto.CompactTextString(m) } +func (*Policy_Timeout) ProtoMessage() {} +func (*Policy_Timeout) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } + +func (m *Policy_Timeout) GetHandshake() *Second { + if m != nil { + return m.Handshake + } + return nil +} + +func (m *Policy_Timeout) GetConnectionIdle() *Second { + if m != nil { + return m.ConnectionIdle + } + return nil +} + +func (m *Policy_Timeout) GetUplinkOnly() *Second { + if m != nil { + return m.UplinkOnly + } + return nil +} + +func (m *Policy_Timeout) GetDownlinkOnly() *Second { + if m != nil { + return m.DownlinkOnly + } + return nil +} + +type Config struct { + Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +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{2} } + +func (m *Config) GetLevel() map[uint32]*Policy { + if m != nil { + return m.Level + } + return nil +} + +func init() { + proto.RegisterType((*Second)(nil), "v2ray.core.app.policy.Second") + proto.RegisterType((*Policy)(nil), "v2ray.core.app.policy.Policy") + proto.RegisterType((*Policy_Timeout)(nil), "v2ray.core.app.policy.Policy.Timeout") + proto.RegisterType((*Config)(nil), "v2ray.core.app.policy.Config") +} + +func init() { proto.RegisterFile("v2ray.com/core/app/policy/config.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 349 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x4a, 0xeb, 0x40, + 0x14, 0x86, 0x49, 0x7a, 0x9b, 0x72, 0x4f, 0x6f, 0xaf, 0x32, 0x58, 0x88, 0x05, 0xa5, 0x14, 0x94, + 0xae, 0x26, 0x90, 0x6e, 0x44, 0xb1, 0x62, 0x45, 0x41, 0x10, 0x2c, 0x51, 0x14, 0xdc, 0x94, 0x71, + 0x32, 0xda, 0xd0, 0xe9, 0x9c, 0x21, 0xa6, 0x95, 0xbc, 0x86, 0x6f, 0xe0, 0xd6, 0x87, 0xf2, 0x59, + 0x24, 0x99, 0x84, 0x6c, 0x5a, 0xe9, 0x6e, 0x72, 0xf8, 0xfe, 0x8f, 0x43, 0xfe, 0x03, 0x87, 0x4b, + 0x3f, 0x66, 0x29, 0xe5, 0x38, 0xf7, 0x38, 0xc6, 0xc2, 0x63, 0x5a, 0x7b, 0x1a, 0x65, 0xc4, 0x53, + 0x8f, 0xa3, 0x7a, 0x89, 0x5e, 0xa9, 0x8e, 0x31, 0x41, 0xd2, 0x2e, 0xb9, 0x58, 0x50, 0xa6, 0x35, + 0x35, 0x4c, 0x6f, 0x1f, 0x9c, 0x3b, 0xc1, 0x51, 0x85, 0x64, 0x07, 0xea, 0x4b, 0x26, 0x17, 0xc2, + 0xb5, 0xba, 0x56, 0xbf, 0x15, 0x98, 0x8f, 0xde, 0xb7, 0x0d, 0xce, 0x38, 0x47, 0xc9, 0x19, 0x34, + 0x92, 0x68, 0x2e, 0x70, 0x91, 0xe4, 0x48, 0xd3, 0x3f, 0xa0, 0x2b, 0x9d, 0xd4, 0xf0, 0xf4, 0xde, + 0xc0, 0x41, 0x99, 0xea, 0x7c, 0xd8, 0xd0, 0x28, 0x86, 0xe4, 0x04, 0xfe, 0x4e, 0x99, 0x0a, 0xdf, + 0xa6, 0x6c, 0x26, 0x0a, 0xdd, 0xde, 0x1a, 0x9d, 0xd9, 0x2f, 0xa8, 0x78, 0x72, 0x05, 0x5b, 0x1c, + 0x95, 0x12, 0x3c, 0x89, 0x50, 0x4d, 0xa2, 0x50, 0x0a, 0xd7, 0xde, 0x44, 0xf1, 0xbf, 0x4a, 0x5d, + 0x87, 0x52, 0x90, 0x21, 0x34, 0x17, 0x5a, 0x46, 0x6a, 0x36, 0x41, 0x25, 0x53, 0xb7, 0xb6, 0x89, + 0x03, 0x4c, 0xe2, 0x56, 0xc9, 0x94, 0x8c, 0xa0, 0x15, 0xe2, 0xbb, 0xaa, 0x0c, 0x7f, 0x36, 0x31, + 0xfc, 0x2b, 0x33, 0x99, 0xa3, 0xf7, 0x69, 0x81, 0x73, 0x91, 0x17, 0x45, 0x86, 0x50, 0x97, 0x62, + 0x29, 0xa4, 0x6b, 0x75, 0x6b, 0xfd, 0xa6, 0xdf, 0x5f, 0xa3, 0x31, 0x34, 0xbd, 0xc9, 0xd0, 0x4b, + 0x95, 0xc4, 0x69, 0x60, 0x62, 0x9d, 0x47, 0x80, 0x6a, 0x48, 0xb6, 0xa1, 0x36, 0x13, 0x69, 0xd1, + 0x66, 0xf6, 0x24, 0x83, 0xb2, 0xe1, 0xdf, 0x7f, 0x96, 0xa9, 0xaf, 0x38, 0x80, 0x63, 0xfb, 0xc8, + 0x1a, 0x9d, 0xc2, 0x2e, 0xc7, 0xf9, 0x6a, 0x7c, 0x6c, 0x3d, 0x39, 0xe6, 0xf5, 0x65, 0xb7, 0x1f, + 0xfc, 0x80, 0x65, 0x0b, 0xc6, 0x82, 0x9e, 0x6b, 0x5d, 0x98, 0x9e, 0x9d, 0xfc, 0x02, 0x07, 0x3f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x25, 0x25, 0xc2, 0xab, 0x02, 0x00, 0x00, +} diff --git a/app/policy/config.proto b/app/policy/config.proto new file mode 100644 index 000000000..b00aefc5c --- /dev/null +++ b/app/policy/config.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package v2ray.core.app.policy; +option csharp_namespace = "V2Ray.Core.App.Policy"; +option go_package = "policy"; +option java_package = "com.v2ray.core.app.policy"; +option java_multiple_files = true; + +message Second { + uint32 value = 1; +} + +message Policy { + // Timeout is a message for timeout settings in various stages, in seconds. + message Timeout { + Second handshake = 1; + Second connection_idle = 2; + Second uplink_only = 3; + Second downlink_only = 4; + } + + Timeout timeout = 1; +} + +message Config { + map level = 1; +} diff --git a/app/policy/manager/manager.go b/app/policy/manager/manager.go new file mode 100644 index 000000000..73ec14f8e --- /dev/null +++ b/app/policy/manager/manager.go @@ -0,0 +1,62 @@ +package manager + +import ( + "context" + + "v2ray.com/core/app/policy" + "v2ray.com/core/common" +) + +type Instance struct { + levels map[uint32]*policy.Policy +} + +func New(ctx context.Context, config *policy.Config) (*Instance, error) { + levels := config.Level + if levels == nil { + levels = make(map[uint32]*policy.Policy) + } + for _, p := range levels { + g := global() + g.OverrideWith(p) + *p = g + } + return &Instance{ + levels: levels, + }, nil +} + +func global() policy.Policy { + return policy.Policy{ + Timeout: &policy.Policy_Timeout{ + Handshake: &policy.Second{Value: 4}, + ConnectionIdle: &policy.Second{Value: 300}, + UplinkOnly: &policy.Second{Value: 5}, + DownlinkOnly: &policy.Second{Value: 30}, + }, + } +} + +func (m *Instance) GetPolicy(level uint32) policy.Policy { + if p, ok := m.levels[level]; ok { + return *p + } + return global() +} + +func (m *Instance) Start() error { + return nil +} + +func (m *Instance) Close() { +} + +func (m *Instance) Interface() interface{} { + return (*policy.Interface)(nil) +} + +func init() { + common.Must(common.RegisterConfig((*policy.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return New(ctx, config.(*policy.Config)) + })) +} diff --git a/app/policy/policy.go b/app/policy/policy.go new file mode 100644 index 000000000..1849a5ffa --- /dev/null +++ b/app/policy/policy.go @@ -0,0 +1,17 @@ +package policy + +import ( + "v2ray.com/core/app" +) + +type Interface interface { + GetPolicy(level uint32) Policy +} + +func PolicyFromSpace(space app.Space) Interface { + app := space.GetApplication((*Interface)(nil)) + if app == nil { + return nil + } + return app.(Interface) +} diff --git a/common/protocol/user.go b/common/protocol/user.go index 3ae450191..07f08ef94 100644 --- a/common/protocol/user.go +++ b/common/protocol/user.go @@ -1,7 +1,5 @@ package protocol -import "time" - func (u *User) GetTypedAccount() (Account, error) { if u.GetAccount() == nil { return nil, newError("Account missing").AtWarning() @@ -19,20 +17,3 @@ func (u *User) GetTypedAccount() (Account, error) { } return nil, newError("Unknown account type: ", u.Account.Type) } - -func (u *User) GetSettings() UserSettings { - settings := UserSettings{} - switch u.Level { - case 0: - settings.PayloadTimeout = time.Second * 30 - case 1: - settings.PayloadTimeout = time.Minute * 2 - default: - settings.PayloadTimeout = time.Minute * 5 - } - return settings -} - -type UserSettings struct { - PayloadTimeout time.Duration -} diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 8b51f1d13..800853bb7 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -4,6 +4,7 @@ import ( // The following are necessary as they register handlers in their init functions. _ "v2ray.com/core/app/dispatcher/impl" _ "v2ray.com/core/app/dns/server" + _ "v2ray.com/core/app/policy/manager" _ "v2ray.com/core/app/proxyman/inbound" _ "v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/router" diff --git a/proxy/dokodemo/config.pb.go b/proxy/dokodemo/config.pb.go index f4e8d36ff..c55306b8f 100644 --- a/proxy/dokodemo/config.pb.go +++ b/proxy/dokodemo/config.pb.go @@ -23,6 +23,7 @@ type Config struct { NetworkList *v2ray_core_common_net1.NetworkList `protobuf:"bytes,3,opt,name=network_list,json=networkList" json:"network_list,omitempty"` Timeout uint32 `protobuf:"varint,4,opt,name=timeout" json:"timeout,omitempty"` FollowRedirect bool `protobuf:"varint,5,opt,name=follow_redirect,json=followRedirect" json:"follow_redirect,omitempty"` + UserLevel uint32 `protobuf:"varint,6,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -65,6 +66,13 @@ func (m *Config) GetFollowRedirect() bool { return false } +func (m *Config) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + func init() { proto.RegisterType((*Config)(nil), "v2ray.core.proxy.dokodemo.Config") } @@ -72,23 +80,25 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/dokodemo/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 286 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcf, 0x4a, 0x03, 0x31, - 0x10, 0x87, 0x49, 0xad, 0x6d, 0x49, 0xfd, 0x03, 0x39, 0xa5, 0x82, 0x50, 0x7b, 0x69, 0xf1, 0x90, - 0x40, 0x3d, 0x7a, 0xb3, 0x15, 0x11, 0x44, 0x97, 0x1c, 0x3c, 0x78, 0x29, 0x6b, 0x36, 0x95, 0xd0, - 0x4d, 0x66, 0x99, 0x8d, 0xd6, 0x7d, 0x25, 0x5f, 0xcb, 0x17, 0x11, 0xb3, 0xbb, 0x28, 0x42, 0xbd, - 0xcd, 0x4c, 0xbe, 0x7c, 0x33, 0xfc, 0xe8, 0xf9, 0xdb, 0x1c, 0xd3, 0x4a, 0x68, 0x70, 0x52, 0x03, - 0x1a, 0x59, 0x20, 0xbc, 0x57, 0x32, 0x83, 0x0d, 0x64, 0xc6, 0x81, 0xd4, 0xe0, 0xd7, 0xf6, 0x45, - 0x14, 0x08, 0x01, 0xd8, 0xa8, 0x65, 0xd1, 0x88, 0xc8, 0x89, 0x96, 0x3b, 0x99, 0xfe, 0xd1, 0x68, - 0x70, 0x0e, 0xbc, 0xf4, 0x26, 0xc8, 0x34, 0xcb, 0xd0, 0x94, 0x65, 0xed, 0xf8, 0x0f, 0xf4, 0x26, - 0x6c, 0x01, 0x37, 0x35, 0x38, 0xf9, 0x24, 0xb4, 0xb7, 0x88, 0xdb, 0xd9, 0x25, 0xed, 0x37, 0x12, - 0x4e, 0xc6, 0x64, 0x36, 0x9c, 0x9f, 0x89, 0x5f, 0x97, 0xd4, 0x06, 0xe1, 0x4d, 0x10, 0xb7, 0xc9, - 0x03, 0x2e, 0xc1, 0xa5, 0xd6, 0xab, 0xf6, 0x07, 0x63, 0xb4, 0x5b, 0x00, 0x06, 0xde, 0x19, 0x93, - 0xd9, 0xa1, 0x8a, 0x35, 0xbb, 0xa6, 0x07, 0xcd, 0xb2, 0x55, 0x6e, 0xcb, 0xc0, 0xf7, 0xa2, 0x75, - 0xb2, 0xc3, 0x7a, 0x5f, 0xa3, 0x77, 0xb6, 0x0c, 0x6a, 0xe8, 0x7f, 0x1a, 0xc6, 0x69, 0x3f, 0x58, - 0x67, 0xe0, 0x35, 0xf0, 0x6e, 0xb4, 0xb7, 0x2d, 0x9b, 0xd2, 0xe3, 0x35, 0xe4, 0x39, 0x6c, 0x57, - 0x68, 0x32, 0x8b, 0x46, 0x07, 0xbe, 0x3f, 0x26, 0xb3, 0x81, 0x3a, 0xaa, 0xc7, 0xaa, 0x99, 0x5e, - 0xdd, 0xd0, 0x53, 0x0d, 0x4e, 0xec, 0x0c, 0x36, 0x21, 0x4f, 0x83, 0xb6, 0xfe, 0xe8, 0x8c, 0x1e, - 0xe7, 0x2a, 0xad, 0xc4, 0xe2, 0x9b, 0x4b, 0x22, 0xb7, 0x6c, 0xde, 0x9e, 0x7b, 0x31, 0xb5, 0x8b, - 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x1c, 0xb0, 0xd9, 0xd0, 0x01, 0x00, 0x00, + // 310 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcf, 0x4e, 0xc2, 0x40, + 0x10, 0x87, 0xd3, 0x8a, 0x80, 0x8b, 0x7f, 0x92, 0x3d, 0x2d, 0x46, 0x12, 0xe4, 0x02, 0xf1, 0xb0, + 0x4d, 0xf0, 0xe8, 0x0d, 0x30, 0xc6, 0x84, 0x28, 0xd9, 0x83, 0x07, 0x2f, 0xa4, 0xb6, 0x83, 0x69, + 0xe8, 0xee, 0x90, 0xe9, 0x02, 0xf6, 0x05, 0x7c, 0x18, 0x9f, 0xd2, 0x74, 0xdb, 0x46, 0x63, 0x82, + 0xb7, 0xd9, 0xdf, 0x7e, 0xf3, 0xcd, 0x64, 0xd8, 0xcd, 0x6e, 0x4c, 0x61, 0x2e, 0x23, 0xd4, 0x41, + 0x84, 0x04, 0xc1, 0x86, 0xf0, 0x23, 0x0f, 0x62, 0x5c, 0x63, 0x0c, 0x1a, 0x83, 0x08, 0xcd, 0x2a, + 0x79, 0x97, 0x1b, 0x42, 0x8b, 0xbc, 0x5b, 0xb3, 0x04, 0xd2, 0x71, 0xb2, 0xe6, 0x2e, 0x87, 0x7f, + 0x34, 0x11, 0x6a, 0x8d, 0x26, 0x30, 0x60, 0x83, 0x30, 0x8e, 0x09, 0xb2, 0xac, 0x74, 0xfc, 0x07, + 0x1a, 0xb0, 0x7b, 0xa4, 0x75, 0x09, 0x0e, 0x3e, 0x7d, 0xd6, 0x9c, 0xba, 0xe9, 0xfc, 0x8e, 0xb5, + 0x2a, 0x89, 0xf0, 0xfa, 0xde, 0xa8, 0x33, 0xbe, 0x96, 0xbf, 0x36, 0x29, 0x0d, 0xd2, 0x80, 0x95, + 0x8f, 0x8b, 0x67, 0x9a, 0xa1, 0x0e, 0x13, 0xa3, 0xea, 0x0e, 0xce, 0x59, 0x63, 0x83, 0x64, 0x85, + 0xdf, 0xf7, 0x46, 0x67, 0xca, 0xd5, 0xfc, 0x9e, 0x9d, 0x56, 0xc3, 0x96, 0x69, 0x92, 0x59, 0x71, + 0xe4, 0xac, 0x83, 0x03, 0xd6, 0xa7, 0x12, 0x9d, 0x27, 0x99, 0x55, 0x1d, 0xf3, 0xf3, 0xe0, 0x57, + 0xac, 0x65, 0x13, 0x0d, 0xb8, 0xb5, 0xa2, 0x51, 0xd8, 0x27, 0xbe, 0xf0, 0x54, 0x1d, 0xf1, 0x21, + 0xbb, 0x58, 0x61, 0x9a, 0xe2, 0x7e, 0x49, 0x10, 0x27, 0x04, 0x91, 0x15, 0xc7, 0x7d, 0x6f, 0xd4, + 0x56, 0xe7, 0x65, 0xac, 0xaa, 0x94, 0xf7, 0x18, 0xdb, 0x66, 0x40, 0xcb, 0x14, 0x76, 0x90, 0x8a, + 0xa6, 0xdb, 0xf3, 0xa4, 0x48, 0xe6, 0x45, 0x30, 0x79, 0x60, 0xbd, 0x08, 0xb5, 0x3c, 0x78, 0xfb, + 0x85, 0xf7, 0xda, 0xae, 0xeb, 0x2f, 0xbf, 0xfb, 0x32, 0x56, 0x61, 0x2e, 0xa7, 0x05, 0xb7, 0x70, + 0xdc, 0xac, 0xfa, 0x7b, 0x6b, 0xba, 0xc3, 0xde, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x33, 0x8e, + 0x70, 0xce, 0xf3, 0x01, 0x00, 0x00, } diff --git a/proxy/dokodemo/config.proto b/proxy/dokodemo/config.proto index d3cd6df16..19a07dcb3 100644 --- a/proxy/dokodemo/config.proto +++ b/proxy/dokodemo/config.proto @@ -13,6 +13,7 @@ message Config { v2ray.core.common.net.IPOrDomain address = 1; uint32 port = 2; v2ray.core.common.net.NetworkList network_list = 3; - uint32 timeout = 4; + uint32 timeout = 4 [deprecated = true]; bool follow_redirect = 5; + uint32 user_level = 6; } \ No newline at end of file diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index a62a21bdf..064105690 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -4,11 +4,11 @@ package dokodemo import ( "context" - "time" "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -22,6 +22,7 @@ type DokodemoDoor struct { config *Config address net.Address port net.Port + policy policy.Policy } func New(ctx context.Context, config *Config) (*DokodemoDoor, error) { @@ -37,6 +38,17 @@ func New(ctx context.Context, config *Config) (*DokodemoDoor, error) { address: config.GetPredefinedAddress(), port: net.Port(config.Port), } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + d.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + d.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return d, nil } @@ -60,13 +72,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("unable to get destination") } - timeout := time.Second * time.Duration(d.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } - ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, timeout) + timer := signal.CancelAfterInactivity(ctx, cancel, d.policy.Timeout.ConnectionIdle.Duration()) inboundRay, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -82,6 +89,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("failed to transport request").Base(err) } + timer.SetTimeout(d.policy.Timeout.DownlinkOnly.Duration()) + return nil }) @@ -107,7 +116,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("failed to transport response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(d.policy.Timeout.UplinkOnly.Duration()) return nil }) diff --git a/proxy/freedom/config.pb.go b/proxy/freedom/config.pb.go index cd1e925dd..7da98e3e7 100644 --- a/proxy/freedom/config.pb.go +++ b/proxy/freedom/config.pb.go @@ -57,6 +57,7 @@ type Config struct { DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.proxy.freedom.Config_DomainStrategy" json:"domain_strategy,omitempty"` Timeout uint32 `protobuf:"varint,2,opt,name=timeout" json:"timeout,omitempty"` DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride" json:"destination_override,omitempty"` + UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -85,6 +86,13 @@ func (m *Config) GetDestinationOverride() *DestinationOverride { return nil } +func (m *Config) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + func init() { proto.RegisterType((*DestinationOverride)(nil), "v2ray.core.proxy.freedom.DestinationOverride") proto.RegisterType((*Config)(nil), "v2ray.core.proxy.freedom.Config") @@ -94,25 +102,27 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/freedom/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 318 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xcf, 0x4a, 0xc3, 0x40, - 0x10, 0xc6, 0x4d, 0xc5, 0x14, 0x47, 0xac, 0x65, 0xeb, 0x21, 0x88, 0x87, 0xd2, 0x8b, 0x55, 0x70, - 0x23, 0xf1, 0x09, 0xec, 0x1f, 0xa1, 0x27, 0x4b, 0x82, 0xa2, 0x5e, 0x62, 0xcc, 0x4e, 0xcb, 0x82, - 0xd9, 0x09, 0x9b, 0xb5, 0x98, 0x27, 0xf0, 0x5d, 0x7c, 0x4a, 0x71, 0x93, 0xa2, 0x55, 0x73, 0xdb, - 0x99, 0xfd, 0x7d, 0xdf, 0xcc, 0x37, 0x70, 0xba, 0x0a, 0x74, 0x52, 0xf2, 0x94, 0x32, 0x3f, 0x25, - 0x8d, 0x7e, 0xae, 0xe9, 0xad, 0xf4, 0x17, 0x1a, 0x51, 0xd8, 0x96, 0x5a, 0xc8, 0x25, 0xcf, 0x35, - 0x19, 0x62, 0xde, 0x1a, 0xd5, 0xc8, 0x2d, 0xc6, 0x6b, 0xec, 0xe8, 0xe2, 0x97, 0x49, 0x4a, 0x59, - 0x46, 0xca, 0xb7, 0xb2, 0x94, 0x5e, 0xfc, 0x02, 0xf5, 0x0a, 0x75, 0x5c, 0xe4, 0x98, 0x56, 0x5e, - 0x83, 0x07, 0xe8, 0x4d, 0xb0, 0x30, 0x52, 0x25, 0x46, 0x92, 0xba, 0x59, 0xa1, 0xd6, 0x52, 0x20, - 0x1b, 0x81, 0x5b, 0xb1, 0x9e, 0xd3, 0x77, 0x86, 0x7b, 0xc1, 0x19, 0xff, 0x31, 0xb3, 0x72, 0xe5, - 0x6b, 0x57, 0x1e, 0x59, 0x72, 0xaa, 0x44, 0x4e, 0x52, 0x99, 0xb0, 0x56, 0x0e, 0xde, 0x5b, 0xe0, - 0x8e, 0xed, 0xde, 0xec, 0x1e, 0x0e, 0x04, 0x65, 0x89, 0x54, 0x71, 0x61, 0x74, 0x62, 0x70, 0x59, - 0x5a, 0xdf, 0x4e, 0xe0, 0xf3, 0xa6, 0x2c, 0xbc, 0x92, 0xf2, 0x89, 0xd5, 0x45, 0xb5, 0x2c, 0xec, - 0x88, 0x8d, 0x9a, 0x79, 0xd0, 0x36, 0x32, 0x43, 0x7a, 0x35, 0x5e, 0xab, 0xef, 0x0c, 0xf7, 0xc3, - 0x75, 0xc9, 0x9e, 0xe0, 0x50, 0x7c, 0x27, 0x8b, 0xa9, 0x8e, 0xe6, 0x6d, 0xdb, 0x40, 0xe7, 0xcd, - 0x83, 0xff, 0xb9, 0x47, 0xd8, 0x13, 0x7f, 0x9b, 0x83, 0x13, 0xe8, 0x6c, 0x6e, 0xc7, 0x76, 0x61, - 0xe7, 0x2a, 0x8a, 0x67, 0x51, 0x77, 0x8b, 0x01, 0xb8, 0xb7, 0xd1, 0x34, 0x9e, 0xcd, 0xbb, 0xce, - 0x68, 0x02, 0xc7, 0x29, 0x65, 0x8d, 0x13, 0xe7, 0xce, 0x63, 0xbb, 0x7e, 0x7e, 0xb4, 0xbc, 0xbb, - 0x20, 0x4c, 0x4a, 0x3e, 0xfe, 0xa2, 0xe6, 0x96, 0xba, 0xae, 0xbe, 0x9e, 0x5d, 0x7b, 0xf0, 0xcb, - 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x45, 0xb3, 0x84, 0x2e, 0x2a, 0x02, 0x00, 0x00, + // 340 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x6f, 0x4b, 0x83, 0x50, + 0x14, 0xc6, 0xd3, 0xca, 0xb1, 0x13, 0xad, 0xe1, 0x7a, 0x21, 0xb1, 0x60, 0xec, 0x4d, 0x2b, 0xe8, + 0x1a, 0xf6, 0x09, 0xda, 0x9f, 0x60, 0x10, 0x34, 0x94, 0xa2, 0x7a, 0x63, 0xa6, 0x67, 0x43, 0x98, + 0xf7, 0xc8, 0xf5, 0x4e, 0xf2, 0x2b, 0xed, 0x53, 0x86, 0x57, 0x47, 0x2d, 0xb6, 0x77, 0xfa, 0xf8, + 0x7b, 0x9e, 0x73, 0x9e, 0x23, 0x5c, 0xe7, 0x8e, 0x08, 0x0a, 0x16, 0x52, 0x62, 0x87, 0x24, 0xd0, + 0x4e, 0x05, 0x7d, 0x17, 0xf6, 0x5c, 0x20, 0x46, 0x4a, 0xe2, 0xf3, 0x78, 0xc1, 0x52, 0x41, 0x92, + 0x4c, 0x6b, 0x83, 0x0a, 0x64, 0x0a, 0x63, 0x35, 0x76, 0x71, 0xf7, 0x2f, 0x24, 0xa4, 0x24, 0x21, + 0x6e, 0x2b, 0x5b, 0x48, 0x4b, 0x3b, 0x43, 0x91, 0xa3, 0xf0, 0xb3, 0x14, 0xc3, 0x2a, 0xab, 0xff, + 0x0e, 0x9d, 0x31, 0x66, 0x32, 0xe6, 0x81, 0x8c, 0x89, 0x3f, 0xe7, 0x28, 0x44, 0x1c, 0xa1, 0x39, + 0x04, 0xa3, 0x62, 0x2d, 0xad, 0xa7, 0x0d, 0x4e, 0x9c, 0x1b, 0xf6, 0x67, 0x66, 0x95, 0xca, 0x36, + 0xa9, 0xcc, 0x53, 0xe4, 0x84, 0x47, 0x29, 0xc5, 0x5c, 0xba, 0xb5, 0xb3, 0xbf, 0xd6, 0xc1, 0x18, + 0xa9, 0xbd, 0xcd, 0x37, 0x38, 0x8b, 0x28, 0x09, 0x62, 0xee, 0x67, 0x52, 0x04, 0x12, 0x17, 0x85, + 0xca, 0x6d, 0x39, 0x36, 0xdb, 0xd7, 0x85, 0x55, 0x56, 0x36, 0x56, 0x3e, 0xaf, 0xb6, 0xb9, 0xad, + 0x68, 0xeb, 0xdd, 0xec, 0x42, 0x43, 0xc6, 0x09, 0xd2, 0x4a, 0x5a, 0x7a, 0x4f, 0x1b, 0x9c, 0x0e, + 0x75, 0x4b, 0x73, 0x37, 0x92, 0xf9, 0x09, 0xe7, 0xd1, 0x6f, 0x3b, 0x9f, 0xea, 0x7a, 0xd6, 0xa1, + 0x2a, 0x75, 0xbb, 0x7f, 0xf8, 0x8e, 0x9b, 0xb8, 0x9d, 0x68, 0xc7, 0xa1, 0x2e, 0x01, 0x56, 0x19, + 0x0a, 0x7f, 0x89, 0x39, 0x2e, 0xad, 0xa3, 0x72, 0x05, 0xb7, 0x59, 0x2a, 0x4f, 0xa5, 0xd0, 0xbf, + 0x82, 0xd6, 0x76, 0x01, 0xb3, 0x09, 0xc7, 0x0f, 0x9e, 0x3f, 0xf5, 0xda, 0x07, 0x26, 0x80, 0xf1, + 0xe2, 0x4d, 0xfc, 0xe9, 0xac, 0xad, 0x0d, 0xc7, 0xd0, 0x0d, 0x29, 0xd9, 0xbb, 0xd0, 0x4c, 0xfb, + 0x68, 0xd4, 0x8f, 0x6b, 0xdd, 0x7a, 0x75, 0xdc, 0xa0, 0x60, 0xa3, 0x92, 0x9a, 0x29, 0xea, 0xb1, + 0xfa, 0xf4, 0x65, 0xa8, 0x7f, 0x72, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x5e, 0xda, 0x4d, + 0x4d, 0x02, 0x00, 0x00, } diff --git a/proxy/freedom/config.proto b/proxy/freedom/config.proto index ec4764e4b..e90c78eba 100644 --- a/proxy/freedom/config.proto +++ b/proxy/freedom/config.proto @@ -18,6 +18,7 @@ message Config { USE_IP = 1; } DomainStrategy domain_strategy = 1; - uint32 timeout = 2; + uint32 timeout = 2 [deprecated = true]; DestinationOverride destination_override = 3; + uint32 user_level = 4; } diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 028e7c255..d38bb618d 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -4,11 +4,11 @@ package freedom import ( "context" - "time" "v2ray.com/core/app" "v2ray.com/core/app/dns" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/dice" @@ -26,6 +26,7 @@ type Handler struct { timeout uint32 dns dns.Server destOverride *DestinationOverride + policy policy.Policy } // New creates a new Freedom handler. @@ -46,6 +47,14 @@ func New(ctx context.Context, config *Config) (*Handler, error) { return newError("DNS server is not found in the space") } } + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + f.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + f.policy.Timeout.ConnectionIdle.Value = config.Timeout + } return nil }) return f, nil @@ -109,12 +118,8 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial } defer conn.Close() - timeout := time.Second * time.Duration(h.timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, timeout) + timer := signal.CancelAfterInactivity(ctx, cancel, h.policy.Timeout.ConnectionIdle.Duration()) requestDone := signal.ExecuteAsync(func() error { var writer buf.Writer @@ -126,6 +131,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to process request").Base(err) } + timer.SetTimeout(h.policy.Timeout.DownlinkOnly.Duration()) return nil }) @@ -136,6 +142,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(v2reader, output, buf.UpdateActivity(timer)); err != nil { return newError("failed to process response").Base(err) } + timer.SetTimeout(h.policy.Timeout.UplinkOnly.Duration()) return nil }) diff --git a/proxy/http/config.pb.go b/proxy/http/config.pb.go index 0b4170a5e..3986458fd 100644 --- a/proxy/http/config.pb.go +++ b/proxy/http/config.pb.go @@ -20,6 +20,7 @@ type ServerConfig struct { Timeout uint32 `protobuf:"varint,1,opt,name=timeout" json:"timeout,omitempty"` Accounts map[string]string `protobuf:"bytes,2,rep,name=accounts" json:"accounts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` AllowTransparent bool `protobuf:"varint,3,opt,name=allow_transparent,json=allowTransparent" json:"allow_transparent,omitempty"` + UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *ServerConfig) Reset() { *m = ServerConfig{} } @@ -48,6 +49,13 @@ func (m *ServerConfig) GetAllowTransparent() bool { return false } +func (m *ServerConfig) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + // ClientConfig for HTTP proxy client. type ClientConfig struct { } @@ -65,22 +73,24 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/http/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 271 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x5d, 0x4b, 0xc3, 0x30, - 0x14, 0x86, 0x49, 0xe7, 0xc7, 0x8c, 0x9b, 0xcc, 0xe0, 0xa0, 0x7a, 0x55, 0x76, 0x21, 0x05, 0x21, - 0xc5, 0x7a, 0x23, 0xee, 0x4a, 0x8b, 0xe0, 0x8d, 0x30, 0xaa, 0x78, 0xe1, 0x8d, 0xc4, 0x10, 0xb5, - 0xd8, 0xe6, 0x94, 0xb3, 0xd3, 0x6a, 0xfe, 0x92, 0xff, 0xca, 0x7f, 0x22, 0xcd, 0x9c, 0x1f, 0xb0, - 0xab, 0xe4, 0x9c, 0xf7, 0xc9, 0xc3, 0x4b, 0xf8, 0x61, 0x9b, 0xa2, 0x72, 0x52, 0x43, 0x95, 0x68, - 0x40, 0x93, 0xd4, 0x08, 0xef, 0x2e, 0x79, 0x21, 0xaa, 0x13, 0x0d, 0xf6, 0xa9, 0x78, 0x96, 0x35, - 0x02, 0x81, 0x18, 0x2f, 0x39, 0x34, 0xd2, 0x33, 0xb2, 0x63, 0x26, 0x9f, 0x8c, 0x0f, 0x6e, 0x0c, - 0xb6, 0x06, 0x33, 0x4f, 0x8b, 0x90, 0x6f, 0x52, 0x51, 0x19, 0x68, 0x28, 0x64, 0x11, 0x8b, 0x87, - 0xf9, 0x72, 0x14, 0xd7, 0xbc, 0xaf, 0xb4, 0x86, 0xc6, 0xd2, 0x3c, 0x0c, 0xa2, 0x5e, 0xbc, 0x9d, - 0x1e, 0xcb, 0x95, 0x52, 0xf9, 0x57, 0x28, 0xcf, 0xbf, 0xdf, 0x5c, 0x5a, 0x42, 0x97, 0xff, 0x28, - 0xc4, 0x11, 0xdf, 0x55, 0x65, 0x09, 0x6f, 0x0f, 0x84, 0xca, 0xce, 0x6b, 0x85, 0xc6, 0x52, 0xd8, - 0x8b, 0x58, 0xdc, 0xcf, 0x47, 0x3e, 0xb8, 0xfd, 0xdd, 0x1f, 0x4c, 0xf9, 0xf0, 0x9f, 0x47, 0x8c, - 0x78, 0xef, 0xd5, 0x38, 0x5f, 0x71, 0x2b, 0xef, 0xae, 0x62, 0x8f, 0xaf, 0xb7, 0xaa, 0x6c, 0x4c, - 0x18, 0xf8, 0xdd, 0x62, 0x38, 0x0b, 0x4e, 0xd9, 0x64, 0x87, 0x0f, 0xb2, 0xb2, 0x30, 0x96, 0x16, - 0x8d, 0x2e, 0xa6, 0x7c, 0x5f, 0x43, 0xb5, 0xba, 0xfb, 0x8c, 0xdd, 0xaf, 0x75, 0xe7, 0x47, 0x30, - 0xbe, 0x4b, 0x73, 0xe5, 0x64, 0xd6, 0xe5, 0x33, 0x9f, 0x5f, 0x11, 0xd5, 0x8f, 0x1b, 0xfe, 0x3b, - 0x4f, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x08, 0xbc, 0x0a, 0x78, 0x01, 0x00, 0x00, + // 296 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xcf, 0x4a, 0x33, 0x31, + 0x14, 0xc5, 0x99, 0x69, 0xbf, 0xcf, 0xf6, 0xda, 0x4a, 0x0d, 0x16, 0x46, 0x51, 0x28, 0x5d, 0x48, + 0x41, 0xc8, 0x60, 0xdd, 0x88, 0x5d, 0xd9, 0x22, 0xb8, 0x50, 0x28, 0x51, 0x5c, 0xb8, 0x29, 0x31, + 0x5c, 0xb5, 0x98, 0x26, 0x43, 0xe6, 0xce, 0xe8, 0xec, 0x7d, 0x1a, 0x9f, 0x52, 0x92, 0x5a, 0xff, + 0x40, 0x57, 0x49, 0x7e, 0xe7, 0xe4, 0xe4, 0x9e, 0xc0, 0x61, 0x39, 0x74, 0xb2, 0xe2, 0xca, 0x2e, + 0x52, 0x65, 0x1d, 0xa6, 0x99, 0xb3, 0x6f, 0x55, 0xfa, 0x4c, 0x94, 0xa5, 0xca, 0x9a, 0xc7, 0xf9, + 0x13, 0xcf, 0x9c, 0x25, 0xcb, 0xba, 0x2b, 0x9f, 0x43, 0x1e, 0x3c, 0xdc, 0x7b, 0xfa, 0xef, 0x31, + 0xb4, 0x6e, 0xd0, 0x95, 0xe8, 0x26, 0xc1, 0xcd, 0xf6, 0x61, 0x83, 0xe6, 0x0b, 0xb4, 0x05, 0x25, + 0x51, 0x2f, 0x1a, 0xb4, 0xc7, 0x71, 0x12, 0x89, 0x15, 0x62, 0xd7, 0xd0, 0x90, 0x4a, 0xd9, 0xc2, + 0x50, 0x9e, 0xc4, 0xbd, 0xda, 0x60, 0x73, 0x78, 0xcc, 0xd7, 0x06, 0xf3, 0xdf, 0xa1, 0xfc, 0xfc, + 0xeb, 0xce, 0x85, 0x21, 0x57, 0x89, 0xef, 0x08, 0x76, 0x04, 0xdb, 0x52, 0x6b, 0xfb, 0x3a, 0x23, + 0x27, 0x4d, 0x9e, 0x49, 0x87, 0x86, 0x92, 0x5a, 0x2f, 0x1a, 0x34, 0x44, 0x27, 0x08, 0xb7, 0x3f, + 0x9c, 0x1d, 0x00, 0x14, 0x39, 0xba, 0x99, 0xc6, 0x12, 0x75, 0x52, 0xf7, 0xc3, 0x89, 0xa6, 0x27, + 0x57, 0x1e, 0xec, 0x8d, 0xa0, 0xfd, 0xe7, 0x19, 0xd6, 0x81, 0xda, 0x0b, 0x56, 0xa1, 0x45, 0x53, + 0xf8, 0x2d, 0xdb, 0x81, 0x7f, 0xa5, 0xd4, 0x05, 0x26, 0x71, 0x60, 0xcb, 0xc3, 0x59, 0x7c, 0x1a, + 0xf5, 0xb7, 0xa0, 0x35, 0xd1, 0x73, 0x34, 0xb4, 0x1c, 0x78, 0x3c, 0x82, 0x5d, 0x65, 0x17, 0xeb, + 0xab, 0x4d, 0xa3, 0xfb, 0xba, 0x5f, 0x3f, 0xe2, 0xee, 0xdd, 0x50, 0xc8, 0x8a, 0x4f, 0xbc, 0x3e, + 0x0d, 0xfa, 0x25, 0x51, 0xf6, 0xf0, 0x3f, 0xfc, 0xf8, 0xc9, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x69, 0x94, 0x9f, 0xa7, 0x9b, 0x01, 0x00, 0x00, } diff --git a/proxy/http/config.proto b/proxy/http/config.proto index a1d014e8a..995737dd7 100644 --- a/proxy/http/config.proto +++ b/proxy/http/config.proto @@ -8,9 +8,10 @@ option java_multiple_files = true; // Config for HTTP proxy server. message ServerConfig { - uint32 timeout = 1; + uint32 timeout = 1 [deprecated = true]; map accounts = 2; bool allow_transparent = 3; + uint32 user_level = 4; } // ClientConfig for HTTP proxy client. diff --git a/proxy/http/server.go b/proxy/http/server.go index 9e6749505..e7e0b65ea 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -13,6 +13,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" @@ -24,6 +25,7 @@ import ( // Server is a HTTP proxy server. type Server struct { config *ServerConfig + policy policy.Policy } // NewServer creates a new HTTP inbound handler. @@ -35,6 +37,17 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { s := &Server{ config: config, } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + s.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return s, nil } @@ -94,7 +107,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet reader := bufio.NewReaderSize(readerOnly{conn}, buf.Size) Start: - conn.SetReadDeadline(time.Now().Add(time.Second * 16)) + conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) request, err := http.ReadRequest(reader) if err != nil { @@ -157,12 +170,8 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade return newError("failed to write back OK response").Base(err) } - timeout := time.Second * time.Duration(s.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, timeout) + timer := signal.CancelAfterInactivity(ctx, cancel, s.policy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err @@ -181,6 +190,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade requestDone := signal.ExecuteAsync(func() error { defer ray.InboundInput().Close() + defer timer.SetTimeout(s.policy.Timeout.DownlinkOnly.Duration()) v2reader := buf.NewReader(conn) return buf.Copy(v2reader, ray.InboundInput(), buf.UpdateActivity(timer)) @@ -191,7 +201,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade if err := buf.Copy(ray.InboundOutput(), v2writer, buf.UpdateActivity(timer)); err != nil { return err } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(s.policy.Timeout.UplinkOnly.Duration()) return nil }) diff --git a/proxy/shadowsocks/client.go b/proxy/shadowsocks/client.go index e93ee370a..473ecf626 100644 --- a/proxy/shadowsocks/client.go +++ b/proxy/shadowsocks/client.go @@ -2,9 +2,10 @@ package shadowsocks import ( "context" - "time" + "v2ray.com/core/app" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -18,7 +19,8 @@ import ( // Client is a inbound handler for Shadowsocks protocol type Client struct { - serverPicker protocol.ServerPicker + serverPicker protocol.ServerPicker + policyManager policy.Interface } // NewClient create a new Shadowsocks client. @@ -33,6 +35,18 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { client := &Client{ serverPicker: protocol.NewRoundRobinServerPicker(serverList), } + space := app.SpaceFromContext(ctx) + if space == nil { + return nil, newError("Space not found.") + } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + client.policyManager = pm + return nil + }) return client, nil } @@ -90,8 +104,9 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale request.Option |= RequestOptionOneTimeAuth } + sessionPolicy := v.policyManager.GetPolicy(user.Level) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, time.Minute*5) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) if request.Command == protocol.RequestCommandTCP { bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) @@ -105,11 +120,13 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale } requestDone := signal.ExecuteAsync(func() error { + defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return buf.Copy(outboundRay.OutboundInput(), bodyWriter, buf.UpdateActivity(timer)) }) responseDone := signal.ExecuteAsync(func() error { defer outboundRay.OutboundOutput().Close() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) responseReader, err := ReadTCPResponse(user, conn) if err != nil { diff --git a/proxy/shadowsocks/config.proto b/proxy/shadowsocks/config.proto index fbc2c912e..4323ef046 100644 --- a/proxy/shadowsocks/config.proto +++ b/proxy/shadowsocks/config.proto @@ -38,4 +38,4 @@ message ServerConfig { message ClientConfig { repeated v2ray.core.common.protocol.ServerEndpoint server = 1; -} \ No newline at end of file +} diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index 9feeb3378..f2d409449 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -7,6 +7,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -18,9 +19,10 @@ import ( ) type Server struct { - config *ServerConfig - user *protocol.User - account *ShadowsocksAccount + config *ServerConfig + user *protocol.User + account *ShadowsocksAccount + policyManager policy.Interface } // NewServer create a new Shadowsocks server. @@ -45,6 +47,15 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { account: account, } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policyManager = pm + return nil + }) + return s, nil } @@ -128,7 +139,8 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection } func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - conn.SetReadDeadline(time.Now().Add(time.Second * 8)) + sessionPolicy := s.policyManager.GetPolicy(s.user.Level) + conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())) bufferedReader := buf.NewBufferedReader(buf.NewReader(conn)) request, bodyReader, err := ReadTCPSession(s.user, bufferedReader) if err != nil { @@ -145,9 +157,8 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, ctx = protocol.ContextWithUser(ctx, request.User) - userSettings := s.user.GetSettings() ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, userSettings.PayloadTimeout) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err @@ -177,7 +188,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) return nil }) @@ -188,6 +199,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, if err := buf.Copy(bodyReader, ray.InboundInput(), buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } + timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return nil }) diff --git a/proxy/socks/config.pb.go b/proxy/socks/config.pb.go index 74942bdc5..3b664de9b 100644 --- a/proxy/socks/config.pb.go +++ b/proxy/socks/config.pb.go @@ -68,6 +68,7 @@ type ServerConfig struct { Address *v2ray_core_common_net.IPOrDomain `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` UdpEnabled bool `protobuf:"varint,4,opt,name=udp_enabled,json=udpEnabled" json:"udp_enabled,omitempty"` Timeout uint32 `protobuf:"varint,5,opt,name=timeout" json:"timeout,omitempty"` + UserLevel uint32 `protobuf:"varint,6,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *ServerConfig) Reset() { *m = ServerConfig{} } @@ -110,6 +111,13 @@ func (m *ServerConfig) GetTimeout() uint32 { return 0 } +func (m *ServerConfig) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + type ClientConfig struct { Server []*v2ray_core_common_protocol1.ServerEndpoint `protobuf:"bytes,1,rep,name=server" json:"server,omitempty"` } @@ -136,34 +144,35 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/socks/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 449 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xd1, 0x6e, 0xd3, 0x3e, - 0x14, 0xc6, 0xff, 0x49, 0xff, 0x5d, 0xb3, 0xd3, 0x0e, 0x55, 0x16, 0x9a, 0xa2, 0xdc, 0x10, 0x2a, - 0x21, 0xa2, 0x5d, 0x38, 0x28, 0xdc, 0x20, 0x26, 0x90, 0xb2, 0xae, 0x12, 0xdc, 0xac, 0x95, 0x3b, - 0x40, 0xe2, 0xa6, 0xf2, 0x1c, 0xc3, 0xa2, 0x35, 0x76, 0x64, 0x3b, 0x85, 0xbc, 0x12, 0x8f, 0xc3, - 0x13, 0xa1, 0xda, 0xc9, 0x34, 0x50, 0x77, 0x77, 0x4e, 0xce, 0x77, 0xbe, 0x9c, 0xef, 0x67, 0x78, - 0xb9, 0xcb, 0x14, 0x6d, 0x31, 0x93, 0x55, 0xca, 0xa4, 0xe2, 0x69, 0xad, 0xe4, 0xcf, 0x36, 0xd5, - 0x92, 0xdd, 0xe9, 0x94, 0x49, 0xf1, 0xad, 0xfc, 0x8e, 0x6b, 0x25, 0x8d, 0x44, 0xa7, 0xbd, 0x50, - 0x71, 0x6c, 0x45, 0xd8, 0x8a, 0xa2, 0x7f, 0x0d, 0x98, 0xac, 0x2a, 0x29, 0x52, 0xc1, 0x4d, 0x4a, - 0x8b, 0x42, 0x71, 0xad, 0x9d, 0x41, 0xf4, 0xea, 0xb0, 0xd0, 0x0e, 0x99, 0xdc, 0xa6, 0x9a, 0xab, - 0x1d, 0x57, 0x1b, 0x5d, 0x73, 0xe6, 0x36, 0x66, 0x39, 0x8c, 0x72, 0xc6, 0x64, 0x23, 0x0c, 0x8a, - 0x20, 0x68, 0x34, 0x57, 0x82, 0x56, 0x3c, 0xf4, 0x62, 0x2f, 0x39, 0x26, 0xf7, 0xfd, 0x7e, 0x56, - 0x53, 0xad, 0x7f, 0x48, 0x55, 0x84, 0xbe, 0x9b, 0xf5, 0xfd, 0xec, 0xb7, 0x0f, 0x93, 0xb5, 0x35, - 0x9e, 0xdb, 0x30, 0xe8, 0x1d, 0x1c, 0xd3, 0xc6, 0xdc, 0x6e, 0x4c, 0x5b, 0x3b, 0xa7, 0x27, 0x59, - 0x8c, 0x0f, 0x47, 0xc3, 0x79, 0x63, 0x6e, 0xaf, 0xdb, 0x9a, 0x93, 0x80, 0x76, 0x15, 0xba, 0x82, - 0x80, 0xba, 0x93, 0x74, 0xe8, 0xc7, 0x83, 0x64, 0x9c, 0x65, 0x8f, 0x6d, 0x3f, 0xfc, 0x2d, 0xee, - 0x72, 0xe8, 0x85, 0x30, 0xaa, 0x25, 0xf7, 0x1e, 0xe8, 0x1c, 0x46, 0x1d, 0xa5, 0x70, 0x10, 0x7b, - 0xc9, 0x38, 0x7b, 0xfe, 0xd0, 0xce, 0x21, 0xc2, 0x82, 0x1b, 0xfc, 0x71, 0xb5, 0x54, 0x97, 0xb2, - 0xa2, 0xa5, 0x20, 0xfd, 0x06, 0x7a, 0x06, 0xe3, 0xa6, 0xa8, 0x37, 0x5c, 0xd0, 0x9b, 0x2d, 0x2f, - 0xc2, 0xff, 0x63, 0x2f, 0x09, 0x08, 0x34, 0x45, 0xbd, 0x70, 0x5f, 0x50, 0x08, 0x23, 0x53, 0x56, - 0x5c, 0x36, 0x26, 0x1c, 0xc6, 0x5e, 0x72, 0x42, 0xfa, 0x36, 0x3a, 0x87, 0x93, 0xbf, 0x4e, 0x42, - 0x53, 0x18, 0xdc, 0xf1, 0xb6, 0x63, 0xbb, 0x2f, 0xd1, 0x53, 0x18, 0xee, 0xe8, 0xb6, 0xe1, 0x1d, - 0x53, 0xd7, 0xbc, 0xf5, 0xdf, 0x78, 0x33, 0x02, 0x93, 0xf9, 0xb6, 0xe4, 0xc2, 0x74, 0x4c, 0x2f, - 0xe0, 0xc8, 0x3d, 0x5e, 0xe8, 0x59, 0x24, 0x67, 0x07, 0x32, 0xf4, 0xcf, 0xdc, 0x61, 0x59, 0x88, - 0xa2, 0x96, 0xa5, 0x30, 0xa4, 0xdb, 0x3c, 0x7b, 0x01, 0x41, 0x8f, 0x1b, 0x8d, 0x61, 0x74, 0xb5, - 0xdc, 0xe4, 0x9f, 0xae, 0x3f, 0x4c, 0xff, 0x43, 0x13, 0x08, 0x56, 0xf9, 0x7a, 0xfd, 0x65, 0x49, - 0x2e, 0xa7, 0xde, 0xc5, 0x7b, 0x88, 0x98, 0xac, 0x1e, 0x41, 0xbe, 0xf2, 0xbe, 0x0e, 0x6d, 0xf1, - 0xcb, 0x3f, 0xfd, 0x9c, 0x11, 0xda, 0xe2, 0xf9, 0x5e, 0xb1, 0xb2, 0x8a, 0xf5, 0x7e, 0x70, 0x73, - 0x64, 0xef, 0x78, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x57, 0x01, 0x54, 0x95, 0xf7, 0x02, 0x00, - 0x00, + // 470 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x5d, 0x8b, 0xd3, 0x40, + 0x14, 0x75, 0xb2, 0xb6, 0x4d, 0x6f, 0xbb, 0x52, 0x06, 0x59, 0x42, 0x51, 0x8c, 0x05, 0xb1, 0xec, + 0xc3, 0x44, 0xe2, 0x8b, 0xb8, 0x28, 0xb4, 0xdd, 0x82, 0x82, 0x6c, 0xcb, 0x74, 0x55, 0xf0, 0x25, + 0xcc, 0x4e, 0x46, 0x37, 0x6c, 0x32, 0x13, 0x66, 0x26, 0xd5, 0xfc, 0x25, 0xff, 0x9f, 0xef, 0x92, + 0xaf, 0x65, 0x95, 0xee, 0xdb, 0xfd, 0x38, 0xf7, 0xcc, 0x3d, 0xe7, 0x0e, 0xbc, 0xdc, 0x87, 0x9a, + 0x95, 0x84, 0xab, 0x2c, 0xe0, 0x4a, 0x8b, 0x20, 0xd7, 0xea, 0x57, 0x19, 0x18, 0xc5, 0x6f, 0x4c, + 0xc0, 0x95, 0xfc, 0x9e, 0xfc, 0x20, 0xb9, 0x56, 0x56, 0xe1, 0x93, 0x0e, 0xa8, 0x05, 0xa9, 0x41, + 0xa4, 0x06, 0x4d, 0xff, 0x27, 0xe0, 0x2a, 0xcb, 0x94, 0x0c, 0xa4, 0xb0, 0x01, 0x8b, 0x63, 0x2d, + 0x8c, 0x69, 0x08, 0xa6, 0xaf, 0x0e, 0x03, 0xeb, 0x26, 0x57, 0x69, 0x60, 0x84, 0xde, 0x0b, 0x1d, + 0x99, 0x5c, 0xf0, 0x66, 0x62, 0xb6, 0x80, 0xc1, 0x82, 0x73, 0x55, 0x48, 0x8b, 0xa7, 0xe0, 0x16, + 0x46, 0x68, 0xc9, 0x32, 0xe1, 0x21, 0x1f, 0xcd, 0x87, 0xf4, 0x36, 0xaf, 0x7a, 0x39, 0x33, 0xe6, + 0xa7, 0xd2, 0xb1, 0xe7, 0x34, 0xbd, 0x2e, 0x9f, 0xfd, 0x71, 0x60, 0xbc, 0xab, 0x89, 0x57, 0xb5, + 0x18, 0xfc, 0x0e, 0x86, 0xac, 0xb0, 0xd7, 0x91, 0x2d, 0xf3, 0x86, 0xe9, 0x51, 0xe8, 0x93, 0xc3, + 0xd2, 0xc8, 0xa2, 0xb0, 0xd7, 0x97, 0x65, 0x2e, 0xa8, 0xcb, 0xda, 0x08, 0x5f, 0x80, 0xcb, 0x9a, + 0x95, 0x8c, 0xe7, 0xf8, 0x47, 0xf3, 0x51, 0x18, 0xde, 0x37, 0x7d, 0xf7, 0x59, 0xd2, 0xea, 0x30, + 0x6b, 0x69, 0x75, 0x49, 0x6f, 0x39, 0xf0, 0x19, 0x0c, 0x5a, 0x97, 0xbc, 0x23, 0x1f, 0xcd, 0x47, + 0xe1, 0xf3, 0xbb, 0x74, 0x8d, 0x45, 0x44, 0x0a, 0x4b, 0x3e, 0x6e, 0x37, 0xfa, 0x5c, 0x65, 0x2c, + 0x91, 0xb4, 0x9b, 0xc0, 0xcf, 0x60, 0x54, 0xc4, 0x79, 0x24, 0x24, 0xbb, 0x4a, 0x45, 0xec, 0x3d, + 0xf4, 0xd1, 0xdc, 0xa5, 0x50, 0xc4, 0xf9, 0xba, 0xa9, 0xe0, 0x27, 0x30, 0xb0, 0x49, 0x26, 0x54, + 0x61, 0xbd, 0x9e, 0x8f, 0xe6, 0xc7, 0x4b, 0xc7, 0x43, 0xb4, 0x2b, 0xe1, 0xa7, 0x00, 0x95, 0x87, + 0x51, 0x2a, 0xf6, 0x22, 0xf5, 0xfa, 0x15, 0x80, 0x0e, 0xab, 0xca, 0xa7, 0xaa, 0x30, 0x3d, 0x83, + 0xe3, 0x7f, 0xb6, 0xc6, 0x13, 0x38, 0xba, 0x11, 0x65, 0x6b, 0x7f, 0x15, 0xe2, 0xc7, 0xd0, 0xdb, + 0xb3, 0xb4, 0x10, 0xad, 0xed, 0x4d, 0xf2, 0xd6, 0x79, 0x83, 0x66, 0x14, 0xc6, 0xab, 0x34, 0x11, + 0xd2, 0xb6, 0xb6, 0x2f, 0xa1, 0xdf, 0xdc, 0xd7, 0x43, 0xb5, 0x6b, 0xa7, 0x07, 0x64, 0x76, 0x3f, + 0xa1, 0x75, 0x6e, 0x2d, 0xe3, 0x5c, 0x25, 0xd2, 0xd2, 0x76, 0xf2, 0xf4, 0x05, 0xb8, 0xdd, 0x45, + 0xf0, 0x08, 0x06, 0x17, 0x9b, 0x68, 0xf1, 0xf9, 0xf2, 0xc3, 0xe4, 0x01, 0x1e, 0x83, 0xbb, 0x5d, + 0xec, 0x76, 0x5f, 0x37, 0xf4, 0x7c, 0x82, 0x96, 0xef, 0x61, 0xca, 0x55, 0x76, 0xcf, 0x55, 0xb6, + 0xe8, 0x5b, 0xaf, 0x0e, 0x7e, 0x3b, 0x27, 0x5f, 0x42, 0xca, 0x4a, 0xb2, 0xaa, 0x10, 0xdb, 0x1a, + 0xb1, 0xab, 0x1a, 0x57, 0xfd, 0x7a, 0x8f, 0xd7, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x23, 0xac, + 0x72, 0x71, 0x1a, 0x03, 0x00, 0x00, } diff --git a/proxy/socks/config.proto b/proxy/socks/config.proto index f6121c5e5..0d69862b4 100644 --- a/proxy/socks/config.proto +++ b/proxy/socks/config.proto @@ -24,9 +24,10 @@ message ServerConfig { map accounts = 2; v2ray.core.common.net.IPOrDomain address = 3; bool udp_enabled = 4; - uint32 timeout = 5; + uint32 timeout = 5 [deprecated = true]; + uint32 user_level = 6; } message ClientConfig { repeated v2ray.core.common.protocol.ServerEndpoint server = 1; -} \ No newline at end of file +} diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 95debeb70..de45358e3 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -8,6 +8,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -21,6 +22,7 @@ import ( // Server is a SOCKS 5 proxy server type Server struct { config *ServerConfig + policy policy.Policy } // NewServer creates a new Server object. @@ -32,6 +34,17 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { s := &Server{ config: config, } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + s.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return s, nil } @@ -57,7 +70,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet } func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - conn.SetReadDeadline(time.Now().Add(time.Second * 8)) + conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) reader := buf.NewBufferedReader(buf.NewReader(conn)) inboundDest, ok := proxy.InboundEntryPointFromContext(ctx) @@ -103,12 +116,8 @@ func (*Server) handleUDP(c net.Conn) error { } func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { - timeout := time.Second * time.Duration(v.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, timeout) + timer := signal.CancelAfterInactivity(ctx, cancel, v.policy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -125,6 +134,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(v2reader, input, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } + timer.SetTimeout(v.policy.Timeout.DownlinkOnly.Duration()) return nil }) @@ -133,7 +143,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(output, v2writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(v.policy.Timeout.UplinkOnly.Duration()) return nil }) diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 847ce5498..731ba440d 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -11,6 +11,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" "v2ray.com/core/common/buf" @@ -78,6 +79,7 @@ type Handler struct { usersByEmail *userByEmail detours *DetourConfig sessionHistory *encoding.SessionHistory + policyManager policy.Interface } // New creates a new VMess inbound handler. @@ -104,7 +106,11 @@ func New(ctx context.Context, config *Config) (*Handler, error) { space.OnInitialize(func() error { handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space) if handler.inboundHandlerManager == nil { - return newError("InboundHandlerManager is not found is space") + return newError("InboundHandlerManager is not found is space.") + } + handler.policyManager = policy.PolicyFromSpace(space) + if handler.policyManager == nil { + return newError("Policy is not found in space.") } return nil }) @@ -174,7 +180,8 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess // Process implements proxy.Inbound.Process(). func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher dispatcher.Interface) error { - if err := connection.SetReadDeadline(time.Now().Add(time.Second * 8)); err != nil { + sessionPolicy := h.policyManager.GetPolicy(0) + if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())); err != nil { return newError("unable to set read deadline").Base(err).AtWarning() } @@ -203,11 +210,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i log.Trace(newError("unable to set back read deadline").Base(err)) } - userSettings := request.User.GetSettings() + sessionPolicy = h.policyManager.GetPolicy(request.User.Level) ctx = protocol.ContextWithUser(ctx, request.User) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, userSettings.PayloadTimeout) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, request.Destination()) if err != nil { return newError("failed to dispatch request to ", request.Destination()).Base(err) @@ -217,12 +224,14 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i output := ray.InboundOutput() requestDone := signal.ExecuteAsync(func() error { + defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return transferRequest(timer, session, request, reader, input) }) responseDone := signal.ExecuteAsync(func() error { writer := buf.NewBufferedWriter(buf.NewWriter(connection)) defer writer.Flush() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) response := &protocol.ResponseHeader{ Command: h.generateCommand(ctx, request), diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index c2d7fb7e9..a1a0287bb 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -8,6 +8,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -23,8 +24,9 @@ import ( // Handler is an outbound connection handler for VMess protocol. type Handler struct { - serverList *protocol.ServerList - serverPicker protocol.ServerPicker + serverList *protocol.ServerList + serverPicker protocol.ServerPicker + policyManager policy.Interface } func New(ctx context.Context, config *Config) (*Handler, error) { @@ -42,6 +44,15 @@ func New(ctx context.Context, config *Config) (*Handler, error) { serverPicker: protocol.NewRoundRobinServerPicker(serverList), } + space.OnInitialize(func() error { + pm := policy.PolicyFromSpace(space) + if pm == nil { + return newError("Policy is not found in space.") + } + handler.policyManager = pm + return nil + }) + return handler, nil } @@ -102,9 +113,10 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial output := outboundRay.OutboundOutput() session := encoding.NewClientSession(protocol.DefaultIDHash) + sessionPolicy := v.policyManager.GetPolicy(request.User.Level) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, time.Minute*5) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) requestDone := signal.ExecuteAsync(func() error { writer := buf.NewBufferedWriter(buf.NewWriter(conn)) @@ -137,11 +149,13 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial return err } } + timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return nil }) responseDone := signal.ExecuteAsync(func() error { defer output.Close() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) reader := buf.NewBufferedReader(buf.NewReader(conn)) header, err := session.DecodeResponseHeader(reader) diff --git a/v2ray.go b/v2ray.go index 06baa2e51..1107e3b8c 100644 --- a/v2ray.go +++ b/v2ray.go @@ -7,6 +7,7 @@ import ( "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dns" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" "v2ray.com/core/common/net" @@ -115,7 +116,24 @@ func newSimpleServer(config *Config) (*simpleServer, error) { return nil, err } common.Must(space.AddApplication(d)) - // disp = d.(dispatcher.Interface) + } + + if p := policy.PolicyFromSpace(space); p == nil { + p, err := app.CreateAppFromConfig(ctx, &policy.Config{ + Level: map[uint32]*policy.Policy{ + 1: &policy.Policy{ + Timeout: &policy.Policy_Timeout{ + ConnectionIdle: &policy.Second{ + Value: 600, + }, + }, + }, + }, + }) + if err != nil { + return nil, err + } + common.Must(space.AddApplication(p)) } for _, inbound := range config.Inbound {