Sfoglia il codice sorgente

Migrate `udp_timeout` from seconds to duration format

世界 1 anno fa
parent
commit
55b1bcc6a5

+ 1 - 0
docs/configuration/inbound/tun.md

@@ -29,6 +29,7 @@
     "fc00::/7"
   ],
   "endpoint_independent_nat": false,
+  "udp_timeout": "5m",
   "stack": "system",
   "include_interface": [
     "lan0"

+ 1 - 0
docs/configuration/inbound/tun.zh.md

@@ -29,6 +29,7 @@
     "fc00::/7"
   ],
   "endpoint_independent_nat": false,
+  "udp_timeout": "5m",
   "stack": "system",
   "include_interface": [
     "lan0"

+ 12 - 10
docs/configuration/shared/listen.md

@@ -7,7 +7,7 @@
   "tcp_fast_open": false,
   "tcp_multi_path": false,
   "udp_fragment": false,
-  "udp_timeout": 300,
+  "udp_timeout": "5m",
   "detour": "another-in",
   "sniff": false,
   "sniff_override_destination": false,
@@ -19,14 +19,14 @@
 
 ### Fields
 
-| Field                          | Available Context                                                 |
-|--------------------------------|-------------------------------------------------------------------|
-| `listen`                       | Needs to listen on TCP or UDP.                                    |
-| `listen_port`                  | Needs to listen on TCP or UDP.                                    |
-| `tcp_fast_open`                | Needs to listen on TCP.                                           |
-| `tcp_multi_path`               | Needs to listen on TCP.                                           |
-| `udp_timeout`                  | Needs to assemble UDP connections, currently Tun and Shadowsocks. |
-| `udp_disable_domain_unmapping` | Needs to listen on UDP and accept domain UDP addresses.           |
+| Field                          | Available Context                                       |
+|--------------------------------|---------------------------------------------------------|
+| `listen`                       | Needs to listen on TCP or UDP.                          |
+| `listen_port`                  | Needs to listen on TCP or UDP.                          |
+| `tcp_fast_open`                | Needs to listen on TCP.                                 |
+| `tcp_multi_path`               | Needs to listen on TCP.                                 |
+| `udp_timeout`                  | Needs to assemble UDP connections.                      |
+| `udp_disable_domain_unmapping` | Needs to listen on UDP and accept domain UDP addresses. |
 
 #### listen
 
@@ -56,7 +56,9 @@ Enable UDP fragmentation.
 
 #### udp_timeout
 
-UDP NAT expiration time in seconds, default is 300 (5 minutes).
+UDP NAT expiration time in seconds.
+
+`5m` is used by default.
 
 #### detour
 

+ 11 - 9
docs/configuration/shared/listen.zh.md

@@ -7,7 +7,7 @@
   "tcp_fast_open": false,
   "tcp_multi_path": false,
   "udp_fragment": false,
-  "udp_timeout": 300,
+  "udp_timeout": "5m",
   "detour": "another-in",
   "sniff": false,
   "sniff_override_destination": false,
@@ -18,13 +18,13 @@
 ```
 
 
-| 字段                                | 可用上下文                               |
-|-----------------------------------|-------------------------------------|
-| `listen`                          | 需要监听 TCP 或 UDP。                     |
-| `listen_port`                     | 需要监听 TCP 或 UDP。                     |
-| `tcp_fast_open`                   | 需要监听 TCP。                           |
-| `tcp_multi_path`                  | 需要监听 TCP。                           |
-| `udp_timeout`                     | 需要组装 UDP 连接, 当前为 Tun 和 Shadowsocks。 |
+| 字段               | 可用上下文           |
+|------------------|-----------------|
+| `listen`         | 需要监听 TCP 或 UDP。 |
+| `listen_port`    | 需要监听 TCP 或 UDP。 |
+| `tcp_fast_open`  | 需要监听 TCP。       |
+| `tcp_multi_path` | 需要监听 TCP。       |
+| `udp_timeout`    | 需要组装 UDP 连接。    |
 | 
 
 ### 字段
@@ -57,7 +57,9 @@
 
 #### udp_timeout
 
-UDP NAT 过期时间,以秒为单位,默认为 300(5 分钟)。
+UDP NAT 过期时间,以秒为单位。
+
+默认使用 `5m`。
 
 #### detour
 

+ 5 - 4
inbound/direct.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"net"
 	"net/netip"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	C "github.com/sagernet/sing-box/constant"
@@ -47,13 +48,13 @@ func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLog
 		inbound.overrideOption = 3
 		inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
 	}
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
-	inbound.udpNat = udpnat.New[netip.AddrPort](udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
+	inbound.udpNat = udpnat.New[netip.AddrPort](int64(udpTimeout.Seconds()), adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
 	inbound.connHandler = inbound
 	inbound.packetHandler = inbound
 	inbound.packetUpstream = inbound.udpNat

+ 7 - 6
inbound/shadowsocks.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"net"
 	"os"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/common/mux"
@@ -65,19 +66,19 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
 		return nil, err
 	}
 
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
 	switch {
 	case options.Method == shadowsocks.MethodNone:
-		inbound.service = shadowsocks.NewNoneService(options.UDPTimeout, inbound.upstreamContextHandler())
+		inbound.service = shadowsocks.NewNoneService(int64(udpTimeout.Seconds()), inbound.upstreamContextHandler())
 	case common.Contains(shadowaead.List, options.Method):
-		inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, udpTimeout, inbound.upstreamContextHandler())
+		inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, int64(udpTimeout.Seconds()), inbound.upstreamContextHandler())
 	case common.Contains(shadowaead_2022.List, options.Method):
-		inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, udpTimeout, inbound.upstreamContextHandler(), ntp.TimeFuncFromContext(ctx))
+		inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, int64(udpTimeout.Seconds()), inbound.upstreamContextHandler(), ntp.TimeFuncFromContext(ctx))
 	default:
 		err = E.New("unsupported method: ", options.Method)
 	}

+ 6 - 5
inbound/shadowsocks_multi.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"net"
 	"os"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/common/mux"
@@ -53,25 +54,25 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
 	if err != nil {
 		return nil, err
 	}
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
 	var service shadowsocks.MultiService[int]
 	if common.Contains(shadowaead_2022.List, options.Method) {
 		service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
 			options.Method,
 			options.Password,
-			udpTimeout,
+			int64(udpTimeout.Seconds()),
 			adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound),
 			ntp.TimeFuncFromContext(ctx),
 		)
 	} else if common.Contains(shadowaead.List, options.Method) {
 		service, err = shadowaead.NewMultiService[int](
 			options.Method,
-			udpTimeout,
+			int64(udpTimeout.Seconds()),
 			adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
 	} else {
 		return nil, E.New("unsupported method: " + options.Method)

+ 5 - 4
inbound/shadowsocks_relay.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"net"
 	"os"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/common/mux"
@@ -50,16 +51,16 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
 	if err != nil {
 		return nil, err
 	}
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
 	service, err := shadowaead_2022.NewRelayServiceWithPassword[int](
 		options.Method,
 		options.Password,
-		udpTimeout,
+		int64(udpTimeout.Seconds()),
 		adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound),
 	)
 	if err != nil {

+ 5 - 4
inbound/tproxy.go

@@ -5,6 +5,7 @@ import (
 	"net"
 	"net/netip"
 	"syscall"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/common/redir"
@@ -37,15 +38,15 @@ func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLog
 			listenOptions: options.ListenOptions,
 		},
 	}
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
 	tproxy.connHandler = tproxy
 	tproxy.oobPacketHandler = tproxy
-	tproxy.udpNat = udpnat.New[netip.AddrPort](udpTimeout, tproxy.upstreamContextHandler())
+	tproxy.udpNat = udpnat.New[netip.AddrPort](int64(udpTimeout.Seconds()), tproxy.upstreamContextHandler())
 	tproxy.packetUpstream = tproxy.udpNat
 	return tproxy
 }

+ 5 - 4
inbound/tun.go

@@ -5,6 +5,7 @@ import (
 	"net"
 	"strconv"
 	"strings"
+	"time"
 
 	"github.com/sagernet/sing-box/adapter"
 	C "github.com/sagernet/sing-box/constant"
@@ -42,11 +43,11 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
 	if tunMTU == 0 {
 		tunMTU = 9000
 	}
-	var udpTimeout int64
+	var udpTimeout time.Duration
 	if options.UDPTimeout != 0 {
-		udpTimeout = options.UDPTimeout
+		udpTimeout = time.Duration(options.UDPTimeout)
 	} else {
-		udpTimeout = int64(C.UDPTimeout.Seconds())
+		udpTimeout = C.UDPTimeout
 	}
 	includeUID := uidToRange(options.IncludeUID)
 	if len(options.IncludeUIDRange) > 0 {
@@ -92,7 +93,7 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
 			TableIndex:               2022,
 		},
 		endpointIndependentNat: options.EndpointIndependentNat,
-		udpTimeout:             udpTimeout,
+		udpTimeout:             int64(udpTimeout.Seconds()),
 		stack:                  options.Stack,
 		platformInterface:      platformInterface,
 		platformOptions:        common.PtrValueOrDefault(options.Platform),

+ 24 - 10
option/inbound.go

@@ -1,6 +1,8 @@
 package option
 
 import (
+	"time"
+
 	"github.com/sagernet/sing-box/common/json"
 	C "github.com/sagernet/sing-box/constant"
 	E "github.com/sagernet/sing/common/exceptions"
@@ -128,15 +130,27 @@ type InboundOptions struct {
 }
 
 type ListenOptions struct {
-	Listen                      *ListenAddress `json:"listen,omitempty"`
-	ListenPort                  uint16         `json:"listen_port,omitempty"`
-	TCPFastOpen                 bool           `json:"tcp_fast_open,omitempty"`
-	TCPMultiPath                bool           `json:"tcp_multi_path,omitempty"`
-	UDPFragment                 *bool          `json:"udp_fragment,omitempty"`
-	UDPFragmentDefault          bool           `json:"-"`
-	UDPTimeout                  int64          `json:"udp_timeout,omitempty"`
-	ProxyProtocol               bool           `json:"proxy_protocol,omitempty"`
-	ProxyProtocolAcceptNoHeader bool           `json:"proxy_protocol_accept_no_header,omitempty"`
-	Detour                      string         `json:"detour,omitempty"`
+	Listen                      *ListenAddress   `json:"listen,omitempty"`
+	ListenPort                  uint16           `json:"listen_port,omitempty"`
+	TCPFastOpen                 bool             `json:"tcp_fast_open,omitempty"`
+	TCPMultiPath                bool             `json:"tcp_multi_path,omitempty"`
+	UDPFragment                 *bool            `json:"udp_fragment,omitempty"`
+	UDPFragmentDefault          bool             `json:"-"`
+	UDPTimeout                  UDPTimeoutCompat `json:"udp_timeout,omitempty"`
+	ProxyProtocol               bool             `json:"proxy_protocol,omitempty"`
+	ProxyProtocolAcceptNoHeader bool             `json:"proxy_protocol_accept_no_header,omitempty"`
+	Detour                      string           `json:"detour,omitempty"`
 	InboundOptions
 }
+
+type UDPTimeoutCompat Duration
+
+func (u *UDPTimeoutCompat) UnmarshalJSON(data []byte) error {
+	var valueNumber int64
+	err := json.Unmarshal(data, &valueNumber)
+	if err == nil {
+		*u = UDPTimeoutCompat(time.Second * time.Duration(valueNumber))
+		return nil
+	}
+	return json.Unmarshal(data, (*Duration)(u))
+}

+ 1 - 1
option/tun.go

@@ -23,7 +23,7 @@ type TunInboundOptions struct {
 	IncludePackage           Listable[string]       `json:"include_package,omitempty"`
 	ExcludePackage           Listable[string]       `json:"exclude_package,omitempty"`
 	EndpointIndependentNat   bool                   `json:"endpoint_independent_nat,omitempty"`
-	UDPTimeout               int64                  `json:"udp_timeout,omitempty"`
+	UDPTimeout               UDPTimeoutCompat       `json:"udp_timeout,omitempty"`
 	Stack                    string                 `json:"stack,omitempty"`
 	Platform                 *TunPlatformOptions    `json:"platform,omitempty"`
 	InboundOptions