From ea94d07f659a77cecf8a9cc9051012d746e6cda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 13 Sep 2021 14:50:18 +0800 Subject: [PATCH] Add domainStrategy to outbound & Add preferIPv4/6 to domainStrategy --- app/proxyman/config.pb.go | 189 ++++++++++++++++++++++--------- app/proxyman/config.proto | 10 ++ app/proxyman/outbound/handler.go | 58 +++++++++- infra/conf/xray.go | 30 +++-- 4 files changed, 223 insertions(+), 64 deletions(-) diff --git a/app/proxyman/config.pb.go b/app/proxyman/config.pb.go index d1b9b1fb..37e048ea 100644 --- a/app/proxyman/config.pb.go +++ b/app/proxyman/config.pb.go @@ -69,6 +69,64 @@ func (KnownProtocols) EnumDescriptor() ([]byte, []int) { return file_app_proxyman_config_proto_rawDescGZIP(), []int{0} } +type DomainStrategy int32 + +const ( + DomainStrategy_AS_IS DomainStrategy = 0 + DomainStrategy_USE_IP DomainStrategy = 1 + DomainStrategy_USE_IP4 DomainStrategy = 2 + DomainStrategy_USE_IP6 DomainStrategy = 3 + DomainStrategy_PREFER_IP4 DomainStrategy = 4 + DomainStrategy_PREFER_IP6 DomainStrategy = 5 +) + +// Enum value maps for DomainStrategy. +var ( + DomainStrategy_name = map[int32]string{ + 0: "AS_IS", + 1: "USE_IP", + 2: "USE_IP4", + 3: "USE_IP6", + 4: "PREFER_IP4", + 5: "PREFER_IP6", + } + DomainStrategy_value = map[string]int32{ + "AS_IS": 0, + "USE_IP": 1, + "USE_IP4": 2, + "USE_IP6": 3, + "PREFER_IP4": 4, + "PREFER_IP6": 5, + } +) + +func (x DomainStrategy) Enum() *DomainStrategy { + p := new(DomainStrategy) + *p = x + return p +} + +func (x DomainStrategy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DomainStrategy) Descriptor() protoreflect.EnumDescriptor { + return file_app_proxyman_config_proto_enumTypes[1].Descriptor() +} + +func (DomainStrategy) Type() protoreflect.EnumType { + return &file_app_proxyman_config_proto_enumTypes[1] +} + +func (x DomainStrategy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DomainStrategy.Descriptor instead. +func (DomainStrategy) EnumDescriptor() ([]byte, []int) { + return file_app_proxyman_config_proto_rawDescGZIP(), []int{1} +} + type AllocationStrategy_Type int32 const ( @@ -105,11 +163,11 @@ func (x AllocationStrategy_Type) String() string { } func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor { - return file_app_proxyman_config_proto_enumTypes[1].Descriptor() + return file_app_proxyman_config_proto_enumTypes[2].Descriptor() } func (AllocationStrategy_Type) Type() protoreflect.EnumType { - return &file_app_proxyman_config_proto_enumTypes[1] + return &file_app_proxyman_config_proto_enumTypes[2] } func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber { @@ -523,6 +581,7 @@ type SenderConfig struct { StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"` ProxySettings *internet.ProxyConfig `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"` MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"` + DomainStrategy DomainStrategy `protobuf:"varint,5,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.app.proxyman.DomainStrategy" json:"domain_strategy,omitempty"` } func (x *SenderConfig) Reset() { @@ -585,6 +644,13 @@ func (x *SenderConfig) GetMultiplexSettings() *MultiplexingConfig { return nil } +func (x *SenderConfig) GetDomainStrategy() DomainStrategy { + if x != nil { + return x.DomainStrategy + } + return DomainStrategy_AS_IS +} + type MultiplexingConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -836,7 +902,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{ 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, 0xb0, 0x02, 0x0a, + 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xfc, 0x02, 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, @@ -855,21 +921,32 @@ var file_app_proxyman_config_proto_rawDesc = []byte{ 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, 0x22, - 0x50, 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, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, - 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 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, + 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x4a, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, + 0x67, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0x50, 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, 0x0d, + 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2a, 0x23, 0x0a, + 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, + 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c, 0x53, + 0x10, 0x01, 0x2a, 0x61, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, + 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, + 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, + 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x5f, + 0x49, 0x50, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x5f, + 0x49, 0x50, 0x36, 0x10, 0x05, 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 ( @@ -884,48 +961,50 @@ 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, 2) +var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_app_proxyman_config_proto_goTypes = []interface{}{ (KnownProtocols)(0), // 0: xray.app.proxyman.KnownProtocols - (AllocationStrategy_Type)(0), // 1: xray.app.proxyman.AllocationStrategy.Type - (*InboundConfig)(nil), // 2: xray.app.proxyman.InboundConfig - (*AllocationStrategy)(nil), // 3: xray.app.proxyman.AllocationStrategy - (*SniffingConfig)(nil), // 4: xray.app.proxyman.SniffingConfig - (*ReceiverConfig)(nil), // 5: xray.app.proxyman.ReceiverConfig - (*InboundHandlerConfig)(nil), // 6: xray.app.proxyman.InboundHandlerConfig - (*OutboundConfig)(nil), // 7: xray.app.proxyman.OutboundConfig - (*SenderConfig)(nil), // 8: xray.app.proxyman.SenderConfig - (*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig - (*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency - (*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh - (*net.PortRange)(nil), // 12: xray.common.net.PortRange - (*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain - (*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig - (*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage - (*internet.ProxyConfig)(nil), // 16: xray.transport.internet.ProxyConfig + (DomainStrategy)(0), // 1: xray.app.proxyman.DomainStrategy + (AllocationStrategy_Type)(0), // 2: xray.app.proxyman.AllocationStrategy.Type + (*InboundConfig)(nil), // 3: xray.app.proxyman.InboundConfig + (*AllocationStrategy)(nil), // 4: xray.app.proxyman.AllocationStrategy + (*SniffingConfig)(nil), // 5: xray.app.proxyman.SniffingConfig + (*ReceiverConfig)(nil), // 6: xray.app.proxyman.ReceiverConfig + (*InboundHandlerConfig)(nil), // 7: xray.app.proxyman.InboundHandlerConfig + (*OutboundConfig)(nil), // 8: xray.app.proxyman.OutboundConfig + (*SenderConfig)(nil), // 9: xray.app.proxyman.SenderConfig + (*MultiplexingConfig)(nil), // 10: xray.app.proxyman.MultiplexingConfig + (*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency + (*AllocationStrategy_AllocationStrategyRefresh)(nil), // 12: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh + (*net.PortRange)(nil), // 13: xray.common.net.PortRange + (*net.IPOrDomain)(nil), // 14: xray.common.net.IPOrDomain + (*internet.StreamConfig)(nil), // 15: xray.transport.internet.StreamConfig + (*serial.TypedMessage)(nil), // 16: xray.common.serial.TypedMessage + (*internet.ProxyConfig)(nil), // 17: xray.transport.internet.ProxyConfig } var file_app_proxyman_config_proto_depIdxs = []int32{ - 1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type - 10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency - 11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh - 12, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange - 13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain - 3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy - 14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 2, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type + 11, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency + 12, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh + 13, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange + 14, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain + 4, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy + 15, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig 0, // 7: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols - 4, // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig - 15, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage - 15, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage - 13, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain - 14, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig - 16, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig - 9, // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig - 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 + 5, // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig + 16, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage + 16, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage + 14, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain + 15, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 17, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig + 10, // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig + 1, // 15: xray.app.proxyman.SenderConfig.domain_strategy:type_name -> xray.app.proxyman.DomainStrategy + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_app_proxyman_config_proto_init() } @@ -1060,7 +1139,7 @@ func file_app_proxyman_config_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_app_proxyman_config_proto_rawDesc, - NumEnums: 2, + NumEnums: 3, NumMessages: 10, NumExtensions: 0, NumServices: 0, diff --git a/app/proxyman/config.proto b/app/proxyman/config.proto index 67bbf360..0587b21f 100644 --- a/app/proxyman/config.proto +++ b/app/proxyman/config.proto @@ -88,12 +88,22 @@ message InboundHandlerConfig { message OutboundConfig {} +enum DomainStrategy { + AS_IS = 0; + USE_IP = 1; + USE_IP4 = 2; + USE_IP6 = 3; + PREFER_IP4 = 4; + PREFER_IP6 = 5; +} + message SenderConfig { // Send traffic through the given IP. Only IP is allowed. xray.common.net.IPOrDomain via = 1; xray.transport.internet.StreamConfig stream_settings = 2; xray.transport.internet.ProxyConfig proxy_settings = 3; MultiplexingConfig multiplex_settings = 4; + DomainStrategy domain_strategy = 5; } message MultiplexingConfig { diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index d5cc59f1..19c87a67 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -2,7 +2,7 @@ package outbound import ( "context" - + "github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/app/proxyman" @@ -54,6 +54,7 @@ type Handler struct { streamSettings *internet.MemoryStreamConfig proxy proxy.Outbound outboundManager outbound.Manager + dnsClient dns.Client mux *mux.ClientManager uplinkCounter stats.Counter downlinkCounter stats.Counter @@ -66,6 +67,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou h := &Handler{ tag: config.Tag, outboundManager: v.GetFeature(outbound.ManagerType()).(outbound.Manager), + dnsClient: v.GetFeature(dns.ClientType()).(dns.Client), uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, } @@ -140,7 +142,47 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) { common.Interrupt(link.Writer) } } else { - if err := h.proxy.Process(ctx, link, h); err != nil { + outbound := session.OutboundFromContext(ctx) + destination := outbound.Target + var domainString string + if destination.Address.Family().IsDomain() { + domainString = destination.Address.Domain() + } else if outbound.RouteTarget.Address != nil && outbound.RouteTarget.Address.Family().IsDomain() { + domainString = outbound.RouteTarget.Address.Domain() + } else { + domainString = "" + } + + if h.senderSettings != nil && h.senderSettings.DomainStrategy != proxyman.DomainStrategy_AS_IS && domainString != "" { + var ips []net.IP + var err error + + option := dns.IPOption{ + IPv4Enable: true, + IPv6Enable: true, + FakeEnable: false, + } + + switch h.senderSettings.DomainStrategy { + case proxyman.DomainStrategy_USE_IP4: + option.IPv6Enable = false + case proxyman.DomainStrategy_USE_IP6: + option.IPv4Enable = false + } + ips, err = h.dnsClient.LookupIP(domainString, option) + if err == nil { + switch h.senderSettings.DomainStrategy { + case proxyman.DomainStrategy_PREFER_IP4: + ips = reorderAddresses(ips, false) + case proxyman.DomainStrategy_PREFER_IP6: + ips = reorderAddresses(ips, true) + } + destination.Address = net.IPAddress(ips[0]) + outbound.Target = destination + } + } + err := h.proxy.Process(ctx, link, h) + if err != nil { // Ensure outbound ray is properly closed. newError("failed to process outbound traffic").Base(err).WriteToLog(session.ExportIDToError(ctx)) common.Interrupt(link.Writer) @@ -151,6 +193,18 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) { } } +func reorderAddresses(ips []net.IP, preferIPv6 bool) []net.IP { + var result []net.IP + for i := 0; i < 2; i++ { + for _, ip := range ips { + if (preferIPv6 == (i == 0)) == (ip.To4() == nil) { + result = append(result, ip) + } + } + } + return result +} + // Address implements internet.Dialer. func (h *Handler) Address() net.Address { if h.senderSettings == nil || h.senderSettings.Via == nil { diff --git a/infra/conf/xray.go b/infra/conf/xray.go index eaed946d..2a0506db 100644 --- a/infra/conf/xray.go +++ b/infra/conf/xray.go @@ -269,13 +269,14 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) { } type OutboundDetourConfig struct { - Protocol string `json:"protocol"` - SendThrough *Address `json:"sendThrough"` - Tag string `json:"tag"` - Settings *json.RawMessage `json:"settings"` - StreamSetting *StreamConfig `json:"streamSettings"` - ProxySettings *ProxyConfig `json:"proxySettings"` - MuxSettings *MuxConfig `json:"mux"` + Protocol string `json:"protocol"` + SendThrough *Address `json:"sendThrough"` + Tag string `json:"tag"` + Settings *json.RawMessage `json:"settings"` + StreamSetting *StreamConfig `json:"streamSettings"` + ProxySettings *ProxyConfig `json:"proxySettings"` + MuxSettings *MuxConfig `json:"mux"` + DomainStrategy string `json:"domainStrategy"` } func (c *OutboundDetourConfig) checkChainProxyConfig() error { @@ -295,6 +296,21 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) { return nil, err } + switch c.DomainStrategy { + case "UseIP": + senderSettings.DomainStrategy = proxyman.DomainStrategy_USE_IP + case "UseIPv4": + senderSettings.DomainStrategy = proxyman.DomainStrategy_USE_IP4 + case "UseIPv6": + senderSettings.DomainStrategy = proxyman.DomainStrategy_USE_IP6 + case "PreferIPv4": + senderSettings.DomainStrategy = proxyman.DomainStrategy_PREFER_IP4 + case "PreferIPv6": + senderSettings.DomainStrategy = proxyman.DomainStrategy_PREFER_IP6 + default: + senderSettings.DomainStrategy = proxyman.DomainStrategy_AS_IS + } + if c.SendThrough != nil { address := c.SendThrough if address.Family().IsDomain() {