Migrate udp_timeout from seconds to duration format

This commit is contained in:
世界 2023-12-20 19:55:14 +08:00
parent d6eddce420
commit 55b1bcc6a5
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
12 changed files with 83 additions and 57 deletions

View file

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

View file

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

View file

@ -7,7 +7,7 @@
"tcp_fast_open": false, "tcp_fast_open": false,
"tcp_multi_path": false, "tcp_multi_path": false,
"udp_fragment": false, "udp_fragment": false,
"udp_timeout": 300, "udp_timeout": "5m",
"detour": "another-in", "detour": "another-in",
"sniff": false, "sniff": false,
"sniff_override_destination": false, "sniff_override_destination": false,
@ -20,12 +20,12 @@
### Fields ### Fields
| Field | Available Context | | Field | Available Context |
|--------------------------------|-------------------------------------------------------------------| |--------------------------------|---------------------------------------------------------|
| `listen` | Needs to listen on TCP or UDP. | | `listen` | Needs to listen on TCP or UDP. |
| `listen_port` | 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_fast_open` | Needs to listen on TCP. |
| `tcp_multi_path` | 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_timeout` | Needs to assemble UDP connections. |
| `udp_disable_domain_unmapping` | Needs to listen on UDP and accept domain UDP addresses. | | `udp_disable_domain_unmapping` | Needs to listen on UDP and accept domain UDP addresses. |
#### listen #### listen
@ -56,7 +56,9 @@ Enable UDP fragmentation.
#### udp_timeout #### 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 #### detour

View file

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

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"net" "net"
"net/netip" "net/netip"
"time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant" 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.overrideOption = 3
inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort} inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
} }
var udpTimeout int64 var udpTimeout time.Duration
if options.UDPTimeout != 0 { if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout udpTimeout = time.Duration(options.UDPTimeout)
} else { } 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.connHandler = inbound
inbound.packetHandler = inbound inbound.packetHandler = inbound
inbound.packetUpstream = inbound.udpNat inbound.packetUpstream = inbound.udpNat

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"net" "net"
"os" "os"
"time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/mux" "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 return nil, err
} }
var udpTimeout int64 var udpTimeout time.Duration
if options.UDPTimeout != 0 { if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout udpTimeout = time.Duration(options.UDPTimeout)
} else { } else {
udpTimeout = int64(C.UDPTimeout.Seconds()) udpTimeout = C.UDPTimeout
} }
switch { switch {
case options.Method == shadowsocks.MethodNone: 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): 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): 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: default:
err = E.New("unsupported method: ", options.Method) err = E.New("unsupported method: ", options.Method)
} }

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import (
"net" "net"
"net/netip" "net/netip"
"syscall" "syscall"
"time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/redir" "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, listenOptions: options.ListenOptions,
}, },
} }
var udpTimeout int64 var udpTimeout time.Duration
if options.UDPTimeout != 0 { if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout udpTimeout = time.Duration(options.UDPTimeout)
} else { } else {
udpTimeout = int64(C.UDPTimeout.Seconds()) udpTimeout = C.UDPTimeout
} }
tproxy.connHandler = tproxy tproxy.connHandler = tproxy
tproxy.oobPacketHandler = 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 tproxy.packetUpstream = tproxy.udpNat
return tproxy return tproxy
} }

View file

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

View file

@ -1,6 +1,8 @@
package option package option
import ( import (
"time"
"github.com/sagernet/sing-box/common/json" "github.com/sagernet/sing-box/common/json"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
@ -134,9 +136,21 @@ type ListenOptions struct {
TCPMultiPath bool `json:"tcp_multi_path,omitempty"` TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
UDPFragment *bool `json:"udp_fragment,omitempty"` UDPFragment *bool `json:"udp_fragment,omitempty"`
UDPFragmentDefault bool `json:"-"` UDPFragmentDefault bool `json:"-"`
UDPTimeout int64 `json:"udp_timeout,omitempty"` UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
ProxyProtocol bool `json:"proxy_protocol,omitempty"` ProxyProtocol bool `json:"proxy_protocol,omitempty"`
ProxyProtocolAcceptNoHeader bool `json:"proxy_protocol_accept_no_header,omitempty"` ProxyProtocolAcceptNoHeader bool `json:"proxy_protocol_accept_no_header,omitempty"`
Detour string `json:"detour,omitempty"` Detour string `json:"detour,omitempty"`
InboundOptions 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))
}

View file

@ -23,7 +23,7 @@ type TunInboundOptions struct {
IncludePackage Listable[string] `json:"include_package,omitempty"` IncludePackage Listable[string] `json:"include_package,omitempty"`
ExcludePackage Listable[string] `json:"exclude_package,omitempty"` ExcludePackage Listable[string] `json:"exclude_package,omitempty"`
EndpointIndependentNat bool `json:"endpoint_independent_nat,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"` Stack string `json:"stack,omitempty"`
Platform *TunPlatformOptions `json:"platform,omitempty"` Platform *TunPlatformOptions `json:"platform,omitempty"`
InboundOptions InboundOptions