From 7b7880d29b9f127c47db90cd3e4d0df1da6a584c Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Thu, 23 Dec 2021 05:28:09 +0300 Subject: [PATCH 01/12] Add TCP keep alive idle setting --- transport/internet/config.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transport/internet/config.proto b/transport/internet/config.proto index f0d384f1c5a..6e0e48a35f3 100644 --- a/transport/internet/config.proto +++ b/transport/internet/config.proto @@ -95,4 +95,6 @@ message SocketConfig { int32 tcp_keep_alive_interval = 8; uint32 tfo_queue_length = 9; + + int32 tcp_keep_alive_idle = 10; } From dfa47bc0836c03bf9c54d705e51b4d1b6b2a8491 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Thu, 23 Dec 2021 05:28:37 +0300 Subject: [PATCH 02/12] Add TCP keep alive idle setting: auto generated --- transport/internet/config.pb.go | 55 ++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index dcef3af4a61..8a33f203b0e 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -422,6 +422,7 @@ type SocketConfig struct { 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"` } func (x *SocketConfig) Reset() { @@ -519,6 +520,13 @@ func (x *SocketConfig) GetTfoQueueLength() uint32 { return 0 } +func (x *SocketConfig) GetTcpKeepAliveIdle() int32 { + if x != nil { + return x.TcpKeepAliveIdle + } + return 0 +} + var File_transport_internet_config_proto protoreflect.FileDescriptor var file_transport_internet_config_proto_rawDesc = []byte{ @@ -573,7 +581,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 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, 0xc2, 0x04, 0x0a, + 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, 0xf1, 0x04, 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, @@ -603,27 +611,30 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x66, 0x6f, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x74, 0x66, 0x6f, 0x51, 0x75, - 0x65, 0x75, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 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, 0x34, 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, 0x75, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x13, 0x74, 0x63, 0x70, + 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x64, 0x6c, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, + 0x6c, 0x69, 0x76, 0x65, 0x49, 0x64, 0x6c, 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, 0x34, 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 ( From 288519cd1783a5238982fdaf03951f881f9d6123 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Sat, 13 Nov 2021 21:31:49 +0000 Subject: [PATCH 03/12] Add TCP keep alive support in Linux --- transport/internet/sockopt_linux.go | 16 ++++++++++++++-- transport/internet/system_dialer.go | 6 +++++- transport/internet/system_listener.go | 4 ++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/transport/internet/sockopt_linux.go b/transport/internet/sockopt_linux.go index dc2f36e1aef..0c00b927a05 100644 --- a/transport/internet/sockopt_linux.go +++ b/transport/internet/sockopt_linux.go @@ -59,10 +59,16 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } } - if config.TcpKeepAliveInterval != 0 { + if config.TcpKeepAliveInterval > 0 { if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } } } @@ -93,10 +99,16 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) } } - if config.TcpKeepAliveInterval != 0 { + if config.TcpKeepAliveInterval > 0 { if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } } } diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index eb6ffffa7a5..a696f26d337 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -63,10 +63,14 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne dest: destAddr, }, nil } - + goStdKeepAlive := time.Duration(0) + if sockopt.TcpKeepAliveIdle != 0 { + goStdKeepAlive = time.Duration(-1) + } dialer := &net.Dialer{ Timeout: time.Second * 16, LocalAddr: resolveSrcAddr(dest.Network, src), + KeepAlive: goStdKeepAlive, } if sockopt != nil || len(d.controllers) > 0 { diff --git a/transport/internet/system_listener.go b/transport/internet/system_listener.go index a13a367681e..56c5d7ece20 100644 --- a/transport/internet/system_listener.go +++ b/transport/internet/system_listener.go @@ -4,6 +4,7 @@ import ( "context" "runtime" "syscall" + "time" "github.com/pires/go-proxyproto" @@ -49,6 +50,9 @@ 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.TcpKeepAliveIdle != 0 { + lc.KeepAlive = time.Duration(-1) + } case *net.UnixAddr: lc.Control = nil network = addr.Network() From 86e754165be5b1b0d7fc1ad439560bc92a54b282 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Sat, 13 Nov 2021 21:46:45 +0000 Subject: [PATCH 04/12] Add TCP keep alive support in MacOS, FreeBSD --- transport/internet/sockopt_darwin.go | 17 +++++++++++++++++ transport/internet/sockopt_freebsd.go | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index c4b2e8deb38..a90a9815cbe 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -25,6 +25,15 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf return err } } + + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } return nil @@ -42,6 +51,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return err } } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } return nil diff --git a/transport/internet/sockopt_freebsd.go b/transport/internet/sockopt_freebsd.go index 50834cdd255..98e8d11eee7 100644 --- a/transport/internet/sockopt_freebsd.go +++ b/transport/internet/sockopt_freebsd.go @@ -141,6 +141,14 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf return newError("failed to set TCP_FASTOPEN_CONNECT=0").Base(err) } } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } if config.Tproxy.IsEnabled() { @@ -175,6 +183,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return newError("failed to set TCP_FASTOPEN=0").Base(err) } } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } if config.Tproxy.IsEnabled() { From 006dde410166089645380d6c11e1c4c721ae06ba Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Sat, 13 Nov 2021 22:13:37 +0000 Subject: [PATCH 05/12] Add TCP keep alive support in Windows --- transport/internet/sockopt_windows.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/transport/internet/sockopt_windows.go b/transport/internet/sockopt_windows.go index 0f8d475d8da..c69cb173633 100644 --- a/transport/internet/sockopt_windows.go +++ b/transport/internet/sockopt_windows.go @@ -25,6 +25,11 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil { return err } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } return nil @@ -35,6 +40,11 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil { return err } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + return newError("failed to set SO_KEEPALIVE", err) + } + } } return nil From 7fe6a880b7dd2a09c19d68a6e7d7fa592581f0b9 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 13 Nov 2021 22:32:23 +0000 Subject: [PATCH 06/12] fix bug introduced in adding tcp keep alive adjustment --- transport/internet/system_dialer.go | 2 +- transport/internet/system_listener.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index a696f26d337..578e434d20c 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -64,7 +64,7 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne }, nil } goStdKeepAlive := time.Duration(0) - if sockopt.TcpKeepAliveIdle != 0 { + if sockopt != nil && sockopt.TcpKeepAliveIdle != 0 { goStdKeepAlive = time.Duration(-1) } dialer := &net.Dialer{ diff --git a/transport/internet/system_listener.go b/transport/internet/system_listener.go index 56c5d7ece20..a6a7ee90280 100644 --- a/transport/internet/system_listener.go +++ b/transport/internet/system_listener.go @@ -50,7 +50,7 @@ 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.TcpKeepAliveIdle != 0 { + if sockopt != nil && sockopt.TcpKeepAliveIdle != 0 { lc.KeepAlive = time.Duration(-1) } case *net.UnixAddr: From 5b370922e2a0fe9df63d20332fc12e7413eb6fac Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 20 Nov 2021 16:46:23 +0000 Subject: [PATCH 07/12] embed macOS const to avoid platform inconsistency --- transport/internet/sockopt_darwin.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index a90a9815cbe..308616d1aa4 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -10,7 +10,8 @@ const ( // TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections. TCP_FASTOPEN_SERVER = 0x01 // nolint: golint,stylecheck // TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections. - TCP_FASTOPEN_CLIENT = 0x02 // nolint: golint,stylecheck + TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck + TCP_KEEPINTVL = 0x101 // nolint: golint,stylecheck ) func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { @@ -52,7 +53,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) } } if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { From 574e261d79601e2c5c346d7d0cea57e92ac64029 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 20 Nov 2021 16:52:42 +0000 Subject: [PATCH 08/12] embed macOS const to avoid platform inconsistency(again) --- transport/internet/sockopt_darwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index 308616d1aa4..4353f28a789 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -28,7 +28,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { From 8fe67f48ab84f0c8429dc593ae0301248e2fc942 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 20 Nov 2021 17:31:50 +0000 Subject: [PATCH 09/12] add TCP Keep Alive support in config --- infra/conf/transport_internet.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 542557a160a..4af6093f41a 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -391,6 +391,7 @@ type SocketConfig struct { TProxy string `json:"tproxy"` AcceptProxyProtocol bool `json:"acceptProxyProtocol"` TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"` + TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"` } // Build implements Buildable. @@ -426,6 +427,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { Tproxy: tproxy, AcceptProxyProtocol: c.AcceptProxyProtocol, TcpKeepAliveInterval: c.TCPKeepAliveInterval, + TcpKeepAliveIdle: c.TCPKeepAliveIdle, }, nil } From 7917c29cb07efa105e4c45b907e878a52ad3de60 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 28 Nov 2021 21:20:39 +0000 Subject: [PATCH 10/12] use sys/unix instead of syscall Suggestion from: https://github.com/v2fly/v2ray-core/pull/1395#issuecomment-974761647 --- transport/internet/sockopt_darwin.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index 4353f28a789..8f9a95c1aab 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -1,7 +1,7 @@ package internet import ( - "syscall" + "golang.org/x/sys/unix" ) const ( @@ -18,20 +18,20 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf if isTCPSocket(network) { switch config.Tfo { case SocketConfig_Enable: - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, TCP_FASTOPEN_CLIENT); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, unix.TCP_FASTOPEN_CLIENT); err != nil { return err } case SocketConfig_Disable: - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, 0); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil { return err } } if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) } } @@ -44,19 +44,19 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) if isTCPSocket(network) { switch config.Tfo { case SocketConfig_Enable: - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, TCP_FASTOPEN_SERVER); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_SERVER); err != nil { return err } case SocketConfig_Disable: - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, 0); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil { return err } } if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { return newError("failed to set TCP_KEEPINTVL", err) } - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) } } From 22393fd56e8eeaeabfe6511110db981ed28ec04c Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sun, 28 Nov 2021 21:27:28 +0000 Subject: [PATCH 11/12] use sys/unix instead of syscall Suggestion from: https://github.com/v2fly/v2ray-core/pull/1395#issuecomment-974761647 --- transport/internet/sockopt_darwin.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index 8f9a95c1aab..556c8c675b1 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -5,20 +5,17 @@ import ( ) const ( - // TCP_FASTOPEN is the socket option on darwin for TCP fast open. - TCP_FASTOPEN = 0x105 // nolint: golint,stylecheck // TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections. TCP_FASTOPEN_SERVER = 0x01 // nolint: golint,stylecheck // TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections. TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck - TCP_KEEPINTVL = 0x101 // nolint: golint,stylecheck ) func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { if isTCPSocket(network) { switch config.Tfo { case SocketConfig_Enable: - if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, unix.TCP_FASTOPEN_CLIENT); err != nil { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_CLIENT); err != nil { return err } case SocketConfig_Disable: From c68a6b40ac0d6e7d57db101bb06b4e528559f374 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Thu, 23 Dec 2021 14:02:47 +0300 Subject: [PATCH 12/12] Separate TcpKeepAliveIdle and TcpKeepAliveInterval check logic --- transport/internet/sockopt_darwin.go | 28 +++++++++++++++++++++------ transport/internet/sockopt_freebsd.go | 26 +++++++++++++++++++------ transport/internet/sockopt_linux.go | 28 +++++++++++++++++---------- transport/internet/sockopt_windows.go | 4 ++-- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index 556c8c675b1..22225ce8506 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -9,6 +9,8 @@ const ( TCP_FASTOPEN_SERVER = 0x01 // nolint: golint,stylecheck // TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections. TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck + // syscall.TCP_KEEPINTVL is missing on some darwin architectures. + sysTCP_KEEPINTVL = 0x101 // nolint: revive,stylecheck ) func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { @@ -24,9 +26,16 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } } - if config.TcpKeepAliveInterval > 0 { - if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + } + if config.TcpKeepAliveInterval > 0 { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } } if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) @@ -49,9 +58,16 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return err } } - if config.TcpKeepAliveInterval > 0 { - if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } + } + if config.TcpKeepAliveInterval > 0 { + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } } if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) diff --git a/transport/internet/sockopt_freebsd.go b/transport/internet/sockopt_freebsd.go index 98e8d11eee7..b90a0fc72cf 100644 --- a/transport/internet/sockopt_freebsd.go +++ b/transport/internet/sockopt_freebsd.go @@ -141,9 +141,16 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf return newError("failed to set TCP_FASTOPEN_CONNECT=0").Base(err) } } - if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } + } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) @@ -183,9 +190,16 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return newError("failed to set TCP_FASTOPEN=0").Base(err) } } - if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } + } + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) diff --git a/transport/internet/sockopt_linux.go b/transport/internet/sockopt_linux.go index 0c00b927a05..6d7f2e94dbf 100644 --- a/transport/internet/sockopt_linux.go +++ b/transport/internet/sockopt_linux.go @@ -59,12 +59,16 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } } - if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 { + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } } - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { - return newError("failed to set TCP_KEEPIDLE", err) + if config.TcpKeepAliveIdle > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) @@ -99,12 +103,16 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) } } - if config.TcpKeepAliveInterval > 0 { - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { - return newError("failed to set TCP_KEEPINTVL", err) + if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 { + if config.TcpKeepAliveInterval > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { + return newError("failed to set TCP_KEEPINTVL", err) + } } - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { - return newError("failed to set TCP_KEEPIDLE", err) + if config.TcpKeepAliveIdle > 0 { + if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil { + return newError("failed to set TCP_KEEPIDLE", err) + } } if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) diff --git a/transport/internet/sockopt_windows.go b/transport/internet/sockopt_windows.go index c69cb173633..a076700734f 100644 --- a/transport/internet/sockopt_windows.go +++ b/transport/internet/sockopt_windows.go @@ -25,7 +25,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil { return err } - if config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) } @@ -40,7 +40,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil { return err } - if config.TcpKeepAliveInterval > 0 { + if config.TcpKeepAliveIdle > 0 { if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { return newError("failed to set SO_KEEPALIVE", err) }