From cd56eaaba219ce5bdb04cdac695cd8d62ed29a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 6 Dec 2025 11:23:01 +0800 Subject: [PATCH] Add more tcp keep alive options Also update default TCP keep-alive initial period from 10 minutes to 5 minutes. --- common/dialer/default.go | 15 ++++++++-- common/listener/listener_tcp.go | 2 +- constant/timeout.go | 2 +- docs/configuration/shared/dial.md | 35 ++++++++++++++++++++++- docs/configuration/shared/dial.zh.md | 34 ++++++++++++++++++++++ docs/configuration/shared/listen.md | 30 ++++++++++++++++++++ docs/configuration/shared/listen.zh.md | 30 ++++++++++++++++++++ option/inbound.go | 1 + option/outbound.go | 39 ++++++++++++++------------ 9 files changed, 164 insertions(+), 24 deletions(-) diff --git a/common/dialer/default.go b/common/dialer/default.go index 06f637a3a..23754e0a3 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -143,9 +143,18 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial } else { dialer.Timeout = C.TCPConnectTimeout } - // TODO: Add an option to customize the keep alive period - dialer.KeepAlive = C.TCPKeepAliveInitial - dialer.Control = control.Append(dialer.Control, control.SetKeepAlivePeriod(C.TCPKeepAliveInitial, C.TCPKeepAliveInterval)) + if !options.DisableTCPKeepAlive { + keepIdle := time.Duration(options.TCPKeepAlive) + if keepIdle == 0 { + keepIdle = C.TCPKeepAliveInitial + } + keepInterval := time.Duration(options.TCPKeepAliveInterval) + if keepInterval == 0 { + keepInterval = C.TCPKeepAliveInterval + } + dialer.KeepAlive = keepIdle + dialer.Control = control.Append(dialer.Control, control.SetKeepAlivePeriod(keepIdle, keepInterval)) + } var udpFragment bool if options.UDPFragment != nil { udpFragment = *options.UDPFragment diff --git a/common/listener/listener_tcp.go b/common/listener/listener_tcp.go index e63d643c8..2164ff8e1 100644 --- a/common/listener/listener_tcp.go +++ b/common/listener/listener_tcp.go @@ -37,7 +37,7 @@ func (l *Listener) ListenTCP() (net.Listener, error) { if l.listenOptions.ReuseAddr { listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr()) } - if l.listenOptions.TCPKeepAlive >= 0 { + if !l.listenOptions.DisableTCPKeepAlive { keepIdle := time.Duration(l.listenOptions.TCPKeepAlive) if keepIdle == 0 { keepIdle = C.TCPKeepAliveInitial diff --git a/constant/timeout.go b/constant/timeout.go index eb0fd34c0..e1bc7ccdf 100644 --- a/constant/timeout.go +++ b/constant/timeout.go @@ -3,7 +3,7 @@ package constant import "time" const ( - TCPKeepAliveInitial = 10 * time.Minute + TCPKeepAliveInitial = 5 * time.Minute TCPKeepAliveInterval = 75 * time.Second TCPConnectTimeout = 5 * time.Second TCPTimeout = 15 * time.Second diff --git a/docs/configuration/shared/dial.md b/docs/configuration/shared/dial.md index f48f355d9..cf775b655 100644 --- a/docs/configuration/shared/dial.md +++ b/docs/configuration/shared/dial.md @@ -2,6 +2,12 @@ icon: material/new-box --- +!!! quote "Changes in sing-box 1.13.0" + + :material-plus: [disable_tcp_keep_alive](#disable_tcp_keep_alive) + :material-plus: [tcp_keep_alive](#tcp_keep_alive) + :material-plus: [tcp_keep_alive_interval](#tcp_keep_alive_interval) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [domain_resolver](#domain_resolver) @@ -29,8 +35,11 @@ icon: material/new-box "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, + "disable_tcp_keep_alive": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, - + "domain_resolver": "", // or {} "network_strategy": "", "network_type": [], @@ -112,6 +121,30 @@ Enable TCP Fast Open. Enable TCP Multi Path. +#### disable_tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + +Disable TCP keep alive. + +#### tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + + Default value changed from `10m` to `5m`. + +TCP keep-alive initial period. + +`5m` will be used by default. + +#### tcp_keep_alive_interval + +!!! question "Since sing-box 1.13.0" + +TCP keep-alive interval. + +`75s` will be used by default. + #### udp_fragment Enable UDP fragmentation. diff --git a/docs/configuration/shared/dial.zh.md b/docs/configuration/shared/dial.zh.md index babb43e98..acd622137 100644 --- a/docs/configuration/shared/dial.zh.md +++ b/docs/configuration/shared/dial.zh.md @@ -2,6 +2,12 @@ icon: material/new-box --- +!!! quote "sing-box 1.13.0 中的更改" + + :material-plus: [disable_tcp_keep_alive](#disable_tcp_keep_alive) + :material-plus: [tcp_keep_alive](#tcp_keep_alive) + :material-plus: [tcp_keep_alive_interval](#tcp_keep_alive_interval) + !!! quote "sing-box 1.12.0 中的更改" :material-plus: [domain_resolver](#domain_resolver) @@ -29,7 +35,11 @@ icon: material/new-box "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, + "disable_tcp_keep_alive": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, + "domain_resolver": "", // 或 {} "network_strategy": "", "network_type": [], @@ -109,6 +119,30 @@ icon: material/new-box 启用 TCP Multi Path。 +#### disable_tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + +禁用 TCP keep alive。 + +#### tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + + 默认值从 `10m` 更改为 `5m`。 + +TCP keep-alive 初始周期。 + +默认使用 `5m`。 + +#### tcp_keep_alive_interval + +!!! question "自 sing-box 1.13.0 起" + +TCP keep-alive 间隔。 + +默认使用 `75s`。 + #### udp_fragment 启用 UDP 分段。 diff --git a/docs/configuration/shared/listen.md b/docs/configuration/shared/listen.md index 4040e42f0..38a3749cf 100644 --- a/docs/configuration/shared/listen.md +++ b/docs/configuration/shared/listen.md @@ -2,6 +2,11 @@ icon: material/new-box --- +!!! quote "Changes in sing-box 1.13.0" + + :material-plus: [disable_tcp_keep_alive](#disable_tcp_keep_alive) + :material-alert: [tcp_keep_alive](#tcp_keep_alive) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [netns](#netns) @@ -29,6 +34,9 @@ icon: material/new-box "netns": "", "tcp_fast_open": false, "tcp_multi_path": false, + "disable_tcp_keep_alive": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, "udp_timeout": "", "detour": "", @@ -101,6 +109,28 @@ Enable TCP Fast Open. Enable TCP Multi Path. +#### disable_tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + +Disable TCP keep alive. + +#### tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + + Default value changed from `10m` to `5m`. + +TCP keep alive initial period. + +`5m` will be used by default. + +#### tcp_keep_alive_interval + +TCP keep-alive interval. + +`75s` will be used by default. + #### udp_fragment Enable UDP fragmentation. diff --git a/docs/configuration/shared/listen.zh.md b/docs/configuration/shared/listen.zh.md index cd12036ca..8893f37b3 100644 --- a/docs/configuration/shared/listen.zh.md +++ b/docs/configuration/shared/listen.zh.md @@ -2,6 +2,11 @@ icon: material/new-box --- +!!! quote "sing-box 1.13.0 中的更改" + + :material-plus: [disable_tcp_keep_alive](#disable_tcp_keep_alive) + :material-alert: [tcp_keep_alive](#tcp_keep_alive) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [netns](#netns) @@ -29,6 +34,9 @@ icon: material/new-box "netns": "", "tcp_fast_open": false, "tcp_multi_path": false, + "disable_tcp_keep_alive": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, "udp_timeout": "", "detour": "", @@ -101,6 +109,28 @@ icon: material/new-box 启用 TCP Multi Path。 +#### disable_tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + +禁用 TCP keep alive。 + +#### tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + + 默认值从 `10m` 更改为 `5m`。 + +TCP keep alive 初始周期。 + +默认使用 `5m`。 + +#### tcp_keep_alive_interval + +TCP keep-alive 间隔。 + +默认使用 `75s`。 + #### udp_fragment 启用 UDP 分段。 diff --git a/option/inbound.go b/option/inbound.go index 64ded9b1c..42930eccb 100644 --- a/option/inbound.go +++ b/option/inbound.go @@ -65,6 +65,7 @@ type ListenOptions struct { RoutingMark FwMark `json:"routing_mark,omitempty"` ReuseAddr bool `json:"reuse_addr,omitempty"` NetNs string `json:"netns,omitempty"` + DisableTCPKeepAlive bool `json:"disable_tcp_keep_alive,omitempty"` TCPKeepAlive badoption.Duration `json:"tcp_keep_alive,omitempty"` TCPKeepAliveInterval badoption.Duration `json:"tcp_keep_alive_interval,omitempty"` TCPFastOpen bool `json:"tcp_fast_open,omitempty"` diff --git a/option/outbound.go b/option/outbound.go index 2520d000f..b5c52fa2d 100644 --- a/option/outbound.go +++ b/option/outbound.go @@ -65,24 +65,27 @@ type DialerOptionsWrapper interface { } type DialerOptions struct { - Detour string `json:"detour,omitempty"` - BindInterface string `json:"bind_interface,omitempty"` - Inet4BindAddress *badoption.Addr `json:"inet4_bind_address,omitempty"` - Inet6BindAddress *badoption.Addr `json:"inet6_bind_address,omitempty"` - ProtectPath string `json:"protect_path,omitempty"` - RoutingMark FwMark `json:"routing_mark,omitempty"` - ReuseAddr bool `json:"reuse_addr,omitempty"` - NetNs string `json:"netns,omitempty"` - ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"` - TCPFastOpen bool `json:"tcp_fast_open,omitempty"` - TCPMultiPath bool `json:"tcp_multi_path,omitempty"` - UDPFragment *bool `json:"udp_fragment,omitempty"` - UDPFragmentDefault bool `json:"-"` - DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` - NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"` - NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"` - FallbackNetworkType badoption.Listable[InterfaceType] `json:"fallback_network_type,omitempty"` - FallbackDelay badoption.Duration `json:"fallback_delay,omitempty"` + Detour string `json:"detour,omitempty"` + BindInterface string `json:"bind_interface,omitempty"` + Inet4BindAddress *badoption.Addr `json:"inet4_bind_address,omitempty"` + Inet6BindAddress *badoption.Addr `json:"inet6_bind_address,omitempty"` + ProtectPath string `json:"protect_path,omitempty"` + RoutingMark FwMark `json:"routing_mark,omitempty"` + ReuseAddr bool `json:"reuse_addr,omitempty"` + NetNs string `json:"netns,omitempty"` + ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"` + TCPFastOpen bool `json:"tcp_fast_open,omitempty"` + TCPMultiPath bool `json:"tcp_multi_path,omitempty"` + DisableTCPKeepAlive bool `json:"disable_tcp_keep_alive,omitempty"` + TCPKeepAlive badoption.Duration `json:"tcp_keep_alive,omitempty"` + TCPKeepAliveInterval badoption.Duration `json:"tcp_keep_alive_interval,omitempty"` + UDPFragment *bool `json:"udp_fragment,omitempty"` + UDPFragmentDefault bool `json:"-"` + DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` + NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"` + NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"` + FallbackNetworkType badoption.Listable[InterfaceType] `json:"fallback_network_type,omitempty"` + FallbackDelay badoption.Duration `json:"fallback_delay,omitempty"` // Deprecated: migrated to domain resolver DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`