From 35b4ad44c0b18f31dbe901383a4e1f34d56a68a9 Mon Sep 17 00:00:00 2001 From: Kaede Akino Date: Thu, 8 Aug 2024 22:04:16 +0800 Subject: [PATCH] feat: add MPTCP support --- infra/conf/cfgcommon/socketcfg/socket.go | 11 ++ infra/conf/v4/transport_test.go | 4 +- transport/internet/config.pb.go | 201 ++++++++++++++++------- transport/internet/config.proto | 14 ++ transport/internet/sockopt_test.go | 30 ++++ transport/internet/system_dialer.go | 9 + transport/internet/system_listener.go | 13 +- 7 files changed, 217 insertions(+), 65 deletions(-) diff --git a/infra/conf/cfgcommon/socketcfg/socket.go b/infra/conf/cfgcommon/socketcfg/socket.go index ab6996f7d..940c0d826 100644 --- a/infra/conf/cfgcommon/socketcfg/socket.go +++ b/infra/conf/cfgcommon/socketcfg/socket.go @@ -18,6 +18,7 @@ type SocketConfig struct { RxBufSize uint64 `json:"rxBufSize"` TxBufSize uint64 `json:"txBufSize"` ForceBufSize bool `json:"forceBufSize"` + MPTCP *bool `json:"mptcp"` } // Build implements Buildable. @@ -46,6 +47,15 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { tproxy = internet.SocketConfig_Off } + var mptcpSettings internet.MPTCPState + if c.MPTCP != nil { + if *c.MPTCP { + mptcpSettings = internet.MPTCPState_Enable + } else { + mptcpSettings = internet.MPTCPState_Disable + } + } + return &internet.SocketConfig{ Mark: c.Mark, Tfo: tfoSettings, @@ -58,5 +68,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { TxBufSize: int64(c.TxBufSize), ForceBufSize: c.ForceBufSize, BindToDevice: c.BindToDevice, + Mptcp: mptcpSettings, }, nil } diff --git a/infra/conf/v4/transport_test.go b/infra/conf/v4/transport_test.go index f342a1258..1eddc3fc2 100644 --- a/infra/conf/v4/transport_test.go +++ b/infra/conf/v4/transport_test.go @@ -38,13 +38,15 @@ func TestSocketConfig(t *testing.T) { Input: `{ "mark": 1, "tcpFastOpen": true, - "tcpFastOpenQueueLength": 1024 + "tcpFastOpenQueueLength": 1024, + "mptcp": true }`, Parser: createParser(), Output: &internet.SocketConfig{ Mark: 1, Tfo: internet.SocketConfig_Enable, TfoQueueLength: 1024, + Mptcp: internet.MPTCPState_Enable, }, }, }) diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index 1ded5291f..31b62337c 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -1,3 +1,9 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v4.25.3 +// source: transport/internet/config.proto + package internet import ( @@ -73,6 +79,60 @@ func (TransportProtocol) EnumDescriptor() ([]byte, []int) { return file_transport_internet_config_proto_rawDescGZIP(), []int{0} } +// MPTCP is the state of MPTCP settings. +// Define it here to avoid conflict with TCPFastOpenState. +type MPTCPState int32 + +const ( + // AsIs is to leave the current MPTCP state as is, unmodified. + MPTCPState_AsIs MPTCPState = 0 + // Enable is for enabling MPTCP explictly. + MPTCPState_Enable MPTCPState = 1 + // Disable is for disabling MPTCP explictly. + MPTCPState_Disable MPTCPState = 2 +) + +// Enum value maps for MPTCPState. +var ( + MPTCPState_name = map[int32]string{ + 0: "AsIs", + 1: "Enable", + 2: "Disable", + } + MPTCPState_value = map[string]int32{ + "AsIs": 0, + "Enable": 1, + "Disable": 2, + } +) + +func (x MPTCPState) Enum() *MPTCPState { + p := new(MPTCPState) + *p = x + return p +} + +func (x MPTCPState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MPTCPState) Descriptor() protoreflect.EnumDescriptor { + return file_transport_internet_config_proto_enumTypes[1].Descriptor() +} + +func (MPTCPState) Type() protoreflect.EnumType { + return &file_transport_internet_config_proto_enumTypes[1] +} + +func (x MPTCPState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MPTCPState.Descriptor instead. +func (MPTCPState) EnumDescriptor() ([]byte, []int) { + return file_transport_internet_config_proto_rawDescGZIP(), []int{1} +} + type SocketConfig_TCPFastOpenState int32 const ( @@ -109,11 +169,11 @@ func (x SocketConfig_TCPFastOpenState) String() string { } func (SocketConfig_TCPFastOpenState) Descriptor() protoreflect.EnumDescriptor { - return file_transport_internet_config_proto_enumTypes[1].Descriptor() + return file_transport_internet_config_proto_enumTypes[2].Descriptor() } func (SocketConfig_TCPFastOpenState) Type() protoreflect.EnumType { - return &file_transport_internet_config_proto_enumTypes[1] + return &file_transport_internet_config_proto_enumTypes[2] } func (x SocketConfig_TCPFastOpenState) Number() protoreflect.EnumNumber { @@ -161,11 +221,11 @@ func (x SocketConfig_TProxyMode) String() string { } func (SocketConfig_TProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_transport_internet_config_proto_enumTypes[2].Descriptor() + return file_transport_internet_config_proto_enumTypes[3].Descriptor() } func (SocketConfig_TProxyMode) Type() protoreflect.EnumType { - return &file_transport_internet_config_proto_enumTypes[2] + return &file_transport_internet_config_proto_enumTypes[3] } func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber { @@ -410,17 +470,18 @@ type SocketConfig struct { Tproxy SocketConfig_TProxyMode `protobuf:"varint,3,opt,name=tproxy,proto3,enum=v2ray.core.transport.internet.SocketConfig_TProxyMode" json:"tproxy,omitempty"` // ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket // option. This option is for UDP only. - ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` - BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` - BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` - AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` - TcpKeepAliveInterval int32 `protobuf:"varint,8,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"` - TfoQueueLength uint32 `protobuf:"varint,9,opt,name=tfo_queue_length,json=tfoQueueLength,proto3" json:"tfo_queue_length,omitempty"` - TcpKeepAliveIdle int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"` - BindToDevice string `protobuf:"bytes,11,opt,name=bind_to_device,json=bindToDevice,proto3" json:"bind_to_device,omitempty"` - RxBufSize int64 `protobuf:"varint,12,opt,name=rx_buf_size,json=rxBufSize,proto3" json:"rx_buf_size,omitempty"` - TxBufSize int64 `protobuf:"varint,13,opt,name=tx_buf_size,json=txBufSize,proto3" json:"tx_buf_size,omitempty"` - ForceBufSize bool `protobuf:"varint,14,opt,name=force_buf_size,json=forceBufSize,proto3" json:"force_buf_size,omitempty"` + ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` + BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` + BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` + TcpKeepAliveInterval int32 `protobuf:"varint,8,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"` + TfoQueueLength uint32 `protobuf:"varint,9,opt,name=tfo_queue_length,json=tfoQueueLength,proto3" json:"tfo_queue_length,omitempty"` + TcpKeepAliveIdle int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"` + BindToDevice string `protobuf:"bytes,11,opt,name=bind_to_device,json=bindToDevice,proto3" json:"bind_to_device,omitempty"` + RxBufSize int64 `protobuf:"varint,12,opt,name=rx_buf_size,json=rxBufSize,proto3" json:"rx_buf_size,omitempty"` + TxBufSize int64 `protobuf:"varint,13,opt,name=tx_buf_size,json=txBufSize,proto3" json:"tx_buf_size,omitempty"` + ForceBufSize bool `protobuf:"varint,14,opt,name=force_buf_size,json=forceBufSize,proto3" json:"force_buf_size,omitempty"` + Mptcp MPTCPState `protobuf:"varint,15,opt,name=mptcp,proto3,enum=v2ray.core.transport.internet.MPTCPState" json:"mptcp,omitempty"` } func (x *SocketConfig) Reset() { @@ -553,6 +614,13 @@ func (x *SocketConfig) GetForceBufSize() bool { return false } +func (x *SocketConfig) GetMptcp() MPTCPState { + if x != nil { + return x.Mptcp + } + return MPTCPState_AsIs +} + var File_transport_internet_config_proto protoreflect.FileDescriptor var file_transport_internet_config_proto_rawDesc = []byte{ @@ -605,7 +673,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x22, 0xfd, 0x05, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x22, 0xbe, 0x06, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x4e, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, @@ -646,27 +714,34 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x78, 0x42, 0x75, 0x66, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, - 0x65, 0x42, 0x75, 0x66, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, - 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, - 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, - 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, - 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, - 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, - 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, - 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, - 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x42, 0x78, 0x0a, 0x21, - 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, - 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, - 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x42, 0x75, 0x66, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x6d, 0x70, 0x74, 0x63, + 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x4d, 0x50, 0x54, 0x43, 0x50, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x05, 0x6d, 0x70, 0x74, 0x63, 0x70, 0x22, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, + 0x46, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, + 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, + 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, + 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, + 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, + 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, + 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, + 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x2a, 0x2f, 0x0a, + 0x0a, 0x4d, 0x50, 0x54, 0x43, 0x50, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x41, + 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, + 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x42, 0x78, + 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, + 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, + 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -681,32 +756,34 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte { return file_transport_internet_config_proto_rawDescData } -var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 4) var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_transport_internet_config_proto_goTypes = []interface{}{ +var file_transport_internet_config_proto_goTypes = []any{ (TransportProtocol)(0), // 0: v2ray.core.transport.internet.TransportProtocol - (SocketConfig_TCPFastOpenState)(0), // 1: v2ray.core.transport.internet.SocketConfig.TCPFastOpenState - (SocketConfig_TProxyMode)(0), // 2: v2ray.core.transport.internet.SocketConfig.TProxyMode - (*TransportConfig)(nil), // 3: v2ray.core.transport.internet.TransportConfig - (*StreamConfig)(nil), // 4: v2ray.core.transport.internet.StreamConfig - (*ProxyConfig)(nil), // 5: v2ray.core.transport.internet.ProxyConfig - (*SocketConfig)(nil), // 6: v2ray.core.transport.internet.SocketConfig - (*anypb.Any)(nil), // 7: google.protobuf.Any + (MPTCPState)(0), // 1: v2ray.core.transport.internet.MPTCPState + (SocketConfig_TCPFastOpenState)(0), // 2: v2ray.core.transport.internet.SocketConfig.TCPFastOpenState + (SocketConfig_TProxyMode)(0), // 3: v2ray.core.transport.internet.SocketConfig.TProxyMode + (*TransportConfig)(nil), // 4: v2ray.core.transport.internet.TransportConfig + (*StreamConfig)(nil), // 5: v2ray.core.transport.internet.StreamConfig + (*ProxyConfig)(nil), // 6: v2ray.core.transport.internet.ProxyConfig + (*SocketConfig)(nil), // 7: v2ray.core.transport.internet.SocketConfig + (*anypb.Any)(nil), // 8: google.protobuf.Any } var file_transport_internet_config_proto_depIdxs = []int32{ 0, // 0: v2ray.core.transport.internet.TransportConfig.protocol:type_name -> v2ray.core.transport.internet.TransportProtocol - 7, // 1: v2ray.core.transport.internet.TransportConfig.settings:type_name -> google.protobuf.Any + 8, // 1: v2ray.core.transport.internet.TransportConfig.settings:type_name -> google.protobuf.Any 0, // 2: v2ray.core.transport.internet.StreamConfig.protocol:type_name -> v2ray.core.transport.internet.TransportProtocol - 3, // 3: v2ray.core.transport.internet.StreamConfig.transport_settings:type_name -> v2ray.core.transport.internet.TransportConfig - 7, // 4: v2ray.core.transport.internet.StreamConfig.security_settings:type_name -> google.protobuf.Any - 6, // 5: v2ray.core.transport.internet.StreamConfig.socket_settings:type_name -> v2ray.core.transport.internet.SocketConfig - 1, // 6: v2ray.core.transport.internet.SocketConfig.tfo:type_name -> v2ray.core.transport.internet.SocketConfig.TCPFastOpenState - 2, // 7: v2ray.core.transport.internet.SocketConfig.tproxy:type_name -> v2ray.core.transport.internet.SocketConfig.TProxyMode - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 4, // 3: v2ray.core.transport.internet.StreamConfig.transport_settings:type_name -> v2ray.core.transport.internet.TransportConfig + 8, // 4: v2ray.core.transport.internet.StreamConfig.security_settings:type_name -> google.protobuf.Any + 7, // 5: v2ray.core.transport.internet.StreamConfig.socket_settings:type_name -> v2ray.core.transport.internet.SocketConfig + 2, // 6: v2ray.core.transport.internet.SocketConfig.tfo:type_name -> v2ray.core.transport.internet.SocketConfig.TCPFastOpenState + 3, // 7: v2ray.core.transport.internet.SocketConfig.tproxy:type_name -> v2ray.core.transport.internet.SocketConfig.TProxyMode + 1, // 8: v2ray.core.transport.internet.SocketConfig.mptcp:type_name -> v2ray.core.transport.internet.MPTCPState + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_transport_internet_config_proto_init() } @@ -715,7 +792,7 @@ func file_transport_internet_config_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_transport_internet_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_transport_internet_config_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*TransportConfig); i { case 0: return &v.state @@ -727,7 +804,7 @@ func file_transport_internet_config_proto_init() { return nil } } - file_transport_internet_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_transport_internet_config_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*StreamConfig); i { case 0: return &v.state @@ -739,7 +816,7 @@ func file_transport_internet_config_proto_init() { return nil } } - file_transport_internet_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_transport_internet_config_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ProxyConfig); i { case 0: return &v.state @@ -751,7 +828,7 @@ func file_transport_internet_config_proto_init() { return nil } } - file_transport_internet_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_transport_internet_config_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*SocketConfig); i { case 0: return &v.state @@ -769,7 +846,7 @@ func file_transport_internet_config_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_transport_internet_config_proto_rawDesc, - NumEnums: 3, + NumEnums: 4, NumMessages: 4, NumExtensions: 0, NumServices: 0, diff --git a/transport/internet/config.proto b/transport/internet/config.proto index 2478c6f2e..0a6a057db 100644 --- a/transport/internet/config.proto +++ b/transport/internet/config.proto @@ -53,6 +53,17 @@ message ProxyConfig { bool transportLayerProxy = 2; } +// MPTCP is the state of MPTCP settings. +// Define it here to avoid conflict with TCPFastOpenState. +enum MPTCPState { + // AsIs is to leave the current MPTCP state as is, unmodified. + AsIs = 0; + // Enable is for enabling MPTCP explictly. + Enable = 1; + // Disable is for disabling MPTCP explictly. + Disable = 2; +} + // SocketConfig is options to be applied on network sockets. message SocketConfig { // Mark of the connection. If non-zero, the value will be set to SO_MARK. @@ -103,4 +114,7 @@ message SocketConfig { int64 rx_buf_size = 12; int64 tx_buf_size = 13; bool force_buf_size = 14; + + + MPTCPState mptcp = 15; } diff --git a/transport/internet/sockopt_test.go b/transport/internet/sockopt_test.go index 56e978e06..d712e2782 100644 --- a/transport/internet/sockopt_test.go +++ b/transport/internet/sockopt_test.go @@ -39,3 +39,33 @@ func TestTCPFastOpen(t *testing.T) { t.Fatal(r) } } + +// Currently, Multipath TCP is only supported on Linux. +// We test the Multipath TCP Settings on other platforms for ensure code will not have any negative impact on other platforms. +func TestMultipathTCP(t *testing.T) { + tcpServer := tcp.Server{ + MsgProcessor: func(b []byte) []byte { + return b + }, + } + dest, err := tcpServer.StartContext(context.Background(), &SocketConfig{Mptcp: MPTCPState_Enable}) + common.Must(err) + defer tcpServer.Close() + + ctx := context.Background() + dialer := DefaultSystemDialer{} + conn, err := dialer.Dial(ctx, nil, dest, &SocketConfig{ + Mptcp: MPTCPState_Enable, + }) + common.Must(err) + defer conn.Close() + + _, err = conn.Write([]byte("abcd")) + common.Must(err) + + b := buf.New() + common.Must2(b.ReadFrom(conn)) + if r := cmp.Diff(b.Bytes(), []byte("abcd")); r != "" { + t.Fatal(r) + } +} diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 314664a78..e6783d0a5 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -73,6 +73,15 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne KeepAlive: goStdKeepAlive, } + if sockopt != nil { + switch sockopt.Mptcp { + case MPTCPState_Enable: + dialer.SetMultipathTCP(true) + case MPTCPState_Disable: + dialer.SetMultipathTCP(false) + } + } + if sockopt != nil || len(d.controllers) > 0 { dialer.Control = func(network, address string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { diff --git a/transport/internet/system_listener.go b/transport/internet/system_listener.go index ef54228d6..84f9f1e8a 100644 --- a/transport/internet/system_listener.go +++ b/transport/internet/system_listener.go @@ -69,8 +69,17 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S network = addr.Network() address = addr.String() lc.Control = getControlFunc(ctx, sockopt, dl.controllers) - if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { - lc.KeepAlive = time.Duration(-1) + if sockopt != nil { + switch sockopt.Mptcp { + case MPTCPState_Enable: + lc.SetMultipathTCP(true) + case MPTCPState_Disable: + lc.SetMultipathTCP(false) + } + + if sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0 { + lc.KeepAlive = time.Duration(-1) + } } case *net.UnixAddr: lc.Control = nil