From fe57507fd98773319f7163f67e132f6846893b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=90=B2=93=F0=90=B3=9B=F0=90=B3=AA=F0=90=B3=82?= =?UTF-8?q?=F0=90=B3=90=20=F0=90=B2=80=F0=90=B3=A2=F0=90=B3=A6=F0=90=B3=AB?= =?UTF-8?q?=F0=90=B3=A2=20=F0=90=B2=A5=F0=90=B3=94=F0=90=B3=9B=F0=90=B3=AA?= =?UTF-8?q?=F0=90=B3=8C=F0=90=B3=91=F0=90=B3=96=F0=90=B3=87?= <26771058+KobeArthurScofield@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:31:27 +0800 Subject: [PATCH] Outbound: One endpoint and at most one user only (#5144) https://github.com/XTLS/Xray-core/pull/5124#issuecomment-3281091009 Fixes https://github.com/XTLS/Xray-core/pull/5124#pullrequestreview-3218097421 --- app/proxyman/config.go | 22 -- app/proxyman/config.pb.go | 543 +++++++------------------- app/proxyman/config.proto | 36 +- app/proxyman/inbound/always.go | 15 +- app/proxyman/inbound/dynamic.go | 222 ----------- app/proxyman/inbound/inbound.go | 10 +- common/protocol/headers.go | 9 - common/protocol/server_picker.go | 89 ----- common/protocol/server_picker_test.go | 71 ---- common/protocol/server_spec.go | 112 +----- common/protocol/server_spec.pb.go | 6 +- common/protocol/server_spec.proto | 2 +- common/protocol/server_spec_test.go | 79 ---- core/xray_test.go | 18 +- features/inbound/inbound.go | 4 - infra/conf/http.go | 19 +- infra/conf/shadowsocks.go | 42 +- infra/conf/socks.go | 19 +- infra/conf/socks_test.go | 56 ++- infra/conf/trojan.go | 42 +- infra/conf/vless.go | 16 +- infra/conf/vless_test.go | 60 ++- infra/conf/vmess.go | 36 +- infra/conf/vmess_test.go | 73 ++-- infra/conf/xray.go | 60 --- infra/conf/xray_test.go | 10 - proxy/http/client.go | 26 +- proxy/http/config.pb.go | 8 +- proxy/http/config.proto | 2 +- proxy/shadowsocks/client.go | 29 +- proxy/shadowsocks/config.pb.go | 6 +- proxy/shadowsocks/config.proto | 2 +- proxy/socks/client.go | 27 +- proxy/socks/config.pb.go | 6 +- proxy/socks/config.proto | 2 +- proxy/trojan/client.go | 27 +- proxy/trojan/config.pb.go | 6 +- proxy/trojan/config.proto | 2 +- proxy/vless/outbound/config.pb.go | 6 +- proxy/vless/outbound/config.proto | 2 +- proxy/vless/outbound/outbound.go | 31 +- proxy/vmess/encoding/commands.go | 72 ---- proxy/vmess/encoding/commands_test.go | 55 --- proxy/vmess/inbound/config.pb.go | 54 +-- proxy/vmess/inbound/config.proto | 2 - proxy/vmess/inbound/inbound.go | 34 +- proxy/vmess/outbound/command.go | 31 +- proxy/vmess/outbound/config.pb.go | 6 +- proxy/vmess/outbound/config.proto | 2 +- proxy/vmess/outbound/outbound.go | 31 +- testing/scenarios/command_test.go | 44 +-- testing/scenarios/dokodemo_test.go | 36 +- testing/scenarios/feature_test.go | 94 ++--- testing/scenarios/policy_test.go | 44 +-- testing/scenarios/reverse_test.go | 44 +-- testing/scenarios/shadowsocks_test.go | 70 ++-- testing/scenarios/socks_test.go | 68 ++-- testing/scenarios/tls_test.go | 180 ++++----- testing/scenarios/transport_test.go | 18 +- testing/scenarios/vless_test.go | 76 ++-- testing/scenarios/vmess_test.go | 409 ++++++------------- 61 files changed, 829 insertions(+), 2394 deletions(-) delete mode 100644 app/proxyman/inbound/dynamic.go delete mode 100644 common/protocol/server_picker.go delete mode 100644 common/protocol/server_picker_test.go delete mode 100644 common/protocol/server_spec_test.go delete mode 100644 proxy/vmess/encoding/commands_test.go diff --git a/app/proxyman/config.go b/app/proxyman/config.go index 76d7a194..871971aa 100644 --- a/app/proxyman/config.go +++ b/app/proxyman/config.go @@ -1,23 +1 @@ package proxyman - -func (s *AllocationStrategy) GetConcurrencyValue() uint32 { - if s == nil || s.Concurrency == nil { - return 3 - } - return s.Concurrency.Value -} - -func (s *AllocationStrategy) GetRefreshValue() uint32 { - if s == nil || s.Refresh == nil { - return 5 - } - return s.Refresh.Value -} - -func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig { - if c.SniffingSettings != nil { - return c.SniffingSettings - } - - return nil -} diff --git a/app/proxyman/config.pb.go b/app/proxyman/config.pb.go index 9713521b..0a0f7625 100644 --- a/app/proxyman/config.pb.go +++ b/app/proxyman/config.pb.go @@ -23,58 +23,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type AllocationStrategy_Type int32 - -const ( - // Always allocate all connection handlers. - AllocationStrategy_Always AllocationStrategy_Type = 0 - // Randomly allocate specific range of handlers. - AllocationStrategy_Random AllocationStrategy_Type = 1 - // External. Not supported yet. - AllocationStrategy_External AllocationStrategy_Type = 2 -) - -// Enum value maps for AllocationStrategy_Type. -var ( - AllocationStrategy_Type_name = map[int32]string{ - 0: "Always", - 1: "Random", - 2: "External", - } - AllocationStrategy_Type_value = map[string]int32{ - "Always": 0, - "Random": 1, - "External": 2, - } -) - -func (x AllocationStrategy_Type) Enum() *AllocationStrategy_Type { - p := new(AllocationStrategy_Type) - *p = x - return p -} - -func (x AllocationStrategy_Type) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor { - return file_app_proxyman_config_proto_enumTypes[0].Descriptor() -} - -func (AllocationStrategy_Type) Type() protoreflect.EnumType { - return &file_app_proxyman_config_proto_enumTypes[0] -} - -func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use AllocationStrategy_Type.Descriptor instead. -func (AllocationStrategy_Type) EnumDescriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0} -} - type InboundConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -111,71 +59,6 @@ func (*InboundConfig) Descriptor() ([]byte, []int) { return file_app_proxyman_config_proto_rawDescGZIP(), []int{0} } -type AllocationStrategy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type AllocationStrategy_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.proxyman.AllocationStrategy_Type" json:"type,omitempty"` - // Number of handlers (ports) running in parallel. - // Default value is 3 if unset. - Concurrency *AllocationStrategy_AllocationStrategyConcurrency `protobuf:"bytes,2,opt,name=concurrency,proto3" json:"concurrency,omitempty"` - // Number of minutes before a handler is regenerated. - // Default value is 5 if unset. - Refresh *AllocationStrategy_AllocationStrategyRefresh `protobuf:"bytes,3,opt,name=refresh,proto3" json:"refresh,omitempty"` -} - -func (x *AllocationStrategy) Reset() { - *x = AllocationStrategy{} - mi := &file_app_proxyman_config_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AllocationStrategy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AllocationStrategy) ProtoMessage() {} - -func (x *AllocationStrategy) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AllocationStrategy.ProtoReflect.Descriptor instead. -func (*AllocationStrategy) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{1} -} - -func (x *AllocationStrategy) GetType() AllocationStrategy_Type { - if x != nil { - return x.Type - } - return AllocationStrategy_Always -} - -func (x *AllocationStrategy) GetConcurrency() *AllocationStrategy_AllocationStrategyConcurrency { - if x != nil { - return x.Concurrency - } - return nil -} - -func (x *AllocationStrategy) GetRefresh() *AllocationStrategy_AllocationStrategyRefresh { - if x != nil { - return x.Refresh - } - return nil -} - type SniffingConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -196,7 +79,7 @@ type SniffingConfig struct { func (x *SniffingConfig) Reset() { *x = SniffingConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[2] + mi := &file_app_proxyman_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -208,7 +91,7 @@ func (x *SniffingConfig) String() string { func (*SniffingConfig) ProtoMessage() {} func (x *SniffingConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[2] + mi := &file_app_proxyman_config_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -221,7 +104,7 @@ func (x *SniffingConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use SniffingConfig.ProtoReflect.Descriptor instead. func (*SniffingConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{2} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{1} } func (x *SniffingConfig) GetEnabled() bool { @@ -268,15 +151,14 @@ type ReceiverConfig struct { PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"` // Listen specifies the IP address that the Receiver should listen on. Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"` - AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"` - StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"` - ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"` - SniffingSettings *SniffingConfig `protobuf:"bytes,7,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"` + StreamSettings *internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"` + ReceiveOriginalDestination bool `protobuf:"varint,4,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"` + SniffingSettings *SniffingConfig `protobuf:"bytes,6,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"` } func (x *ReceiverConfig) Reset() { *x = ReceiverConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[3] + mi := &file_app_proxyman_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -288,7 +170,7 @@ func (x *ReceiverConfig) String() string { func (*ReceiverConfig) ProtoMessage() {} func (x *ReceiverConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[3] + mi := &file_app_proxyman_config_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -301,7 +183,7 @@ func (x *ReceiverConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ReceiverConfig.ProtoReflect.Descriptor instead. func (*ReceiverConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{3} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{2} } func (x *ReceiverConfig) GetPortList() *net.PortList { @@ -318,13 +200,6 @@ func (x *ReceiverConfig) GetListen() *net.IPOrDomain { return nil } -func (x *ReceiverConfig) GetAllocationStrategy() *AllocationStrategy { - if x != nil { - return x.AllocationStrategy - } - return nil -} - func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig { if x != nil { return x.StreamSettings @@ -358,7 +233,7 @@ type InboundHandlerConfig struct { func (x *InboundHandlerConfig) Reset() { *x = InboundHandlerConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[4] + mi := &file_app_proxyman_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -370,7 +245,7 @@ func (x *InboundHandlerConfig) String() string { func (*InboundHandlerConfig) ProtoMessage() {} func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[4] + mi := &file_app_proxyman_config_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -383,7 +258,7 @@ func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use InboundHandlerConfig.ProtoReflect.Descriptor instead. func (*InboundHandlerConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{4} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{3} } func (x *InboundHandlerConfig) GetTag() string { @@ -415,7 +290,7 @@ type OutboundConfig struct { func (x *OutboundConfig) Reset() { *x = OutboundConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[5] + mi := &file_app_proxyman_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -427,7 +302,7 @@ func (x *OutboundConfig) String() string { func (*OutboundConfig) ProtoMessage() {} func (x *OutboundConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[5] + mi := &file_app_proxyman_config_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -440,7 +315,7 @@ func (x *OutboundConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use OutboundConfig.ProtoReflect.Descriptor instead. func (*OutboundConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{5} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{4} } type SenderConfig struct { @@ -459,7 +334,7 @@ type SenderConfig struct { func (x *SenderConfig) Reset() { *x = SenderConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[6] + mi := &file_app_proxyman_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -471,7 +346,7 @@ func (x *SenderConfig) String() string { func (*SenderConfig) ProtoMessage() {} func (x *SenderConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[6] + mi := &file_app_proxyman_config_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -484,7 +359,7 @@ func (x *SenderConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use SenderConfig.ProtoReflect.Descriptor instead. func (*SenderConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{6} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{5} } func (x *SenderConfig) GetVia() *net.IPOrDomain { @@ -546,7 +421,7 @@ type MultiplexingConfig struct { func (x *MultiplexingConfig) Reset() { *x = MultiplexingConfig{} - mi := &file_app_proxyman_config_proto_msgTypes[7] + mi := &file_app_proxyman_config_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -558,7 +433,7 @@ func (x *MultiplexingConfig) String() string { func (*MultiplexingConfig) ProtoMessage() {} func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[7] + mi := &file_app_proxyman_config_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -571,7 +446,7 @@ func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MultiplexingConfig.ProtoReflect.Descriptor instead. func (*MultiplexingConfig) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{7} + return file_app_proxyman_config_proto_rawDescGZIP(), []int{6} } func (x *MultiplexingConfig) GetEnabled() bool { @@ -602,96 +477,6 @@ func (x *MultiplexingConfig) GetXudpProxyUDP443() string { return "" } -type AllocationStrategy_AllocationStrategyConcurrency struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() { - *x = AllocationStrategy_AllocationStrategyConcurrency{} - mi := &file_app_proxyman_config_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AllocationStrategy_AllocationStrategyConcurrency) ProtoMessage() {} - -func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AllocationStrategy_AllocationStrategyConcurrency.ProtoReflect.Descriptor instead. -func (*AllocationStrategy_AllocationStrategyConcurrency) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *AllocationStrategy_AllocationStrategyConcurrency) GetValue() uint32 { - if x != nil { - return x.Value - } - return 0 -} - -type AllocationStrategy_AllocationStrategyRefresh struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() { - *x = AllocationStrategy_AllocationStrategyRefresh{} - mi := &file_app_proxyman_config_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AllocationStrategy_AllocationStrategyRefresh) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AllocationStrategy_AllocationStrategyRefresh) ProtoMessage() {} - -func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_config_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AllocationStrategy_AllocationStrategyRefresh.ProtoReflect.Descriptor instead. -func (*AllocationStrategy_AllocationStrategyRefresh) Descriptor() ([]byte, []int) { - return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 1} -} - -func (x *AllocationStrategy_AllocationStrategyRefresh) GetValue() uint32 { - if x != nil { - return x.Value - } - return 0 -} - var File_app_proxyman_config_proto protoreflect.FileDescriptor var file_app_proxyman_config_proto_rawDesc = []byte{ @@ -706,130 +491,98 @@ var file_app_proxyman_config_proto_rawDesc = []byte{ 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63, - 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a, - 0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, - 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52, - 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, - 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, - 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, - 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xbd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, - 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, - 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, - 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, - 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, - 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, - 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, - 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, - 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, - 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, - 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, - 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, - 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x9d, 0x03, 0x0a, 0x0c, 0x53, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, - 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, + 0x6e, 0x66, 0x69, 0x67, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x6e, + 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4f, + 0x6e, 0x6c, 0x79, 0x22, 0xe5, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, + 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, + 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, + 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, + 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, + 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xc0, 0x01, 0x0a, 0x14, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, + 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, + 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x22, 0x9d, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, + 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, + 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, + 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, - 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, - 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50, + 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, + 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, - 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, - 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, + 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, + 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, + 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, + 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, + 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -844,48 +597,39 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte { return file_app_proxyman_config_proto_rawDescData } -var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_app_proxyman_config_proto_goTypes = []any{ - (AllocationStrategy_Type)(0), // 0: xray.app.proxyman.AllocationStrategy.Type - (*InboundConfig)(nil), // 1: xray.app.proxyman.InboundConfig - (*AllocationStrategy)(nil), // 2: xray.app.proxyman.AllocationStrategy - (*SniffingConfig)(nil), // 3: xray.app.proxyman.SniffingConfig - (*ReceiverConfig)(nil), // 4: xray.app.proxyman.ReceiverConfig - (*InboundHandlerConfig)(nil), // 5: xray.app.proxyman.InboundHandlerConfig - (*OutboundConfig)(nil), // 6: xray.app.proxyman.OutboundConfig - (*SenderConfig)(nil), // 7: xray.app.proxyman.SenderConfig - (*MultiplexingConfig)(nil), // 8: xray.app.proxyman.MultiplexingConfig - (*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 9: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency - (*AllocationStrategy_AllocationStrategyRefresh)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh - (*net.PortList)(nil), // 11: xray.common.net.PortList - (*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain - (*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig - (*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage - (*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig - (internet.DomainStrategy)(0), // 16: xray.transport.internet.DomainStrategy + (*InboundConfig)(nil), // 0: xray.app.proxyman.InboundConfig + (*SniffingConfig)(nil), // 1: xray.app.proxyman.SniffingConfig + (*ReceiverConfig)(nil), // 2: xray.app.proxyman.ReceiverConfig + (*InboundHandlerConfig)(nil), // 3: xray.app.proxyman.InboundHandlerConfig + (*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig + (*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig + (*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig + (*net.PortList)(nil), // 7: xray.common.net.PortList + (*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain + (*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig + (*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage + (*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig + (internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy } var file_app_proxyman_config_proto_depIdxs = []int32{ - 0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type - 9, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency - 10, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh - 11, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList - 12, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain - 2, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy - 13, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig - 3, // 7: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig - 14, // 8: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage - 14, // 9: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage - 12, // 10: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain - 13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig - 15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig - 8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig - 16, // 14: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList + 8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain + 9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig + 10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage + 10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage + 8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain + 9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig + 6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig + 12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_app_proxyman_config_proto_init() } @@ -898,14 +642,13 @@ func file_app_proxyman_config_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_app_proxyman_config_proto_rawDesc, - NumEnums: 1, - NumMessages: 10, + NumEnums: 0, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, GoTypes: file_app_proxyman_config_proto_goTypes, DependencyIndexes: file_app_proxyman_config_proto_depIdxs, - EnumInfos: file_app_proxyman_config_proto_enumTypes, MessageInfos: file_app_proxyman_config_proto_msgTypes, }.Build() File_app_proxyman_config_proto = out.File diff --git a/app/proxyman/config.proto b/app/proxyman/config.proto index a267a00b..4f1298b9 100644 --- a/app/proxyman/config.proto +++ b/app/proxyman/config.proto @@ -13,33 +13,6 @@ import "common/serial/typed_message.proto"; message InboundConfig {} -message AllocationStrategy { - enum Type { - // Always allocate all connection handlers. - Always = 0; - - // Randomly allocate specific range of handlers. - Random = 1; - - // External. Not supported yet. - External = 2; - } - - Type type = 1; - - message AllocationStrategyConcurrency { uint32 value = 1; } - - // Number of handlers (ports) running in parallel. - // Default value is 3 if unset. - AllocationStrategyConcurrency concurrency = 2; - - message AllocationStrategyRefresh { uint32 value = 1; } - - // Number of minutes before a handler is regenerated. - // Default value is 5 if unset. - AllocationStrategyRefresh refresh = 3; -} - message SniffingConfig { // Whether or not to enable content sniffing on an inbound connection. bool enabled = 1; @@ -62,11 +35,10 @@ message ReceiverConfig { xray.common.net.PortList port_list = 1; // Listen specifies the IP address that the Receiver should listen on. xray.common.net.IPOrDomain listen = 2; - AllocationStrategy allocation_strategy = 3; - xray.transport.internet.StreamConfig stream_settings = 4; - bool receive_original_destination = 5; - reserved 6; - SniffingConfig sniffing_settings = 7; + xray.transport.internet.StreamConfig stream_settings = 3; + bool receive_original_destination = 4; + reserved 5; + SniffingConfig sniffing_settings = 6; } message InboundHandlerConfig { diff --git a/app/proxyman/inbound/always.go b/app/proxyman/inbound/always.go index f6a769fb..6fb3ba43 100644 --- a/app/proxyman/inbound/always.go +++ b/app/proxyman/inbound/always.go @@ -5,7 +5,6 @@ import ( "github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/net" @@ -103,7 +102,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * stream: mss, tag: tag, dispatcher: h.mux, - sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(), + sniffingConfig: receiverConfig.SniffingSettings, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, ctx: ctx, @@ -125,7 +124,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * recvOrigDest: receiverConfig.ReceiveOriginalDestination, tag: tag, dispatcher: h.mux, - sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(), + sniffingConfig: receiverConfig.SniffingSettings, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, ctx: ctx, @@ -140,7 +139,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * address: address, port: net.Port(port), dispatcher: h.mux, - sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(), + sniffingConfig: receiverConfig.SniffingSettings, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, stream: mss, @@ -178,14 +177,6 @@ func (h *AlwaysOnInboundHandler) Close() error { return nil } -func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) { - if len(h.workers) == 0 { - return nil, 0, 0 - } - w := h.workers[dice.Roll(len(h.workers))] - return w.Proxy(), w.Port(), 9999 -} - func (h *AlwaysOnInboundHandler) Tag() string { return h.tag } diff --git a/app/proxyman/inbound/dynamic.go b/app/proxyman/inbound/dynamic.go deleted file mode 100644 index f14a9952..00000000 --- a/app/proxyman/inbound/dynamic.go +++ /dev/null @@ -1,222 +0,0 @@ -package inbound - -import ( - "context" - "sync" - "time" - - "github.com/xtls/xray-core/app/proxyman" - "github.com/xtls/xray-core/common/dice" - "github.com/xtls/xray-core/common/errors" - "github.com/xtls/xray-core/common/mux" - "github.com/xtls/xray-core/common/net" - "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/common/task" - "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy" - "github.com/xtls/xray-core/transport/internet" - "google.golang.org/protobuf/proto" -) - -type DynamicInboundHandler struct { - tag string - v *core.Instance - proxyConfig interface{} - receiverConfig *proxyman.ReceiverConfig - streamSettings *internet.MemoryStreamConfig - portMutex sync.Mutex - portsInUse map[net.Port]struct{} - workerMutex sync.RWMutex - worker []worker - lastRefresh time.Time - mux *mux.Server - task *task.Periodic - - ctx context.Context -} - -func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*DynamicInboundHandler, error) { - v := core.MustFromContext(ctx) - h := &DynamicInboundHandler{ - tag: tag, - proxyConfig: proxyConfig, - receiverConfig: receiverConfig, - portsInUse: make(map[net.Port]struct{}), - mux: mux.NewServer(ctx), - v: v, - ctx: ctx, - } - - mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings) - if err != nil { - return nil, errors.New("failed to parse stream settings").Base(err).AtWarning() - } - if receiverConfig.ReceiveOriginalDestination { - if mss.SocketSettings == nil { - mss.SocketSettings = &internet.SocketConfig{} - } - if mss.SocketSettings.Tproxy == internet.SocketConfig_Off { - mss.SocketSettings.Tproxy = internet.SocketConfig_Redirect - } - mss.SocketSettings.ReceiveOriginalDestAddress = true - } - - h.streamSettings = mss - - h.task = &task.Periodic{ - Interval: time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()), - Execute: h.refresh, - } - - return h, nil -} - -func (h *DynamicInboundHandler) allocatePort() net.Port { - allPorts := []int32{} - for _, pr := range h.receiverConfig.PortList.Range { - for i := pr.From; i <= pr.To; i++ { - allPorts = append(allPorts, int32(i)) - } - } - h.portMutex.Lock() - defer h.portMutex.Unlock() - - for { - r := dice.Roll(len(allPorts)) - port := net.Port(allPorts[r]) - _, used := h.portsInUse[port] - if !used { - h.portsInUse[port] = struct{}{} - return port - } - } -} - -func (h *DynamicInboundHandler) closeWorkers(workers []worker) { - ports2Del := make([]net.Port, len(workers)) - for idx, worker := range workers { - ports2Del[idx] = worker.Port() - if err := worker.Close(); err != nil { - errors.LogInfoInner(h.ctx, err, "failed to close worker") - } - } - - h.portMutex.Lock() - for _, port := range ports2Del { - delete(h.portsInUse, port) - } - h.portMutex.Unlock() -} - -func (h *DynamicInboundHandler) refresh() error { - h.lastRefresh = time.Now() - - timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()) * 2 - concurrency := h.receiverConfig.AllocationStrategy.GetConcurrencyValue() - workers := make([]worker, 0, concurrency) - - address := h.receiverConfig.Listen.AsAddress() - if address == nil { - address = net.AnyIP - } - - uplinkCounter, downlinkCounter := getStatCounter(h.v, h.tag) - - for i := uint32(0); i < concurrency; i++ { - port := h.allocatePort() - rawProxy, err := core.CreateObject(h.v, h.proxyConfig) - if err != nil { - errors.LogWarningInner(h.ctx, err, "failed to create proxy instance") - continue - } - p := rawProxy.(proxy.Inbound) - nl := p.Network() - if net.HasNetwork(nl, net.Network_TCP) { - worker := &tcpWorker{ - tag: h.tag, - address: address, - port: port, - proxy: p, - stream: h.streamSettings, - recvOrigDest: h.receiverConfig.ReceiveOriginalDestination, - dispatcher: h.mux, - sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(), - uplinkCounter: uplinkCounter, - downlinkCounter: downlinkCounter, - ctx: h.ctx, - } - if err := worker.Start(); err != nil { - errors.LogWarningInner(h.ctx, err, "failed to create TCP worker") - continue - } - workers = append(workers, worker) - } - - if net.HasNetwork(nl, net.Network_UDP) { - worker := &udpWorker{ - tag: h.tag, - proxy: p, - address: address, - port: port, - dispatcher: h.mux, - sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(), - uplinkCounter: uplinkCounter, - downlinkCounter: downlinkCounter, - stream: h.streamSettings, - ctx: h.ctx, - } - if err := worker.Start(); err != nil { - errors.LogWarningInner(h.ctx, err, "failed to create UDP worker") - continue - } - workers = append(workers, worker) - } - } - - h.workerMutex.Lock() - h.worker = workers - h.workerMutex.Unlock() - - time.AfterFunc(timeout, func() { - h.closeWorkers(workers) - }) - - return nil -} - -func (h *DynamicInboundHandler) Start() error { - return h.task.Start() -} - -func (h *DynamicInboundHandler) Close() error { - return h.task.Close() -} - -func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) { - h.workerMutex.RLock() - defer h.workerMutex.RUnlock() - - if len(h.worker) == 0 { - return nil, 0, 0 - } - w := h.worker[dice.Roll(len(h.worker))] - expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute) - return w.Proxy(), w.Port(), int(expire) -} - -func (h *DynamicInboundHandler) Tag() string { - return h.tag -} - -// ReceiverSettings implements inbound.Handler. -func (h *DynamicInboundHandler) ReceiverSettings() *serial.TypedMessage { - return serial.ToTypedMessage(h.receiverConfig) -} - -// ProxySettings implements inbound.Handler. -func (h *DynamicInboundHandler) ProxySettings() *serial.TypedMessage { - if v, ok := h.proxyConfig.(proto.Message); ok { - return serial.ToTypedMessage(v) - } - return nil -} diff --git a/app/proxyman/inbound/inbound.go b/app/proxyman/inbound/inbound.go index 8e484965..374a0428 100644 --- a/app/proxyman/inbound/inbound.go +++ b/app/proxyman/inbound/inbound.go @@ -178,15 +178,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP) } - allocStrategy := receiverSettings.AllocationStrategy - if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { - return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings) - } - - if allocStrategy.Type == proxyman.AllocationStrategy_Random { - return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings) - } - return nil, errors.New("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError() + return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings) } func init() { diff --git a/common/protocol/headers.go b/common/protocol/headers.go index f6614ec7..bc90ca6c 100644 --- a/common/protocol/headers.go +++ b/common/protocol/headers.go @@ -5,7 +5,6 @@ import ( "github.com/xtls/xray-core/common/bitmask" "github.com/xtls/xray-core/common/net" - "github.com/xtls/xray-core/common/uuid" "golang.org/x/sys/cpu" ) @@ -71,14 +70,6 @@ type ResponseHeader struct { Command ResponseCommand } -type CommandSwitchAccount struct { - Host net.Address - Port net.Port - ID uuid.UUID - Level uint32 - ValidMin byte -} - var ( // Keep in sync with crypto/tls/cipher_suites.go. hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 diff --git a/common/protocol/server_picker.go b/common/protocol/server_picker.go deleted file mode 100644 index 62aa404e..00000000 --- a/common/protocol/server_picker.go +++ /dev/null @@ -1,89 +0,0 @@ -package protocol - -import ( - "sync" -) - -type ServerList struct { - sync.RWMutex - servers []*ServerSpec -} - -func NewServerList() *ServerList { - return &ServerList{} -} - -func (sl *ServerList) AddServer(server *ServerSpec) { - sl.Lock() - defer sl.Unlock() - - sl.servers = append(sl.servers, server) -} - -func (sl *ServerList) Size() uint32 { - sl.RLock() - defer sl.RUnlock() - - return uint32(len(sl.servers)) -} - -func (sl *ServerList) GetServer(idx uint32) *ServerSpec { - sl.Lock() - defer sl.Unlock() - - for { - if idx >= uint32(len(sl.servers)) { - return nil - } - - server := sl.servers[idx] - if !server.IsValid() { - sl.removeServer(idx) - continue - } - - return server - } -} - -func (sl *ServerList) removeServer(idx uint32) { - n := len(sl.servers) - sl.servers[idx] = sl.servers[n-1] - sl.servers = sl.servers[:n-1] -} - -type ServerPicker interface { - PickServer() *ServerSpec -} - -type RoundRobinServerPicker struct { - sync.Mutex - serverlist *ServerList - nextIndex uint32 -} - -func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker { - return &RoundRobinServerPicker{ - serverlist: serverlist, - nextIndex: 0, - } -} - -func (p *RoundRobinServerPicker) PickServer() *ServerSpec { - p.Lock() - defer p.Unlock() - - next := p.nextIndex - server := p.serverlist.GetServer(next) - if server == nil { - next = 0 - server = p.serverlist.GetServer(0) - } - next++ - if next >= p.serverlist.Size() { - next = 0 - } - p.nextIndex = next - - return server -} diff --git a/common/protocol/server_picker_test.go b/common/protocol/server_picker_test.go deleted file mode 100644 index 8919b10b..00000000 --- a/common/protocol/server_picker_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package protocol_test - -import ( - "testing" - "time" - - "github.com/xtls/xray-core/common/net" - . "github.com/xtls/xray-core/common/protocol" -) - -func TestServerList(t *testing.T) { - list := NewServerList() - list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid())) - if list.Size() != 1 { - t.Error("list size: ", list.Size()) - } - list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second)))) - if list.Size() != 2 { - t.Error("list.size: ", list.Size()) - } - - server := list.GetServer(1) - if server.Destination().Port != 2 { - t.Error("server: ", server.Destination()) - } - time.Sleep(2 * time.Second) - server = list.GetServer(1) - if server != nil { - t.Error("server: ", server) - } - - server = list.GetServer(0) - if server.Destination().Port != 1 { - t.Error("server: ", server.Destination()) - } -} - -func TestServerPicker(t *testing.T) { - list := NewServerList() - list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid())) - list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second)))) - list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(3)), BeforeTime(time.Now().Add(time.Second)))) - - picker := NewRoundRobinServerPicker(list) - server := picker.PickServer() - if server.Destination().Port != 1 { - t.Error("server: ", server.Destination()) - } - server = picker.PickServer() - if server.Destination().Port != 2 { - t.Error("server: ", server.Destination()) - } - server = picker.PickServer() - if server.Destination().Port != 3 { - t.Error("server: ", server.Destination()) - } - server = picker.PickServer() - if server.Destination().Port != 1 { - t.Error("server: ", server.Destination()) - } - - time.Sleep(2 * time.Second) - server = picker.PickServer() - if server.Destination().Port != 1 { - t.Error("server: ", server.Destination()) - } - server = picker.PickServer() - if server.Destination().Port != 1 { - t.Error("server: ", server.Destination()) - } -} diff --git a/common/protocol/server_spec.go b/common/protocol/server_spec.go index 24b778bb..d3ab0089 100644 --- a/common/protocol/server_spec.go +++ b/common/protocol/server_spec.go @@ -1,122 +1,30 @@ package protocol import ( - "sync" - "time" - - "github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/net" ) -type ValidationStrategy interface { - IsValid() bool - Invalidate() -} - -type alwaysValidStrategy struct{} - -func AlwaysValid() ValidationStrategy { - return alwaysValidStrategy{} -} - -func (alwaysValidStrategy) IsValid() bool { - return true -} - -func (alwaysValidStrategy) Invalidate() {} - -type timeoutValidStrategy struct { - until time.Time -} - -func BeforeTime(t time.Time) ValidationStrategy { - return &timeoutValidStrategy{ - until: t, - } -} - -func (s *timeoutValidStrategy) IsValid() bool { - return s.until.After(time.Now()) -} - -func (s *timeoutValidStrategy) Invalidate() { - s.until = time.Time{} -} - type ServerSpec struct { - sync.RWMutex - dest net.Destination - users []*MemoryUser - valid ValidationStrategy + Destination net.Destination + User *MemoryUser } -func NewServerSpec(dest net.Destination, valid ValidationStrategy, users ...*MemoryUser) *ServerSpec { +func NewServerSpec(dest net.Destination, user *MemoryUser) *ServerSpec { return &ServerSpec{ - dest: dest, - users: users, - valid: valid, + Destination: dest, + User: user, } } func NewServerSpecFromPB(spec *ServerEndpoint) (*ServerSpec, error) { dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port)) - mUsers := make([]*MemoryUser, len(spec.User)) - for idx, u := range spec.User { - mUser, err := u.ToMemoryUser() + var dUser *MemoryUser + if spec.User != nil { + user, err := spec.User.ToMemoryUser() if err != nil { return nil, err } - mUsers[idx] = mUser + dUser = user } - return NewServerSpec(dest, AlwaysValid(), mUsers...), nil -} - -func (s *ServerSpec) Destination() net.Destination { - return s.dest -} - -func (s *ServerSpec) HasUser(user *MemoryUser) bool { - s.RLock() - defer s.RUnlock() - - for _, u := range s.users { - if u.Account.Equals(user.Account) { - return true - } - } - return false -} - -func (s *ServerSpec) AddUser(user *MemoryUser) { - if s.HasUser(user) { - return - } - - s.Lock() - defer s.Unlock() - - s.users = append(s.users, user) -} - -func (s *ServerSpec) PickUser() *MemoryUser { - s.RLock() - defer s.RUnlock() - - userCount := len(s.users) - switch userCount { - case 0: - return nil - case 1: - return s.users[0] - default: - return s.users[dice.Roll(userCount)] - } -} - -func (s *ServerSpec) IsValid() bool { - return s.valid.IsValid() -} - -func (s *ServerSpec) Invalidate() { - s.valid.Invalidate() + return NewServerSpec(dest, dUser), nil } diff --git a/common/protocol/server_spec.pb.go b/common/protocol/server_spec.pb.go index f196930e..4a98aa05 100644 --- a/common/protocol/server_spec.pb.go +++ b/common/protocol/server_spec.pb.go @@ -28,7 +28,7 @@ type ServerEndpoint struct { Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` - User []*User `protobuf:"bytes,3,rep,name=user,proto3" json:"user,omitempty"` + User *User `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty"` } func (x *ServerEndpoint) Reset() { @@ -75,7 +75,7 @@ func (x *ServerEndpoint) GetPort() uint32 { return 0 } -func (x *ServerEndpoint) GetUser() []*User { +func (x *ServerEndpoint) GetUser() *User { if x != nil { return x.User } @@ -98,7 +98,7 @@ var file_common_protocol_server_spec_proto_rawDesc = []byte{ 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2e, 0x0a, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, diff --git a/common/protocol/server_spec.proto b/common/protocol/server_spec.proto index 6b9cc04c..79c6e58e 100644 --- a/common/protocol/server_spec.proto +++ b/common/protocol/server_spec.proto @@ -12,5 +12,5 @@ import "common/protocol/user.proto"; message ServerEndpoint { xray.common.net.IPOrDomain address = 1; uint32 port = 2; - repeated xray.common.protocol.User user = 3; + xray.common.protocol.User user = 3; } diff --git a/common/protocol/server_spec_test.go b/common/protocol/server_spec_test.go deleted file mode 100644 index 10dfb8c5..00000000 --- a/common/protocol/server_spec_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package protocol_test - -import ( - "strings" - "testing" - "time" - - "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/net" - . "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/common/uuid" - "github.com/xtls/xray-core/proxy/vmess" -) - -func TestAlwaysValidStrategy(t *testing.T) { - strategy := AlwaysValid() - if !strategy.IsValid() { - t.Error("strategy not valid") - } - strategy.Invalidate() - if !strategy.IsValid() { - t.Error("strategy not valid") - } -} - -func TestTimeoutValidStrategy(t *testing.T) { - strategy := BeforeTime(time.Now().Add(2 * time.Second)) - if !strategy.IsValid() { - t.Error("strategy not valid") - } - time.Sleep(3 * time.Second) - if strategy.IsValid() { - t.Error("strategy is valid") - } - - strategy = BeforeTime(time.Now().Add(2 * time.Second)) - strategy.Invalidate() - if strategy.IsValid() { - t.Error("strategy is valid") - } -} - -func TestUserInServerSpec(t *testing.T) { - uuid1 := uuid.New() - uuid2 := uuid.New() - - toAccount := func(a *vmess.Account) Account { - account, err := a.AsAccount() - common.Must(err) - return account - } - - spec := NewServerSpec(net.Destination{}, AlwaysValid(), &MemoryUser{ - Email: "test1@example.com", - Account: toAccount(&vmess.Account{Id: uuid1.String()}), - }) - if spec.HasUser(&MemoryUser{ - Email: "test1@example.com", - Account: toAccount(&vmess.Account{Id: uuid2.String()}), - }) { - t.Error("has user: ", uuid2) - } - - spec.AddUser(&MemoryUser{Email: "test2@example.com"}) - if !spec.HasUser(&MemoryUser{ - Email: "test1@example.com", - Account: toAccount(&vmess.Account{Id: uuid1.String()}), - }) { - t.Error("not having user: ", uuid1) - } -} - -func TestPickUser(t *testing.T) { - spec := NewServerSpec(net.Destination{}, AlwaysValid(), &MemoryUser{Email: "test1@example.com"}, &MemoryUser{Email: "test2@example.com"}, &MemoryUser{Email: "test3@example.com"}) - user := spec.PickUser() - if !strings.HasSuffix(user.Email, "@example.com") { - t.Error("user: ", user.Email) - } -} diff --git a/core/xray_test.go b/core/xray_test.go index f4cb11ab..65ff3fc8 100644 --- a/core/xray_test.go +++ b/core/xray_test.go @@ -63,17 +63,13 @@ func TestXrayClose(t *testing.T) { Outbound: []*OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(0), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(0), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), diff --git a/features/inbound/inbound.go b/features/inbound/inbound.go index 1d3ba7b1..11caf3f9 100644 --- a/features/inbound/inbound.go +++ b/features/inbound/inbound.go @@ -4,7 +4,6 @@ import ( "context" "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/features" ) @@ -20,9 +19,6 @@ type Handler interface { ReceiverSettings() *serial.TypedMessage // Returns the active proxy settings. ProxySettings() *serial.TypedMessage - - // Deprecated: Do not use in new code. - GetRandomInboundProxy() (interface{}, net.Port, int) } // Manager is a feature that manages InboundHandlers. diff --git a/infra/conf/http.go b/infra/conf/http.go index d4092f88..7da8f3f5 100644 --- a/infra/conf/http.go +++ b/infra/conf/http.go @@ -68,12 +68,19 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) { { Address: v.Address, Port: v.Port, - Users: []json.RawMessage{{}}, }, } + if len(v.Username) > 0 { + v.Servers[0].Users = []json.RawMessage{{}} + } } - config.Server = make([]*protocol.ServerEndpoint, len(v.Servers)) - for idx, serverConfig := range v.Servers { + if len(v.Servers) != 1 { + return nil, errors.New(`HTTP settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple HTTP outbounds and routing balancer instead`) + } + for _, serverConfig := range v.Servers { + if len(serverConfig.Users) > 1 { + return nil, errors.New(`HTTP servers: "users" should have one member at most. Multiple members in "users" should use multiple HTTP outbounds and routing balancer instead`) + } server := &protocol.ServerEndpoint{ Address: serverConfig.Address.Build(), Port: uint32(serverConfig.Port), @@ -98,9 +105,11 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) { } } user.Account = serial.ToTypedMessage(account.Build()) - server.User = append(server.User, user) + server.User = user + break } - config.Server[idx] = server + config.Server = server + break } config.Header = make([]*http.Header, 0, 32) for key, value := range v.Headers { diff --git a/infra/conf/shadowsocks.go b/infra/conf/shadowsocks.go index a05c1dc5..4a04d977 100644 --- a/infra/conf/shadowsocks.go +++ b/infra/conf/shadowsocks.go @@ -172,16 +172,16 @@ type ShadowsocksServerTarget struct { } type ShadowsocksClientConfig struct { - Address *Address `json:"address"` - Port uint16 `json:"port"` - Level byte `json:"level"` - Email string `json:"email"` - Cipher string `json:"method"` - Password string `json:"password"` - IVCheck bool `json:"ivCheck"` - UoT bool `json:"uot"` - UoTVersion int `json:"uotVersion"` - Servers []*ShadowsocksServerTarget `json:"servers"` + Address *Address `json:"address"` + Port uint16 `json:"port"` + Level byte `json:"level"` + Email string `json:"email"` + Cipher string `json:"method"` + Password string `json:"password"` + IVCheck bool `json:"ivCheck"` + UoT bool `json:"uot"` + UoTVersion int `json:"uotVersion"` + Servers []*ShadowsocksServerTarget `json:"servers"` } func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { @@ -200,8 +200,8 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { }, } } - if len(v.Servers) == 0 { - return nil, errors.New("0 Shadowsocks server configured.") + if len(v.Servers) != 1 { + return nil, errors.New(`Shadowsocks settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Shadowsocks outbounds and routing balancer instead`) } if len(v.Servers) == 1 { @@ -229,8 +229,7 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { } config := new(shadowsocks.ClientConfig) - serverSpecs := make([]*protocol.ServerEndpoint, len(v.Servers)) - for idx, server := range v.Servers { + for _, server := range v.Servers { if C.Contains(shadowaead_2022.List, server.Cipher) { return nil, errors.New("Shadowsocks 2022 accept no multi servers") } @@ -256,19 +255,16 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) { ss := &protocol.ServerEndpoint{ Address: server.Address.Build(), Port: uint32(server.Port), - User: []*protocol.User{ - { - Level: uint32(server.Level), - Email: server.Email, - Account: serial.ToTypedMessage(account), - }, + User: &protocol.User{ + Level: uint32(server.Level), + Email: server.Email, + Account: serial.ToTypedMessage(account), }, } - serverSpecs[idx] = ss + config.Server = ss + break } - config.Server = serverSpecs - return config, nil } diff --git a/infra/conf/socks.go b/infra/conf/socks.go index 6955001f..d0d68d81 100644 --- a/infra/conf/socks.go +++ b/infra/conf/socks.go @@ -86,12 +86,19 @@ func (v *SocksClientConfig) Build() (proto.Message, error) { { Address: v.Address, Port: v.Port, - Users: []json.RawMessage{{}}, }, } + if len(v.Username) > 0 { + v.Servers[0].Users = []json.RawMessage{{}} + } } - config.Server = make([]*protocol.ServerEndpoint, len(v.Servers)) - for idx, serverConfig := range v.Servers { + if len(v.Servers) != 1 { + return nil, errors.New(`SOCKS settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple SOCKS outbounds and routing balancer instead`) + } + for _, serverConfig := range v.Servers { + if len(serverConfig.Users) > 1 { + return nil, errors.New(`SOCKS servers: "users" should have one member at most. Multiple members in "users" should use multiple SOCKS outbounds and routing balancer instead`) + } server := &protocol.ServerEndpoint{ Address: serverConfig.Address.Build(), Port: uint32(serverConfig.Port), @@ -116,9 +123,11 @@ func (v *SocksClientConfig) Build() (proto.Message, error) { } } user.Account = serial.ToTypedMessage(account.Build()) - server.User = append(server.User, user) + server.User = user + break } - config.Server[idx] = server + config.Server = server + break } return config, nil } diff --git a/infra/conf/socks_test.go b/infra/conf/socks_test.go index da609de8..d94802ec 100644 --- a/infra/conf/socks_test.go +++ b/infra/conf/socks_test.go @@ -65,24 +65,20 @@ func TestSocksOutboundConfig(t *testing.T) { }`, Parser: loadJSON(creator), Output: &socks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, - }, - Port: 1234, - User: []*protocol.User{ - { - Email: "test@email.com", - Account: serial.ToTypedMessage(&socks.Account{ - Username: "test user", - Password: "test pass", - }), - }, + Server: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, }, }, + Port: 1234, + User: &protocol.User{ + Email: "test@email.com", + Account: serial.ToTypedMessage(&socks.Account{ + Username: "test user", + Password: "test pass", + }), + }, }, }, }, @@ -96,24 +92,20 @@ func TestSocksOutboundConfig(t *testing.T) { }`, Parser: loadJSON(creator), Output: &socks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, - }, - Port: 1234, - User: []*protocol.User{ - { - Email: "test@email.com", - Account: serial.ToTypedMessage(&socks.Account{ - Username: "test user", - Password: "test pass", - }), - }, + Server: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, }, }, + Port: 1234, + User: &protocol.User{ + Email: "test@email.com", + Account: serial.ToTypedMessage(&socks.Account{ + Username: "test user", + Password: "test pass", + }), + }, }, }, }, diff --git a/infra/conf/trojan.go b/infra/conf/trojan.go index d7d4ea17..d9907019 100644 --- a/infra/conf/trojan.go +++ b/infra/conf/trojan.go @@ -28,13 +28,13 @@ type TrojanServerTarget struct { // TrojanClientConfig is configuration of trojan servers type TrojanClientConfig struct { - Address *Address `json:"address"` - Port uint16 `json:"port"` - Level byte `json:"level"` - Email string `json:"email"` - Password string `json:"password"` - Flow string `json:"flow"` - Servers []*TrojanServerTarget `json:"servers"` + Address *Address `json:"address"` + Port uint16 `json:"port"` + Level byte `json:"level"` + Email string `json:"email"` + Password string `json:"password"` + Flow string `json:"flow"` + Servers []*TrojanServerTarget `json:"servers"` } // Build implements Buildable @@ -51,15 +51,13 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) { }, } } - if len(c.Servers) == 0 { - return nil, errors.New("0 Trojan server configured.") + if len(c.Servers) != 1 { + return nil, errors.New(`Trojan settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Trojan outbounds and routing balancer instead`) } - config := &trojan.ClientConfig{ - Server: make([]*protocol.ServerEndpoint, len(c.Servers)), - } + config := &trojan.ClientConfig{} - for idx, rec := range c.Servers { + for _, rec := range c.Servers { if rec.Address == nil { return nil, errors.New("Trojan server address is not set.") } @@ -73,19 +71,19 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) { return nil, errors.PrintRemovedFeatureError(`Flow for Trojan`, ``) } - config.Server[idx] = &protocol.ServerEndpoint{ + config.Server = &protocol.ServerEndpoint{ Address: rec.Address.Build(), Port: uint32(rec.Port), - User: []*protocol.User{ - { - Level: uint32(rec.Level), - Email: rec.Email, - Account: serial.ToTypedMessage(&trojan.Account{ - Password: rec.Password, - }), - }, + User: &protocol.User{ + Level: uint32(rec.Level), + Email: rec.Email, + Account: serial.ToTypedMessage(&trojan.Account{ + Password: rec.Password, + }), }, } + + break } return config, nil diff --git a/infra/conf/vless.go b/infra/conf/vless.go index aa410e5c..efb480a0 100644 --- a/infra/conf/vless.go +++ b/infra/conf/vless.go @@ -228,22 +228,20 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) { } } if len(c.Vnext) != 1 { - return nil, errors.New(`VLESS settings: "vnext" should have one and only one member`) + return nil, errors.New(`VLESS settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VLESS outbounds and routing balancer instead`) } - config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext)) - for idx, rec := range c.Vnext { + for _, rec := range c.Vnext { if rec.Address == nil { return nil, errors.New(`VLESS vnext: "address" is not set`) } if len(rec.Users) != 1 { - return nil, errors.New(`VLESS vnext: "users" should have one and only one member`) + return nil, errors.New(`VLESS vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VLESS outbounds and routing balancer instead`) } spec := &protocol.ServerEndpoint{ Address: rec.Address.Build(), Port: uint32(rec.Port), - User: make([]*protocol.User, len(rec.Users)), } - for idx, rawUser := range rec.Users { + for _, rawUser := range rec.Users { user := new(protocol.User) if c.Address != nil { user.Level = c.Level @@ -327,9 +325,11 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) { } user.Account = serial.ToTypedMessage(account) - spec.User[idx] = user + spec.User = user + break } - config.Vnext[idx] = spec + config.Vnext = spec + break } return config, nil diff --git a/infra/conf/vless_test.go b/infra/conf/vless_test.go index 480d3b86..2fd97915 100644 --- a/infra/conf/vless_test.go +++ b/infra/conf/vless_test.go @@ -35,25 +35,21 @@ func TestVLessOutbound(t *testing.T) { }`, Parser: loadJSON(creator), Output: &outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Domain{ - Domain: "example.com", - }, - }, - Port: 443, - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: "27848739-7e62-4138-9fd3-098a63964b6b", - Flow: "xtls-rprx-vision-udp443", - Encryption: "none", - }), - Level: 0, - }, + Vnext: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "example.com", }, }, + Port: 443, + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: "27848739-7e62-4138-9fd3-098a63964b6b", + Flow: "xtls-rprx-vision-udp443", + Encryption: "none", + }), + Level: 0, + }, }, }, }, @@ -68,25 +64,21 @@ func TestVLessOutbound(t *testing.T) { }`, Parser: loadJSON(creator), Output: &outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Domain{ - Domain: "example.com", - }, - }, - Port: 443, - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: "27848739-7e62-4138-9fd3-098a63964b6b", - Flow: "xtls-rprx-vision-udp443", - Encryption: "none", - }), - Level: 0, - }, + Vnext: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "example.com", }, }, + Port: 443, + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: "27848739-7e62-4138-9fd3-098a63964b6b", + Flow: "xtls-rprx-vision-udp443", + Encryption: "none", + }), + Level: 0, + }, }, }, }, diff --git a/infra/conf/vmess.go b/infra/conf/vmess.go index c0171c4b..4db061de 100644 --- a/infra/conf/vmess.go +++ b/infra/conf/vmess.go @@ -46,17 +46,6 @@ func (a *VMessAccount) Build() *vmess.Account { } } -type VMessDetourConfig struct { - ToTag string `json:"to"` -} - -// Build implements Buildable -func (c *VMessDetourConfig) Build() *inbound.DetourConfig { - return &inbound.DetourConfig{ - To: c.ToTag, - } -} - type VMessDefaultConfig struct { Level byte `json:"level"` } @@ -71,7 +60,6 @@ func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig { type VMessInboundConfig struct { Users []json.RawMessage `json:"clients"` Defaults *VMessDefaultConfig `json:"default"` - DetourConfig *VMessDetourConfig `json:"detour"` } // Build implements Buildable @@ -82,10 +70,6 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) { config.Default = c.Defaults.Build() } - if c.DetourConfig != nil { - config.Detour = c.DetourConfig.Build() - } - config.User = make([]*protocol.User, len(c.Users)) for idx, rawData := range c.Users { user := new(protocol.User) @@ -139,16 +123,15 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) { }, } } - if len(c.Receivers) == 0 { - return nil, errors.New("0 VMess receiver configured") + if len(c.Receivers) != 1 { + return nil, errors.New(`VMess settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VMess outbounds and routing balancer instead`) } - serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers)) - for idx, rec := range c.Receivers { - if len(rec.Users) == 0 { - return nil, errors.New("0 user configured for VMess outbound") + for _, rec := range c.Receivers { + if len(rec.Users) != 1 { + return nil, errors.New(`VMess vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VMess outbounds and routing balancer instead`) } if rec.Address == nil { - return nil, errors.New("address is not set in VMess outbound config") + return nil, errors.New(`VMess vnext: "address" is not set`) } spec := &protocol.ServerEndpoint{ Address: rec.Address.Build(), @@ -182,10 +165,11 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) { account.ID = u.String() user.Account = serial.ToTypedMessage(account.Build()) - spec.User = append(spec.User, user) + spec.User = user + break } - serverSpecs[idx] = spec + config.Receiver = spec + break } - config.Receiver = serverSpecs return config, nil } diff --git a/infra/conf/vmess_test.go b/infra/conf/vmess_test.go index e3bf1349..b94db83e 100644 --- a/infra/conf/vmess_test.go +++ b/infra/conf/vmess_test.go @@ -34,26 +34,22 @@ func TestVMessOutbound(t *testing.T) { }`, Parser: loadJSON(creator), Output: &outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, + Receiver: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, }, - Port: 80, - User: []*protocol.User{ - { - Email: "love@example.com", - Level: 255, - Account: serial.ToTypedMessage(&vmess.Account{ - Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019", - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AUTO, - }, - }), + }, + Port: 80, + User: &protocol.User{ + Email: "love@example.com", + Level: 255, + Account: serial.ToTypedMessage(&vmess.Account{ + Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019", + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AUTO, }, - }, + }), }, }, }, @@ -68,26 +64,22 @@ func TestVMessOutbound(t *testing.T) { }`, Parser: loadJSON(creator), Output: &outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, + Receiver: &protocol.ServerEndpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, }, - Port: 80, - User: []*protocol.User{ - { - Email: "love@example.com", - Level: 255, - Account: serial.ToTypedMessage(&vmess.Account{ - Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019", - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AUTO, - }, - }), + }, + Port: 80, + User: &protocol.User{ + Email: "love@example.com", + Level: 255, + Account: serial.ToTypedMessage(&vmess.Account{ + Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019", + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AUTO, }, - }, + }), }, }, }, @@ -113,11 +105,7 @@ func TestVMessInbound(t *testing.T) { ], "default": { "level": 0 - }, - "detour": { - "to": "tag_to_detour" - }, - "disableInsecureEncryption": true + } }`, Parser: loadJSON(creator), Output: &inbound.Config{ @@ -136,9 +124,6 @@ func TestVMessInbound(t *testing.T) { Default: &inbound.DefaultConfig{ Level: 0, }, - Detour: &inbound.DetourConfig{ - To: "tag_to_detour", - }, }, }, }) diff --git a/infra/conf/xray.go b/infra/conf/xray.go index 88f01322..e9cacc87 100644 --- a/infra/conf/xray.go +++ b/infra/conf/xray.go @@ -3,7 +3,6 @@ package conf import ( "context" "encoding/json" - "fmt" "log" "os" "path/filepath" @@ -120,47 +119,12 @@ func (m *MuxConfig) Build() (*proxyman.MultiplexingConfig, error) { }, nil } -type InboundDetourAllocationConfig struct { - Strategy string `json:"strategy"` - Concurrency *uint32 `json:"concurrency"` - RefreshMin *uint32 `json:"refresh"` -} - -// Build implements Buildable. -func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, error) { - config := new(proxyman.AllocationStrategy) - switch strings.ToLower(c.Strategy) { - case "always": - config.Type = proxyman.AllocationStrategy_Always - case "random": - config.Type = proxyman.AllocationStrategy_Random - case "external": - config.Type = proxyman.AllocationStrategy_External - default: - return nil, errors.New("unknown allocation strategy: ", c.Strategy) - } - if c.Concurrency != nil { - config.Concurrency = &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ - Value: *c.Concurrency, - } - } - - if c.RefreshMin != nil { - config.Refresh = &proxyman.AllocationStrategy_AllocationStrategyRefresh{ - Value: *c.RefreshMin, - } - } - - return config, nil -} - type InboundDetourConfig struct { Protocol string `json:"protocol"` PortList *PortList `json:"port"` ListenOn *Address `json:"listen"` Settings *json.RawMessage `json:"settings"` Tag string `json:"tag"` - Allocation *InboundDetourAllocationConfig `json:"allocate"` StreamSetting *StreamConfig `json:"streamSettings"` SniffingConfig *SniffingConfig `json:"sniffing"` } @@ -197,30 +161,6 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) { } } - if c.Allocation != nil { - concurrency := -1 - if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" { - concurrency = int(*c.Allocation.Concurrency) - } - portRange := 0 - - for _, pr := range c.PortList.Range { - portRange += int(pr.To - pr.From + 1) - } - if concurrency >= 0 && concurrency >= portRange { - var ports strings.Builder - for _, pr := range c.PortList.Range { - fmt.Fprintf(&ports, "%d-%d ", pr.From, pr.To) - } - return nil, errors.New("not enough ports. concurrency = ", concurrency, " ports: ", ports.String()) - } - - as, err := c.Allocation.Build() - if err != nil { - return nil, err - } - receiverSettings.AllocationStrategy = as - } if c.StreamSetting != nil { ss, err := c.StreamSetting.Build() if err != nil { diff --git a/infra/conf/xray_test.go b/infra/conf/xray_test.go index 1c05ec2e..c1349fd2 100644 --- a/infra/conf/xray_test.go +++ b/infra/conf/xray_test.go @@ -58,10 +58,6 @@ func TestXrayConfig(t *testing.T) { }, "protocol": "vmess", "port": "443-500", - "allocate": { - "strategy": "random", - "concurrency": 3 - }, "settings": { "clients": [ { @@ -123,12 +119,6 @@ func TestXrayConfig(t *testing.T) { From: 443, To: 500, }}}, - AllocationStrategy: &proxyman.AllocationStrategy{ - Type: proxyman.AllocationStrategy_Random, - Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ - Value: 3, - }, - }, StreamSettings: &internet.StreamConfig{ ProtocolName: "websocket", TransportSettings: []*internet.TransportConfig{ diff --git a/proxy/http/client.go b/proxy/http/client.go index b1326bec..d5be2acb 100644 --- a/proxy/http/client.go +++ b/proxy/http/client.go @@ -31,7 +31,7 @@ import ( ) type Client struct { - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager header []*Header } @@ -48,21 +48,17 @@ var ( // NewClient create a new http client based on the given config. func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Server { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to get server spec").Base(err) - } - serverList.AddServer(s) + if config.Server == nil { + return nil, errors.New(`no target server found`) } - if serverList.Size() == 0 { - return nil, errors.New("0 target server") + server, err := protocol.NewServerSpecFromPB(config.Server) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err) } v := core.MustFromContext(ctx) return &Client{ - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), header: config.Header, }, nil @@ -84,7 +80,9 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter return errors.New("UDP is not supported by HTTP outbound") } - var user *protocol.MemoryUser + server := c.server + dest := server.Destination + user := server.User var conn stat.Connection mbuf, _ := link.Reader.ReadMultiBuffer() @@ -102,10 +100,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter } if err := retry.ExponentialBackoff(5, 100).On(func() error { - server := c.serverPicker.PickServer() - dest := server.Destination() - user = server.PickUser() - netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, header, firstPayload) if netConn != nil { if _, ok := netConn.(*http2Conn); !ok { diff --git a/proxy/http/config.pb.go b/proxy/http/config.pb.go index 03e03441..aef3a759 100644 --- a/proxy/http/config.pb.go +++ b/proxy/http/config.pb.go @@ -196,8 +196,8 @@ type ClientConfig struct { unknownFields protoimpl.UnknownFields // Sever is a list of HTTP server addresses. - Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"` - Header []*Header `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty"` + Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` + Header []*Header `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty"` } func (x *ClientConfig) Reset() { @@ -230,7 +230,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) { return file_proxy_http_config_proto_rawDescGZIP(), []int{3} } -func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint { +func (x *ClientConfig) GetServer() *protocol.ServerEndpoint { if x != nil { return x.Server } @@ -275,7 +275,7 @@ var file_proxy_http_config_proto_rawDesc = []byte{ 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x7d, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, diff --git a/proxy/http/config.proto b/proxy/http/config.proto index bc939df7..240c06b5 100644 --- a/proxy/http/config.proto +++ b/proxy/http/config.proto @@ -28,6 +28,6 @@ message Header { // ClientConfig is the protobuf config for HTTP proxy client. message ClientConfig { // Sever is a list of HTTP server addresses. - repeated xray.common.protocol.ServerEndpoint server = 1; + xray.common.protocol.ServerEndpoint server = 1; repeated Header header = 2; } diff --git a/proxy/shadowsocks/client.go b/proxy/shadowsocks/client.go index c2ad1c1c..29cb0456 100644 --- a/proxy/shadowsocks/client.go +++ b/proxy/shadowsocks/client.go @@ -22,27 +22,23 @@ import ( // Client is a inbound handler for Shadowsocks protocol type Client struct { - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager } // NewClient create a new Shadowsocks client. func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Server { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to parse server spec").Base(err) - } - serverList.AddServer(s) + if config.Server == nil { + return nil, errors.New(`no target server found`) } - if serverList.Size() == 0 { - return nil, errors.New("0 server") + server, err := protocol.NewServerSpecFromPB(config.Server) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err) } v := core.MustFromContext(ctx) client := &Client{ - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), } return client, nil @@ -60,13 +56,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter destination := ob.Target network := destination.Network - var server *protocol.ServerSpec + server := c.server + dest := server.Destination + dest.Network = network var conn stat.Connection err := retry.ExponentialBackoff(5, 100).On(func() error { - server = c.serverPicker.PickServer() - dest := server.Destination() - dest.Network = network rawConn, err := dialer.Dial(ctx, dest) if err != nil { return err @@ -78,7 +73,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter if err != nil { return errors.New("failed to find an available destination").AtWarning().Base(err) } - errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination().NetAddr()) + errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination.NetAddr()) defer conn.Close() @@ -93,7 +88,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter request.Command = protocol.RequestCommandUDP } - user := server.PickUser() + user := server.User _, ok := user.Account.(*MemoryAccount) if !ok { return errors.New("user account is not valid") diff --git a/proxy/shadowsocks/config.pb.go b/proxy/shadowsocks/config.pb.go index 56cddb67..3419c509 100644 --- a/proxy/shadowsocks/config.pb.go +++ b/proxy/shadowsocks/config.pb.go @@ -199,7 +199,7 @@ type ClientConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"` + Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` } func (x *ClientConfig) Reset() { @@ -232,7 +232,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) { return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{2} } -func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint { +func (x *ClientConfig) GetServer() *protocol.ServerEndpoint { if x != nil { return x.Server } @@ -268,7 +268,7 @@ var file_proxy_shadowsocks_config_proto_rawDesc = []byte{ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x74, 0x0a, diff --git a/proxy/shadowsocks/config.proto b/proxy/shadowsocks/config.proto index 8f9fb891..879fb77b 100644 --- a/proxy/shadowsocks/config.proto +++ b/proxy/shadowsocks/config.proto @@ -32,5 +32,5 @@ message ServerConfig { } message ClientConfig { - repeated xray.common.protocol.ServerEndpoint server = 1; + xray.common.protocol.ServerEndpoint server = 1; } diff --git a/proxy/socks/client.go b/proxy/socks/client.go index 232215ec..eac3f35b 100644 --- a/proxy/socks/client.go +++ b/proxy/socks/client.go @@ -22,27 +22,23 @@ import ( // Client is a Socks5 client. type Client struct { - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager } // NewClient create a new Socks5 client based on the given config. func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Server { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to get server spec").Base(err) - } - serverList.AddServer(s) + if config.Server == nil { + return nil, errors.New(`no target server found`) } - if serverList.Size() == 0 { - return nil, errors.New("0 target server") + server, err := protocol.NewServerSpecFromPB(config.Server) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err) } v := core.MustFromContext(ctx) c := &Client{ - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), } @@ -62,15 +58,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter destination := ob.Target // Outbound server. - var server *protocol.ServerSpec - // Outbound server's destination. - var dest net.Destination + server := c.server + dest := server.Destination // Connection to the outbound server. var conn stat.Connection if err := retry.ExponentialBackoff(5, 100).On(func() error { - server = c.serverPicker.PickServer() - dest = server.Destination() rawConn, err := dialer.Dial(ctx, dest) if err != nil { return err @@ -101,7 +94,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter request.Command = protocol.RequestCommandUDP } - user := server.PickUser() + user := server.User if user != nil { request.User = user p = c.policyManager.ForLevel(user.Level) diff --git a/proxy/socks/config.pb.go b/proxy/socks/config.pb.go index ee94d0bc..4363c0ec 100644 --- a/proxy/socks/config.pb.go +++ b/proxy/socks/config.pb.go @@ -210,7 +210,7 @@ type ClientConfig struct { unknownFields protoimpl.UnknownFields // Sever is a list of Socks server addresses. - Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"` + Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` } func (x *ClientConfig) Reset() { @@ -243,7 +243,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) { return file_proxy_socks_config_proto_rawDescGZIP(), []int{2} } -func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint { +func (x *ClientConfig) GetServer() *protocol.ServerEndpoint { if x != nil { return x.Server } @@ -286,7 +286,7 @@ var file_proxy_socks_config_proto_rawDesc = []byte{ 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x25, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, diff --git a/proxy/socks/config.proto b/proxy/socks/config.proto index 32d553d3..b53d565d 100644 --- a/proxy/socks/config.proto +++ b/proxy/socks/config.proto @@ -35,5 +35,5 @@ message ServerConfig { // ClientConfig is the protobuf config for Socks client. message ClientConfig { // Sever is a list of Socks server addresses. - repeated xray.common.protocol.ServerEndpoint server = 1; + xray.common.protocol.ServerEndpoint server = 1; } diff --git a/proxy/trojan/client.go b/proxy/trojan/client.go index a667d352..4af8c019 100644 --- a/proxy/trojan/client.go +++ b/proxy/trojan/client.go @@ -22,27 +22,23 @@ import ( // Client is a inbound handler for trojan protocol type Client struct { - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager } // NewClient create a new trojan client. func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Server { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to parse server spec").Base(err) - } - serverList.AddServer(s) + if config.Server == nil { + return nil, errors.New(`no target server found`) } - if serverList.Size() == 0 { - return nil, errors.New("0 server") + server, err := protocol.NewServerSpecFromPB(config.Server) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err) } v := core.MustFromContext(ctx) client := &Client{ - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), } return client, nil @@ -60,12 +56,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter destination := ob.Target network := destination.Network - var server *protocol.ServerSpec + server := c.server var conn stat.Connection err := retry.ExponentialBackoff(5, 100).On(func() error { - server = c.serverPicker.PickServer() - rawConn, err := dialer.Dial(ctx, server.Destination()) + rawConn, err := dialer.Dial(ctx, server.Destination) if err != nil { return err } @@ -76,11 +71,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter if err != nil { return errors.New("failed to find an available destination").AtWarning().Base(err) } - errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination().NetAddr()) + errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr()) defer conn.Close() - user := server.PickUser() + user := server.User account, ok := user.Account.(*MemoryAccount) if !ok { return errors.New("user account is not valid") diff --git a/proxy/trojan/config.pb.go b/proxy/trojan/config.pb.go index dd555ea4..d3a6f8b9 100644 --- a/proxy/trojan/config.pb.go +++ b/proxy/trojan/config.pb.go @@ -156,7 +156,7 @@ type ClientConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"` + Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` } func (x *ClientConfig) Reset() { @@ -189,7 +189,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) { return file_proxy_trojan_config_proto_rawDescGZIP(), []int{2} } -func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint { +func (x *ClientConfig) GetServer() *protocol.ServerEndpoint { if x != nil { return x.Server } @@ -271,7 +271,7 @@ var file_proxy_trojan_config_proto_rawDesc = []byte{ 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, diff --git a/proxy/trojan/config.proto b/proxy/trojan/config.proto index 4229e2ed..30dedbf4 100644 --- a/proxy/trojan/config.proto +++ b/proxy/trojan/config.proto @@ -23,7 +23,7 @@ message Fallback { } message ClientConfig { - repeated xray.common.protocol.ServerEndpoint server = 1; + xray.common.protocol.ServerEndpoint server = 1; } message ServerConfig { diff --git a/proxy/vless/outbound/config.pb.go b/proxy/vless/outbound/config.pb.go index 76d2f768..ed5db785 100644 --- a/proxy/vless/outbound/config.pb.go +++ b/proxy/vless/outbound/config.pb.go @@ -26,7 +26,7 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Vnext []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=vnext,proto3" json:"vnext,omitempty"` + Vnext *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=vnext,proto3" json:"vnext,omitempty"` } func (x *Config) Reset() { @@ -59,7 +59,7 @@ func (*Config) Descriptor() ([]byte, []int) { return file_proxy_vless_outbound_config_proto_rawDescGZIP(), []int{0} } -func (x *Config) GetVnext() []*protocol.ServerEndpoint { +func (x *Config) GetVnext() *protocol.ServerEndpoint { if x != nil { return x.Vnext } @@ -76,7 +76,7 @@ var file_proxy_vless_outbound_config_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x44, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x76, - 0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, + 0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, diff --git a/proxy/vless/outbound/config.proto b/proxy/vless/outbound/config.proto index 55455cbf..150b2d6c 100644 --- a/proxy/vless/outbound/config.proto +++ b/proxy/vless/outbound/config.proto @@ -9,5 +9,5 @@ option java_multiple_files = true; import "common/protocol/server_spec.proto"; message Config { - repeated xray.common.protocol.ServerEndpoint vnext = 1; + xray.common.protocol.ServerEndpoint vnext = 1; } diff --git a/proxy/vless/outbound/outbound.go b/proxy/vless/outbound/outbound.go index 30b9dcf9..2d4e3ab6 100644 --- a/proxy/vless/outbound/outbound.go +++ b/proxy/vless/outbound/outbound.go @@ -47,8 +47,7 @@ func init() { // Handler is an outbound connection handler for VLess protocol. type Handler struct { - serverList *protocol.ServerList - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager cone bool encryption *encryption.ClientInstance @@ -57,24 +56,22 @@ type Handler struct { // New creates a new VLess outbound handler. func New(ctx context.Context, config *Config) (*Handler, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Vnext { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to parse server spec").Base(err).AtError() - } - serverList.AddServer(s) + if config.Vnext == nil { + return nil, errors.New(`no vnext found`) + } + server, err := protocol.NewServerSpecFromPB(config.Vnext) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err).AtError() } v := core.MustFromContext(ctx) handler := &Handler{ - serverList: serverList, - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), cone: ctx.Value("cone").(bool), } - a := handler.serverPicker.PickServer().PickUser().Account.(*vless.MemoryAccount) + a := handler.server.User.Account.(*vless.MemoryAccount) if a.Encryption != "" && a.Encryption != "none" { s := strings.Split(a.Encryption, ".") var nfsPKeysBytes [][]byte @@ -125,12 +122,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte } ob.Name = "vless" - var rec *protocol.ServerSpec + rec := h.server var conn stat.Connection + if err := retry.ExponentialBackoff(5, 200).On(func() error { - rec = h.serverPicker.PickServer() var err error - conn, err = dialer.Dial(ctx, rec.Destination()) + conn, err = dialer.Dial(ctx, rec.Destination) if err != nil { return err } @@ -145,7 +142,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte iConn = statConn.Connection } target := ob.Target - errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr()) + errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination.NetAddr()) if h.encryption != nil { var err error @@ -172,7 +169,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte request := &protocol.RequestHeader{ Version: encoding.Version, - User: rec.PickUser(), + User: rec.User, Command: command, Address: target.Address, Port: target.Port, diff --git a/proxy/vmess/encoding/commands.go b/proxy/vmess/encoding/commands.go index cdab871b..698052c5 100644 --- a/proxy/vmess/encoding/commands.go +++ b/proxy/vmess/encoding/commands.go @@ -7,10 +7,7 @@ import ( "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/errors" - "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/common/uuid" ) var ( @@ -29,9 +26,6 @@ func MarshalCommand(command interface{}, writer io.Writer) error { var cmdID byte var factory CommandFactory switch command.(type) { - case *protocol.CommandSwitchAccount: - factory = new(CommandSwitchAccountFactory) - cmdID = 1 default: return ErrUnknownCommand } @@ -67,8 +61,6 @@ func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) var factory CommandFactory switch cmdID { - case 1: - factory = new(CommandSwitchAccountFactory) default: return nil, ErrUnknownCommand } @@ -79,67 +71,3 @@ type CommandFactory interface { Marshal(command interface{}, writer io.Writer) error Unmarshal(data []byte) (interface{}, error) } - -type CommandSwitchAccountFactory struct{} - -func (f *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Writer) error { - cmd, ok := command.(*protocol.CommandSwitchAccount) - if !ok { - return ErrCommandTypeMismatch - } - - hostStr := "" - if cmd.Host != nil { - hostStr = cmd.Host.String() - } - common.Must2(writer.Write([]byte{byte(len(hostStr))})) - - if len(hostStr) > 0 { - common.Must2(writer.Write([]byte(hostStr))) - } - - common.Must2(serial.WriteUint16(writer, cmd.Port.Value())) - - idBytes := cmd.ID.Bytes() - common.Must2(writer.Write(idBytes)) - common.Must2(serial.WriteUint16(writer, 0)) // compatible with legacy alterId - common.Must2(writer.Write([]byte{byte(cmd.Level)})) - - common.Must2(writer.Write([]byte{cmd.ValidMin})) - return nil -} - -func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { - cmd := new(protocol.CommandSwitchAccount) - if len(data) == 0 { - return nil, ErrInsufficientLength - } - lenHost := int(data[0]) - if len(data) < lenHost+1 { - return nil, ErrInsufficientLength - } - if lenHost > 0 { - cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost])) - } - portStart := 1 + lenHost - if len(data) < portStart+2 { - return nil, ErrInsufficientLength - } - cmd.Port = net.PortFromBytes(data[portStart : portStart+2]) - idStart := portStart + 2 - if len(data) < idStart+16 { - return nil, ErrInsufficientLength - } - cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) - levelStart := idStart + 16 + 2 - if len(data) < levelStart+1 { - return nil, ErrInsufficientLength - } - cmd.Level = uint32(data[levelStart]) - timeStart := levelStart + 1 - if len(data) < timeStart+1 { - return nil, ErrInsufficientLength - } - cmd.ValidMin = data[timeStart] - return cmd, nil -} diff --git a/proxy/vmess/encoding/commands_test.go b/proxy/vmess/encoding/commands_test.go deleted file mode 100644 index c5415959..00000000 --- a/proxy/vmess/encoding/commands_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package encoding_test - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/assert" - "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/buf" - "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/common/uuid" - . "github.com/xtls/xray-core/proxy/vmess/encoding" -) - -func TestSwitchAccount(t *testing.T) { - sa := &protocol.CommandSwitchAccount{ - Port: 1234, - ID: uuid.New(), - Level: 128, - ValidMin: 16, - } - - buffer := buf.New() - common.Must(MarshalCommand(sa, buffer)) - - cmd, err := UnmarshalCommand(1, buffer.BytesFrom(2)) - common.Must(err) - - sa2, ok := cmd.(*protocol.CommandSwitchAccount) - if !ok { - t.Fatal("failed to convert command to CommandSwitchAccount") - } - if r := cmp.Diff(sa2, sa); r != "" { - t.Error(r) - } -} - -func TestSwitchAccountBugOffByOne(t *testing.T) { - sa := &protocol.CommandSwitchAccount{ - Port: 1234, - ID: uuid.New(), - Level: 128, - ValidMin: 16, - } - - buffer := buf.New() - csaf := CommandSwitchAccountFactory{} - common.Must(csaf.Marshal(sa, buffer)) - - Payload := buffer.Bytes() - - cmd, err := csaf.Unmarshal(Payload[:len(Payload)-1]) - assert.Error(t, err) - assert.Nil(t, cmd) -} diff --git a/proxy/vmess/inbound/config.pb.go b/proxy/vmess/inbound/config.pb.go index 4aa259e8..b713d691 100644 --- a/proxy/vmess/inbound/config.pb.go +++ b/proxy/vmess/inbound/config.pb.go @@ -118,7 +118,6 @@ type Config struct { User []*protocol.User `protobuf:"bytes,1,rep,name=user,proto3" json:"user,omitempty"` Default *DefaultConfig `protobuf:"bytes,2,opt,name=default,proto3" json:"default,omitempty"` - Detour *DetourConfig `protobuf:"bytes,3,opt,name=detour,proto3" json:"detour,omitempty"` // 4 is for legacy setting } func (x *Config) Reset() { @@ -165,13 +164,6 @@ func (x *Config) GetDefault() *DefaultConfig { return nil } -func (x *Config) GetDetour() *DetourConfig { - if x != nil { - return x.Detour - } - return nil -} - var File_proxy_vmess_inbound_config_proto protoreflect.FileDescriptor var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{ @@ -185,26 +177,21 @@ var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x25, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, - 0xbb, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, - 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x3e, 0x0a, - 0x06, 0x64, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, - 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x64, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x42, 0x6a, 0x0a, - 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, - 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, - 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, - 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, - 0x18, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, - 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x7b, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x6a, 0x0a, 0x1c, + 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, + 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2d, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, + 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, + 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x18, + 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, 0x73, + 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -229,12 +216,11 @@ var file_proxy_vmess_inbound_config_proto_goTypes = []any{ var file_proxy_vmess_inbound_config_proto_depIdxs = []int32{ 3, // 0: xray.proxy.vmess.inbound.Config.user:type_name -> xray.common.protocol.User 1, // 1: xray.proxy.vmess.inbound.Config.default:type_name -> xray.proxy.vmess.inbound.DefaultConfig - 0, // 2: xray.proxy.vmess.inbound.Config.detour:type_name -> xray.proxy.vmess.inbound.DetourConfig - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_proxy_vmess_inbound_config_proto_init() } diff --git a/proxy/vmess/inbound/config.proto b/proxy/vmess/inbound/config.proto index 7da1d581..89311ddf 100644 --- a/proxy/vmess/inbound/config.proto +++ b/proxy/vmess/inbound/config.proto @@ -19,6 +19,4 @@ message DefaultConfig { message Config { repeated xray.common.protocol.User user = 1; DefaultConfig default = 2; - DetourConfig detour = 3; - // 4 is for legacy setting } diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 28b560d8..7975551b 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -106,7 +106,6 @@ type Handler struct { inboundHandlerManager feature_inbound.Manager clients *vmess.TimedUserValidator usersByEmail *userByEmail - detours *DetourConfig sessionHistory *encoding.SessionHistory } @@ -117,7 +116,6 @@ func New(ctx context.Context, config *Config) (*Handler, error) { policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager), clients: vmess.NewTimedUserValidator(), - detours: config.Detour, usersByEmail: newUserByEmail(config.GetDefaultValue()), sessionHistory: encoding.NewSessionHistory(), } @@ -323,38 +321,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s return nil } +// Stub command generator func (h *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand { - if h.detours != nil { - tag := h.detours.To - if h.inboundHandlerManager != nil { - handler, err := h.inboundHandlerManager.GetHandler(ctx, tag) - if err != nil { - errors.LogWarningInner(ctx, err, "failed to get detour handler: ", tag) - return nil - } - proxyHandler, port, availableMin := handler.GetRandomInboundProxy() - inboundHandler, ok := proxyHandler.(*Handler) - if ok && inboundHandler != nil { - if availableMin > 255 { - availableMin = 255 - } - - errors.LogDebug(ctx, "pick detour handler for port ", port, " for ", availableMin, " minutes.") - user := inboundHandler.GetOrGenerateUser(request.User.Email) - if user == nil { - return nil - } - account := user.Account.(*vmess.MemoryAccount) - return &protocol.CommandSwitchAccount{ - Port: port, - ID: account.ID.UUID(), - Level: user.Level, - ValidMin: byte(availableMin), - } - } - } - } - return nil } diff --git a/proxy/vmess/outbound/command.go b/proxy/vmess/outbound/command.go index 2d4747dc..c284bfb6 100644 --- a/proxy/vmess/outbound/command.go +++ b/proxy/vmess/outbound/command.go @@ -1,41 +1,14 @@ package outbound import ( - "time" - "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/proxy/vmess" ) -func (h *Handler) handleSwitchAccount(cmd *protocol.CommandSwitchAccount) { - rawAccount := &vmess.Account{ - Id: cmd.ID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AUTO, - }, - } - - account, err := rawAccount.AsAccount() - common.Must(err) - user := &protocol.MemoryUser{ - Email: "", - Level: cmd.Level, - Account: account, - } - dest := net.TCPDestination(cmd.Host, cmd.Port) - until := time.Now().Add(time.Duration(cmd.ValidMin) * time.Minute) - h.serverList.AddServer(protocol.NewServerSpec(dest, protocol.BeforeTime(until), user)) -} - +// As a stub command consumer. func (h *Handler) handleCommand(dest net.Destination, cmd protocol.ResponseCommand) { - switch typedCommand := cmd.(type) { - case *protocol.CommandSwitchAccount: - if typedCommand.Host == nil { - typedCommand.Host = dest.Address - } - h.handleSwitchAccount(typedCommand) + switch cmd.(type) { default: } } diff --git a/proxy/vmess/outbound/config.pb.go b/proxy/vmess/outbound/config.pb.go index 0bc4d925..c5a8a185 100644 --- a/proxy/vmess/outbound/config.pb.go +++ b/proxy/vmess/outbound/config.pb.go @@ -26,7 +26,7 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Receiver []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=Receiver,proto3" json:"Receiver,omitempty"` + Receiver *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=Receiver,proto3" json:"Receiver,omitempty"` } func (x *Config) Reset() { @@ -59,7 +59,7 @@ func (*Config) Descriptor() ([]byte, []int) { return file_proxy_vmess_outbound_config_proto_rawDescGZIP(), []int{0} } -func (x *Config) GetReceiver() []*protocol.ServerEndpoint { +func (x *Config) GetReceiver() *protocol.ServerEndpoint { if x != nil { return x.Receiver } @@ -76,7 +76,7 @@ var file_proxy_vmess_outbound_config_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x08, 0x52, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x42, 0x6d, 0x0a, diff --git a/proxy/vmess/outbound/config.proto b/proxy/vmess/outbound/config.proto index 2a827158..fe3041c6 100644 --- a/proxy/vmess/outbound/config.proto +++ b/proxy/vmess/outbound/config.proto @@ -9,5 +9,5 @@ option java_multiple_files = true; import "common/protocol/server_spec.proto"; message Config { - repeated xray.common.protocol.ServerEndpoint Receiver = 1; + xray.common.protocol.ServerEndpoint Receiver = 1; } diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 27079e03..4850e728 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -29,27 +29,24 @@ import ( // Handler is an outbound connection handler for VMess protocol. type Handler struct { - serverList *protocol.ServerList - serverPicker protocol.ServerPicker + server *protocol.ServerSpec policyManager policy.Manager cone bool } // New creates a new VMess outbound handler. func New(ctx context.Context, config *Config) (*Handler, error) { - serverList := protocol.NewServerList() - for _, rec := range config.Receiver { - s, err := protocol.NewServerSpecFromPB(rec) - if err != nil { - return nil, errors.New("failed to parse server spec").Base(err) - } - serverList.AddServer(s) + if config.Receiver == nil { + return nil, errors.New(`no vnext found`) + } + server, err := protocol.NewServerSpecFromPB(config.Receiver) + if err != nil { + return nil, errors.New("failed to get server spec").Base(err) } v := core.MustFromContext(ctx) handler := &Handler{ - serverList: serverList, - serverPicker: protocol.NewRoundRobinServerPicker(serverList), + server: server, policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager), cone: ctx.Value("cone").(bool), } @@ -67,11 +64,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte ob.Name = "vmess" ob.CanSpliceCopy = 3 - var rec *protocol.ServerSpec + rec := h.server var conn stat.Connection + err := retry.ExponentialBackoff(5, 200).On(func() error { - rec = h.serverPicker.PickServer() - rawConn, err := dialer.Dial(ctx, rec.Destination()) + rawConn, err := dialer.Dial(ctx, rec.Destination) if err != nil { return err } @@ -85,7 +82,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte defer conn.Close() target := ob.Target - errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr()) + errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination.NetAddr()) command := protocol.RequestCommandTCP if target.Network == net.Network_UDP { @@ -95,7 +92,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte command = protocol.RequestCommandMux } - user := rec.PickUser() + user := rec.User request := &protocol.RequestHeader{ Version: encoding.Version, User: user, @@ -202,7 +199,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte if err != nil { return errors.New("failed to read header").Base(err) } - h.handleCommand(rec.Destination(), header.Command) + h.handleCommand(rec.Destination, header.Command) bodyReader, err := session.DecodeResponseBody(request, reader) if err != nil { diff --git a/testing/scenarios/command_test.go b/testing/scenarios/command_test.go index 8ee9e4bf..7afe47d0 100644 --- a/testing/scenarios/command_test.go +++ b/testing/scenarios/command_test.go @@ -423,20 +423,16 @@ func TestCommanderAddRemoveUser(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: u2.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: u2.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -600,20 +596,16 @@ func TestCommanderStats(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), diff --git a/testing/scenarios/dokodemo_test.go b/testing/scenarios/dokodemo_test.go index f74fb4bd..81234cd1 100644 --- a/testing/scenarios/dokodemo_test.go +++ b/testing/scenarios/dokodemo_test.go @@ -94,17 +94,13 @@ func TestDokodemoTCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -190,17 +186,13 @@ func TestDokodemoUDP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), diff --git a/testing/scenarios/feature_test.go b/testing/scenarios/feature_test.go index 6fe0d850..e668587e 100644 --- a/testing/scenarios/feature_test.go +++ b/testing/scenarios/feature_test.go @@ -170,17 +170,13 @@ func TestProxy(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: serverUserID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: serverUserID.String(), + }), }, }, }), @@ -193,17 +189,13 @@ func TestProxy(t *testing.T) { { Tag: "proxy", ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(proxyPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: proxyUserID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(proxyPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: proxyUserID.String(), + }), }, }, }), @@ -308,17 +300,13 @@ func TestProxyOverKCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: serverUserID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: serverUserID.String(), + }), }, }, }), @@ -334,17 +322,13 @@ func TestProxyOverKCP(t *testing.T) { { Tag: "proxy", ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(proxyPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: proxyUserID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(proxyPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: proxyUserID.String(), + }), }, }, }), @@ -685,20 +669,16 @@ func TestDialXray(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), diff --git a/testing/scenarios/policy_test.go b/testing/scenarios/policy_test.go index 644b313c..c5d68a50 100644 --- a/testing/scenarios/policy_test.go +++ b/testing/scenarios/policy_test.go @@ -119,20 +119,16 @@ func TestVMessClosing(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -223,20 +219,16 @@ func TestZeroBuffer(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), diff --git a/testing/scenarios/reverse_test.go b/testing/scenarios/reverse_test.go index f7e2e7af..1e41d2a7 100644 --- a/testing/scenarios/reverse_test.go +++ b/testing/scenarios/reverse_test.go @@ -155,20 +155,16 @@ func TestReverseProxy(t *testing.T) { { Tag: "reverse", ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(reversePort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(reversePort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -348,20 +344,16 @@ func TestReverseProxyLongRunning(t *testing.T) { { Tag: "reverse", ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(reversePort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(reversePort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), diff --git a/testing/scenarios/shadowsocks_test.go b/testing/scenarios/shadowsocks_test.go index f358cbe2..2fdd6204 100644 --- a/testing/scenarios/shadowsocks_test.go +++ b/testing/scenarios/shadowsocks_test.go @@ -75,15 +75,11 @@ func TestShadowsocksChaCha20Poly1305TCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: account, - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: account, }, }, }), @@ -171,15 +167,11 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: account, - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: account, }, }, }), @@ -268,15 +260,11 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: account, - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: account, }, }, }), @@ -370,15 +358,11 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) { }, }), ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: account, - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: account, }, }, }), @@ -455,15 +439,11 @@ func TestShadowsocksNone(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: account, - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: account, }, }, }), diff --git a/testing/scenarios/socks_test.go b/testing/scenarios/socks_test.go index 83ebebc3..a139e5fe 100644 --- a/testing/scenarios/socks_test.go +++ b/testing/scenarios/socks_test.go @@ -73,18 +73,14 @@ func TestSocksBridgeTCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&socks.Account{ - Username: "Test Account", - Password: "Test Password", - }), - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&socks.Account{ + Username: "Test Account", + Password: "Test Password", + }), }, }, }), @@ -152,18 +148,14 @@ func TestSocksWithHttpRequest(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&http.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&http.Account{ - Username: "Test Account", - Password: "Test Password", - }), - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&http.Account{ + Username: "Test Account", + Password: "Test Password", + }), }, }, }), @@ -256,18 +248,14 @@ func TestSocksBridageUDP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&socks.Account{ - Username: "Test Account", - Password: "Test Password", - }), - }, - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&socks.Account{ + Username: "Test Account", + Password: "Test Password", + }), }, }, }), @@ -375,11 +363,9 @@ func TestSocksBridageUDPWithRouting(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{ - Server: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - }, + Server: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), }, }), }, diff --git a/testing/scenarios/tls_test.go b/testing/scenarios/tls_test.go index bf0d2c8a..250e5d47 100644 --- a/testing/scenarios/tls_test.go +++ b/testing/scenarios/tls_test.go @@ -89,17 +89,13 @@ func TestSimpleTLSConnection(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -204,17 +200,13 @@ func TestAutoIssuingCertificate(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -309,17 +301,13 @@ func TestTLSOverKCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -409,17 +397,13 @@ func TestTLSOverWebSocket(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -525,17 +509,13 @@ func TestGRPC(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -641,17 +621,13 @@ func TestGRPCMultiMode(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -752,17 +728,13 @@ func TestSimpleTLSConnectionPinned(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -854,17 +826,13 @@ func TestSimpleTLSConnectionPinnedWrongCert(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -955,17 +923,13 @@ func TestUTLSConnectionPinned(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), @@ -1058,17 +1022,13 @@ func TestUTLSConnectionPinnedWrongCert(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), diff --git a/testing/scenarios/transport_test.go b/testing/scenarios/transport_test.go index bb16deee..80fd13db 100644 --- a/testing/scenarios/transport_test.go +++ b/testing/scenarios/transport_test.go @@ -85,17 +85,13 @@ func TestHTTPConnectionHeader(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + }), }, }, }), diff --git a/testing/scenarios/vless_test.go b/testing/scenarios/vless_test.go index 52a6712f..b699f497 100644 --- a/testing/scenarios/vless_test.go +++ b/testing/scenarios/vless_test.go @@ -94,17 +94,13 @@ func TestVless(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: userID.String(), - }), - }, - }, + Vnext: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: userID.String(), + }), }, }, }), @@ -199,17 +195,13 @@ func TestVlessTls(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: userID.String(), - }), - }, - }, + Vnext: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: userID.String(), + }), }, }, }), @@ -322,18 +314,14 @@ func TestVlessXtlsVision(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: userID.String(), - Flow: vless.XRV, - }), - }, - }, + Vnext: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: userID.String(), + Flow: vless.XRV, + }), }, }, }), @@ -456,18 +444,14 @@ func TestVlessXtlsVisionReality(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Vnext: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vless.Account{ - Id: userID.String(), - Flow: vless.XRV, - }), - }, - }, + Vnext: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vless.Account{ + Id: userID.String(), + Flow: vless.XRV, + }), }, }, }), diff --git a/testing/scenarios/vmess_test.go b/testing/scenarios/vmess_test.go index 012fc96c..402cf940 100644 --- a/testing/scenarios/vmess_test.go +++ b/testing/scenarios/vmess_test.go @@ -26,147 +26,6 @@ import ( "golang.org/x/sync/errgroup" ) -func TestVMessDynamicPort(t *testing.T) { - tcpServer := tcp.Server{ - MsgProcessor: xor, - } - dest, err := tcpServer.Start() - common.Must(err) - defer tcpServer.Close() - - userID := protocol.NewID(uuid.New()) - - retry := 1 - serverPort := tcp.PickPort() - for { - serverConfig := &core.Config{ - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: clog.Severity_Debug, - ErrorLogType: log.LogType_Console, - }), - }, - Inbound: []*core.InboundHandlerConfig{ - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}}, - Listen: net.NewIPOrDomain(net.LocalHostIP), - }), - ProxySettings: serial.ToTypedMessage(&inbound.Config{ - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, - Detour: &inbound.DetourConfig{ - To: "detour", - }, - }), - }, - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort + 100)}}, - Listen: net.NewIPOrDomain(net.LocalHostIP), - }), - ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ - Address: net.NewIPOrDomain(dest.Address), - Port: uint32(dest.Port), - Networks: []net.Network{net.Network_TCP}, - }), - }, - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortList: &net.PortList{ - Range: []*net.PortRange{{From: uint32(serverPort + 1), To: uint32(serverPort + 99)}}, - }, - - Listen: net.NewIPOrDomain(net.LocalHostIP), - AllocationStrategy: &proxyman.AllocationStrategy{ - Type: proxyman.AllocationStrategy_Random, - Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ - Value: 2, - }, - Refresh: &proxyman.AllocationStrategy_AllocationStrategyRefresh{ - Value: 5, - }, - }, - }), - ProxySettings: serial.ToTypedMessage(&inbound.Config{}), - Tag: "detour", - }, - }, - Outbound: []*core.OutboundHandlerConfig{ - { - ProxySettings: serial.ToTypedMessage(&freedom.Config{}), - }, - }, - } - - server, _ := InitializeServerConfig(serverConfig) - if server != nil && WaitConnAvailableWithTest(t, testTCPConn(serverPort+100, 1024, time.Second*2)) { - defer CloseServer(server) - break - } - retry += 1 - if retry > 5 { - t.Fatal("All attempts failed to start server") - } - serverPort = tcp.PickPort() - } - - clientPort := tcp.PickPort() - clientConfig := &core.Config{ - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: clog.Severity_Debug, - ErrorLogType: log.LogType_Console, - }), - }, - Inbound: []*core.InboundHandlerConfig{ - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}}, - Listen: net.NewIPOrDomain(net.LocalHostIP), - }), - ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ - Address: net.NewIPOrDomain(dest.Address), - Port: uint32(dest.Port), - Networks: []net.Network{net.Network_TCP}, - }), - }, - }, - Outbound: []*core.OutboundHandlerConfig{ - { - ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - }), - }, - }, - }, - }, - }), - }, - }, - } - - server, err := InitializeServerConfig(clientConfig) - common.Must(err) - defer CloseServer(server) - - if !WaitConnAvailableWithTest(t, testTCPConn(clientPort, 1024, time.Second*2)) { - t.Fail() - } -} - func TestVMessGCM(t *testing.T) { tcpServer := tcp.Server{ MsgProcessor: xor, @@ -232,20 +91,16 @@ func TestVMessGCM(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -334,20 +189,16 @@ func TestVMessGCMReadv(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -439,20 +290,16 @@ func TestVMessGCMUDP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -538,20 +385,16 @@ func TestVMessChacha20(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_CHACHA20_POLY1305, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_CHACHA20_POLY1305, }, - }, + }), }, }, }), @@ -638,20 +481,16 @@ func TestVMessNone(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_NONE, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_NONE, }, - }, + }), }, }, }), @@ -740,20 +579,16 @@ func TestVMessKCP(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -866,20 +701,16 @@ func TestVMessKCPLarge(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -999,20 +830,16 @@ func TestVMessGCMMux(t *testing.T) { }, }), ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -1126,20 +953,16 @@ func TestVMessGCMMuxUDP(t *testing.T) { }, }), ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + }), }, }, }), @@ -1233,20 +1056,16 @@ func TestVMessZero(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_ZERO, - }, - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_ZERO, }, - }, + }), }, }, }), @@ -1332,21 +1151,17 @@ func TestVMessGCMLengthAuth(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - TestsEnabled: "AuthenticatedLength", - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + TestsEnabled: "AuthenticatedLength", + }), }, }, }), @@ -1436,21 +1251,17 @@ func TestVMessGCMLengthAuthPlusNoTerminationSignal(t *testing.T) { Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIP), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - TestsEnabled: "AuthenticatedLength|NoTerminationSignal", - }), + Receiver: &protocol.ServerEndpoint{ + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: &protocol.User{ + Account: serial.ToTypedMessage(&vmess.Account{ + Id: userID.String(), + SecuritySettings: &protocol.SecurityConfig{ + Type: protocol.SecurityType_AES128_GCM, }, - }, + TestsEnabled: "AuthenticatedLength|NoTerminationSignal", + }), }, }, }),