Compare commits

...

3 Commits

Author SHA1 Message Date
世界
f6c15a09b3 Fix udp 2023-04-25 18:12:16 +08:00
世界
0a099d972b Fix bad type cast in dispatcher 2023-04-25 13:50:25 +08:00
世界
837d7d885f Add smux support 2023-04-24 14:11:54 +08:00
12 changed files with 341 additions and 67 deletions

View File

@@ -30,10 +30,15 @@ var errSniffingTimeout = newError("timeout on sniffing")
type cachedReader struct {
sync.Mutex
reader *pipe.Reader
reader timeoutReader
cache buf.MultiBuffer
}
type timeoutReader interface {
buf.Reader
buf.TimeoutReader
}
func (r *cachedReader) Cache(b *buf.Buffer) {
mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100)
r.Lock()
@@ -84,7 +89,7 @@ func (r *cachedReader) Interrupt() {
r.cache = buf.ReleaseMulti(r.cache)
}
r.Unlock()
r.reader.Interrupt()
common.Interrupt(r.reader)
}
// DefaultDispatcher is a default implementation of Dispatcher.
@@ -345,7 +350,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
d.routedDispatch(ctx, outbound, destination)
} else {
cReader := &cachedReader{
reader: outbound.Reader.(*pipe.Reader),
reader: outbound.Reader.(timeoutReader),
}
outbound.Reader = cReader
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)

View File

@@ -524,6 +524,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"`
SmuxSettings *SingMultiplexConfig `protobuf:"bytes,5,opt,name=smux_settings,json=smuxSettings,proto3" json:"smux_settings,omitempty"`
}
func (x *SenderConfig) Reset() {
@@ -586,6 +587,13 @@ func (x *SenderConfig) GetMultiplexSettings() *MultiplexingConfig {
return nil
}
func (x *SenderConfig) GetSmuxSettings() *SingMultiplexConfig {
if x != nil {
return x.SmuxSettings
}
return nil
}
type MultiplexingConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -661,6 +669,93 @@ func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
return ""
}
type SingMultiplexConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
Protocol string `protobuf:"bytes,2,opt,name=protocol,proto3" json:"protocol,omitempty"`
MaxConnections int32 `protobuf:"varint,3,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"`
MinStreams int32 `protobuf:"varint,4,opt,name=min_streams,json=minStreams,proto3" json:"min_streams,omitempty"`
MaxStreams int32 `protobuf:"varint,5,opt,name=max_streams,json=maxStreams,proto3" json:"max_streams,omitempty"`
Padding bool `protobuf:"varint,6,opt,name=padding,proto3" json:"padding,omitempty"`
}
func (x *SingMultiplexConfig) Reset() {
*x = SingMultiplexConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_app_proxyman_config_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SingMultiplexConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SingMultiplexConfig) ProtoMessage() {}
func (x *SingMultiplexConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SingMultiplexConfig.ProtoReflect.Descriptor instead.
func (*SingMultiplexConfig) Descriptor() ([]byte, []int) {
return file_app_proxyman_config_proto_rawDescGZIP(), []int{8}
}
func (x *SingMultiplexConfig) GetEnabled() bool {
if x != nil {
return x.Enabled
}
return false
}
func (x *SingMultiplexConfig) GetProtocol() string {
if x != nil {
return x.Protocol
}
return ""
}
func (x *SingMultiplexConfig) GetMaxConnections() int32 {
if x != nil {
return x.MaxConnections
}
return 0
}
func (x *SingMultiplexConfig) GetMinStreams() int32 {
if x != nil {
return x.MinStreams
}
return 0
}
func (x *SingMultiplexConfig) GetMaxStreams() int32 {
if x != nil {
return x.MaxStreams
}
return 0
}
func (x *SingMultiplexConfig) GetPadding() bool {
if x != nil {
return x.Padding
}
return false
}
type AllocationStrategy_AllocationStrategyConcurrency struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -672,7 +767,7 @@ type AllocationStrategy_AllocationStrategyConcurrency struct {
func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() {
*x = AllocationStrategy_AllocationStrategyConcurrency{}
if protoimpl.UnsafeEnabled {
mi := &file_app_proxyman_config_proto_msgTypes[8]
mi := &file_app_proxyman_config_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -685,7 +780,7 @@ func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string {
func (*AllocationStrategy_AllocationStrategyConcurrency) ProtoMessage() {}
func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[8]
mi := &file_app_proxyman_config_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -719,7 +814,7 @@ type AllocationStrategy_AllocationStrategyRefresh struct {
func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() {
*x = AllocationStrategy_AllocationStrategyRefresh{}
if protoimpl.UnsafeEnabled {
mi := &file_app_proxyman_config_proto_msgTypes[9]
mi := &file_app_proxyman_config_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -732,7 +827,7 @@ func (x *AllocationStrategy_AllocationStrategyRefresh) String() string {
func (*AllocationStrategy_AllocationStrategyRefresh) ProtoMessage() {}
func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[9]
mi := &file_app_proxyman_config_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -855,7 +950,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
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, 0x0c, 0x53, 0x65,
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xfd, 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, 0x72, 0x44, 0x6f,
@@ -874,18 +969,36 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
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, 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, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50,
0x34, 0x34, 0x33, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74,
0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0d,
0x73, 0x6d, 0x75, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x4d, 0x75, 0x6c, 0x74,
0x69, 0x70, 0x6c, 0x65, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x73, 0x6d, 0x75,
0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 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, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33,
0x22, 0xd0, 0x01, 0x0a, 0x13, 0x53, 0x69, 0x6e, 0x67, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
0x65, 0x78, 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, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x27,
0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x73,
0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x69,
0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d,
0x61, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64,
0x64, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64,
0x69, 0x6e, 0x67, 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,
@@ -909,7 +1022,7 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte {
}
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_app_proxyman_config_proto_goTypes = []interface{}{
(KnownProtocols)(0), // 0: xray.app.proxyman.KnownProtocols
(AllocationStrategy_Type)(0), // 1: xray.app.proxyman.AllocationStrategy.Type
@@ -921,35 +1034,37 @@ var file_app_proxyman_config_proto_goTypes = []interface{}{
(*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.PortList)(nil), // 12: xray.common.net.PortList
(*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
(*SingMultiplexConfig)(nil), // 10: xray.app.proxyman.SingMultiplexConfig
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 12: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
(*net.PortList)(nil), // 13: xray.common.net.PortList
(*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_list:type_name -> xray.common.net.PortList
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
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_list:type_name -> xray.common.net.PortList
14, // 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
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
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
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
10, // 15: xray.app.proxyman.SenderConfig.smux_settings:type_name -> xray.app.proxyman.SingMultiplexConfig
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() }
@@ -1055,7 +1170,7 @@ func file_app_proxyman_config_proto_init() {
}
}
file_app_proxyman_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy_AllocationStrategyConcurrency); i {
switch v := v.(*SingMultiplexConfig); i {
case 0:
return &v.state
case 1:
@@ -1067,6 +1182,18 @@ func file_app_proxyman_config_proto_init() {
}
}
file_app_proxyman_config_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy_AllocationStrategyConcurrency); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy_AllocationStrategyRefresh); i {
case 0:
return &v.state
@@ -1085,7 +1212,7 @@ func file_app_proxyman_config_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
NumEnums: 2,
NumMessages: 10,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -91,6 +91,7 @@ message SenderConfig {
xray.transport.internet.StreamConfig stream_settings = 2;
xray.transport.internet.ProxyConfig proxy_settings = 3;
MultiplexingConfig multiplex_settings = 4;
SingMultiplexConfig smux_settings = 5;
}
message MultiplexingConfig {
@@ -103,3 +104,12 @@ message MultiplexingConfig {
// "reject" (default), "allow" or "skip".
string xudpProxyUDP443 = 4;
}
message SingMultiplexConfig {
bool enabled = 1;
string protocol = 2;
int32 max_connections = 3;
int32 min_streams = 4;
int32 max_streams = 5;
bool padding = 6;
}

View File

@@ -6,12 +6,15 @@ import (
"io"
"os"
sing_mux "github.com/sagernet/sing-mux"
sing_net "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/policy"
@@ -58,6 +61,8 @@ type Handler struct {
outboundManager outbound.Manager
mux *mux.ClientManager
xudp *mux.ClientManager
smux *sing_mux.Client
udp443 string
uplinkCounter stats.Counter
downlinkCounter stats.Counter
@@ -154,6 +159,21 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
h.udp443 = config.XudpProxyUDP443
}
}
if h.senderSettings != nil && h.senderSettings.SmuxSettings != nil {
if config := h.senderSettings.SmuxSettings; config.Enabled {
h.smux, err = sing_mux.NewClient(sing_mux.Options{
Dialer: singbridge.NewOutboundDialer(proxyHandler, h),
Protocol: config.Protocol,
MaxConnections: int(config.MaxConnections),
MinStreams: int(config.MinStreams),
MaxStreams: int(config.MaxStreams),
Padding: config.Padding,
})
if err != nil {
return nil, newError("failed to create sing mux client").Base(err)
}
}
}
h.proxy = proxyHandler
return h, nil
@@ -197,6 +217,34 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
return
}
}
if h.smux != nil {
test := func(err error) {
if err != nil {
err := newError("failed to process mux outbound traffic").Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err)
err.WriteToLog(session.ExportIDToError(ctx))
common.Interrupt(link.Writer)
}
}
inbound := session.InboundFromContext(ctx)
outbound := session.OutboundFromContext(ctx)
if outbound.Target.Network == net.Network_TCP {
conn, err := h.smux.DialContext(ctx, sing_net.NetworkTCP, singbridge.ToSocksaddr(outbound.Target))
if err != nil {
test(err)
return
}
test(singbridge.CopyConn(ctx, inbound.Conn, link, conn))
} else {
packetConn, err := h.smux.ListenPacket(ctx, singbridge.ToSocksaddr(outbound.Target))
if err != nil {
test(err)
return
}
test(singbridge.CopyPacketConn(ctx, inbound.Conn, link, outbound.Target, packetConn))
}
return
}
out:
err := h.proxy.Process(ctx, link, h)
if err != nil {

View File

@@ -7,7 +7,7 @@ import (
"github.com/xtls/xray-core/common/errors"
)
func readOneUDP(r io.Reader) (*Buffer, error) {
func ReadOneUDP(r io.Reader) (*Buffer, error) {
b := New()
for i := 0; i < 64; i++ {
_, err := b.ReadFrom(r)
@@ -166,7 +166,7 @@ type PacketReader struct {
// ReadMultiBuffer implements Reader.
func (r *PacketReader) ReadMultiBuffer() (MultiBuffer, error) {
b, err := readOneUDP(r.Reader)
b, err := ReadOneUDP(r.Reader)
if err != nil {
return nil, err
}

View File

@@ -4,13 +4,17 @@ import (
"context"
"io"
sing_mux "github.com/sagernet/sing-mux"
"github.com/sagernet/sing/common/metadata"
"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/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport"
@@ -38,6 +42,14 @@ func (s *Server) Type() interface{} {
// Dispatch implements routing.Dispatcher
func (s *Server) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
if dest.Address != muxCoolAddress {
if dest.Address.Family() == net.AddressFamilyDomain && dest.Address.Domain() == sing_mux.Destination.Fqdn {
opts := pipe.OptionsFromContext(ctx)
uplinkReader, uplinkWriter := pipe.New(opts...)
downlinkReader, downlinkWriter := pipe.New(opts...)
conn := cnc.NewConnection(cnc.ConnectionInputMulti(downlinkWriter), cnc.ConnectionOutputMulti(uplinkReader))
go sing_mux.HandleConnection(ctx, singbridge.NewDispatcher(s.dispatcher, newError), singbridge.NewLogger(newError), conn, metadata.Metadata{Destination: singbridge.ToSocksaddr(dest)})
return &transport.Link{Reader: downlinkReader, Writer: uplinkWriter}, nil
}
return s.dispatcher.Dispatch(ctx, dest)
}
@@ -59,6 +71,10 @@ func (s *Server) Dispatch(ctx context.Context, dest net.Destination) (*transport
// DispatchLink implements routing.Dispatcher
func (s *Server) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
if dest.Address != muxCoolAddress {
if dest.Address.Family() == net.AddressFamilyDomain && dest.Address.Domain() == sing_mux.Destination.Fqdn {
conn := cnc.NewConnection(cnc.ConnectionInputMulti(link.Writer), cnc.ConnectionOutputMulti(link.Reader))
return sing_mux.HandleConnection(ctx, singbridge.NewDispatcher(s.dispatcher, newError), singbridge.NewLogger(newError), conn, metadata.Metadata{Destination: singbridge.ToSocksaddr(dest)})
}
return s.dispatcher.DispatchLink(ctx, dest, link)
}
_, err := NewServerWorker(ctx, s.dispatcher, link)

View File

@@ -2,11 +2,10 @@ package singbridge
import (
"context"
"io"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"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/session"
@@ -40,9 +39,10 @@ func (d *Dispatcher) NewConnection(ctx context.Context, conn net.Conn, metadata
}
func (d *Dispatcher) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
packetConn := &PacketConn{bufio.NewBindPacketConn(conn.(net.PacketConn), metadata.Destination), ToDestination(metadata.Destination, net.Network_UDP)}
return d.upstream.DispatchLink(ctx, ToDestination(metadata.Destination, net.Network_UDP), &transport.Link{
Reader: buf.NewPacketReader(conn.(io.Reader)),
Writer: buf.NewWriter(conn.(io.Writer)),
Reader: packetConn,
Writer: packetConn,
})
}

View File

@@ -14,6 +14,9 @@ var (
_ buf.Reader = (*Conn)(nil)
_ buf.TimeoutReader = (*Conn)(nil)
_ buf.Writer = (*Conn)(nil)
_ buf.Reader = (*PacketConn)(nil)
_ buf.TimeoutReader = (*PacketConn)(nil)
_ buf.Writer = (*PacketConn)(nil)
)
type Conn struct {
@@ -64,3 +67,32 @@ func (c *Conn) WriteMultiBuffer(bufferList buf.MultiBuffer) error {
}
return nil
}
type PacketConn struct {
net.Conn
destination net.Destination
}
func (c *PacketConn) ReadMultiBuffer() (buf.MultiBuffer, error) {
buffer, err := buf.ReadBuffer(c.Conn)
if err != nil {
return nil, err
}
buffer.UDP = &c.destination
return buf.MultiBuffer{buffer}, nil
}
func (c *PacketConn) ReadMultiBufferTimeout(duration time.Duration) (buf.MultiBuffer, error) {
err := c.SetReadDeadline(time.Now().Add(duration))
if err != nil {
return nil, err
}
defer c.SetReadDeadline(time.Time{})
return c.ReadMultiBuffer()
}
func (c *PacketConn) WriteMultiBuffer(mb buf.MultiBuffer) error {
mb, err := buf.WriteMultiBuffer(c.Conn, mb)
buf.ReleaseMulti(mb)
return err
}

5
go.mod
View File

@@ -13,7 +13,8 @@ require (
github.com/pires/go-proxyproto v0.7.0
github.com/quic-go/quic-go v0.34.0
github.com/refraction-networking/utls v1.3.2
github.com/sagernet/sing v0.2.4
github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207
github.com/sagernet/sing-mux v0.0.0-20230425101127-4e8851eb1a2c
github.com/sagernet/sing-shadowsocks v0.2.1
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
@@ -41,6 +42,7 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/onsi/ginkgo/v2 v2.9.2 // indirect
@@ -48,6 +50,7 @@ require (
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/mod v0.10.0 // indirect

14
go.sum
View File

@@ -89,6 +89,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -143,12 +145,15 @@ github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvj
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.2.3 h1:V50MvZ4c3Iij2lYFWPlzL1PyipwSzjGeN9x+Ox89vpk=
github.com/sagernet/sing v0.2.3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207 h1:+dDVjW20IT+e8maKryaDeRY2+RFmTFdrQeIzqE2WOss=
github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-mux v0.0.0-20230425101127-4e8851eb1a2c h1:56vRmAIFvQZi9V2kNBNM/tOinmLtR9hx1xAWeDbTZb4=
github.com/sagernet/sing-mux v0.0.0-20230425101127-4e8851eb1a2c/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI=
github.com/sagernet/sing-shadowsocks v0.2.1 h1:FvdLQOqpvxHBJUcUe4fvgiYP2XLLwH5i1DtXQviVEPw=
github.com/sagernet/sing-shadowsocks v0.2.1/go.mod h1:T/OgurSjsAe+Ug3+6PprXjmgHFmJidjOvQcjXGTKb3I=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
@@ -257,6 +262,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@@ -130,6 +130,24 @@ func (m *MuxConfig) Build() (*proxyman.MultiplexingConfig, error) {
}, nil
}
type SingMuxConfig struct {
Enabled bool `json:"enabled"`
Protocol string `json:"protocol"`
MaxConnections int `json:"max_connections"`
MinStreams int `json:"min_streams"`
MaxStreams int `json:"max_streams"`
}
func (m *SingMuxConfig) Build() (*proxyman.SingMultiplexConfig, error) {
return &proxyman.SingMultiplexConfig{
Enabled: m.Enabled,
Protocol: m.Protocol,
MaxConnections: int32(m.MaxConnections),
MinStreams: int32(m.MinStreams),
MaxStreams: int32(m.MaxStreams),
}, nil
}
type InboundDetourAllocationConfig struct {
Strategy string `json:"strategy"`
Concurrency *uint32 `json:"concurrency"`
@@ -285,6 +303,7 @@ type OutboundDetourConfig struct {
StreamSetting *StreamConfig `json:"streamSettings"`
ProxySettings *ProxyConfig `json:"proxySettings"`
MuxSettings *MuxConfig `json:"mux"`
SingMuxSettings *SingMuxConfig `json:"smux"`
}
func (c *OutboundDetourConfig) checkChainProxyConfig() error {
@@ -347,6 +366,13 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
}
senderSettings.MultiplexSettings = ms
}
if c.SingMuxSettings != nil {
ms, err := c.SingMuxSettings.Build()
if err != nil {
return nil, newError("failed to build sing-mux config.").Base(err)
}
senderSettings.SmuxSettings = ms
}
settings := []byte("{}")
if c.Settings != nil {

View File

@@ -1,8 +1,9 @@
package grpc
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestConfig_GetServiceName(t *testing.T) {