diff --git a/docs/changelog.md b/docs/changelog.md index e95fc2989..47e772c4b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,8 +4,16 @@ icon: material/alert-decagram #### 1.13.0-beta.7 +* Add fallback routing rule for `auto_redirect` **1** * Fixes and improvements +**1**: + +Adds a fallback iproute2 rule checked after system default rules (32766: main, 32767: default), +ensuring traffic is routed to the sing-box table when no route is found in system tables. + +The rule index can be customized via `auto_redirect_iproute2_fallback_rule_index` (default: 32768). + #### 1.13.0-beta.6 * Update uTLS to v1.8.2 **1** diff --git a/docs/configuration/inbound/tun.md b/docs/configuration/inbound/tun.md index 39393f425..7e67e488c 100644 --- a/docs/configuration/inbound/tun.md +++ b/docs/configuration/inbound/tun.md @@ -6,7 +6,8 @@ icon: material/new-box :material-plus: [auto_redirect_reset_mark](#auto_redirect_reset_mark) :material-plus: [auto_redirect_nfqueue](#auto_redirect_nfqueue) - :material-plus: [exclude_mptcp](#exclude_mptcp) + :material-plus: [exclude_mptcp](#exclude_mptcp) + :material-plus: [auto_redirect_iproute2_fallback_rule_index](#auto_redirect_iproute2_fallback_rule_index) !!! quote "Changes in sing-box 1.12.0" @@ -71,6 +72,7 @@ icon: material/new-box "auto_redirect_output_mark": "0x2024", "auto_redirect_reset_mark": "0x2025", "auto_redirect_nfqueue": 100, + "auto_redirect_iproute2_fallback_rule_index": 32768, "exclude_mptcp": false, "loopback_address": [ "10.7.0.1" @@ -303,6 +305,17 @@ NFQueue number used by `auto_redirect` pre-matching. `100` is used by default. +#### auto_redirect_iproute2_fallback_rule_index + +!!! question "Since sing-box 1.12.18" + +Linux iproute2 fallback rule index generated by `auto_redirect`. + +This rule is checked after system default rules (32766: main, 32767: default), +routing traffic to the sing-box table only when no route is found in system tables. + +`32768` is used by default. + #### exclude_mptcp !!! question "Since sing-box 1.13.0" diff --git a/docs/configuration/inbound/tun.zh.md b/docs/configuration/inbound/tun.zh.md index fa0c5d913..d8520aedb 100644 --- a/docs/configuration/inbound/tun.zh.md +++ b/docs/configuration/inbound/tun.zh.md @@ -6,7 +6,8 @@ icon: material/new-box :material-plus: [auto_redirect_reset_mark](#auto_redirect_reset_mark) :material-plus: [auto_redirect_nfqueue](#auto_redirect_nfqueue) - :material-plus: [exclude_mptcp](#exclude_mptcp) + :material-plus: [exclude_mptcp](#exclude_mptcp) + :material-plus: [auto_redirect_iproute2_fallback_rule_index](#auto_redirect_iproute2_fallback_rule_index) !!! quote "sing-box 1.12.0 中的更改" @@ -71,6 +72,7 @@ icon: material/new-box "auto_redirect_output_mark": "0x2024", "auto_redirect_reset_mark": "0x2025", "auto_redirect_nfqueue": 100, + "auto_redirect_iproute2_fallback_rule_index": 32768, "exclude_mptcp": false, "loopback_address": [ "10.7.0.1" @@ -302,13 +304,24 @@ tun 接口的 IPv6 前缀。 默认使用 `100`。 +#### auto_redirect_iproute2_fallback_rule_index + +!!! question "自 sing-box 1.12.18 起" + +`auto_redirect` 生成的 iproute2 回退规则索引。 + +此规则在系统默认规则(32766: main,32767: default)之后检查, +仅当系统路由表中未找到路由时才将流量路由到 sing-box 路由表。 + +默认使用 `32768`。 + #### exclude_mptcp !!! question "自 sing-box 1.13.0 起" !!! quote "" - 仅支持 Linux,且需要 nftables,`auto_route` 和 `auto_redirect` 已启用。 + 仅支持 Linux,且需要 nftables,`auto_route` 和 `auto_redirect` 已启用。 由于协议限制,MPTCP 无法被透明代理。 diff --git a/go.mod b/go.mod index c02c35fd6..624165349 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/sagernet/sing-shadowsocks v0.2.8 github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 - github.com/sagernet/sing-tun v0.8.0-beta.14 + github.com/sagernet/sing-tun v0.8.0-beta.15 github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 github.com/sagernet/smux v1.5.50-sing-box-mod.1 github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.6 diff --git a/go.sum b/go.sum index 1b066bd60..e28e16bda 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w= github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA= -github.com/sagernet/sing-tun v0.8.0-beta.14 h1:LlIhiynP1aggwDYeHDa+JeJAuptYy+OtQU+hPiHTXbY= -github.com/sagernet/sing-tun v0.8.0-beta.14/go.mod h1:+HAK/y9GZljdT0KYKMYDR8MjjqnqDDQZYp5ZZQoRzS8= +github.com/sagernet/sing-tun v0.8.0-beta.15 h1:R5PMHCXuSUs5g6aor4UhxfaIx+t6yofAYB9YAea7UZM= +github.com/sagernet/sing-tun v0.8.0-beta.15/go.mod h1:+HAK/y9GZljdT0KYKMYDR8MjjqnqDDQZYp5ZZQoRzS8= github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o= github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY= github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478= diff --git a/option/tun.go b/option/tun.go index 48989c9f9..72b6e456b 100644 --- a/option/tun.go +++ b/option/tun.go @@ -11,36 +11,37 @@ import ( ) type TunInboundOptions struct { - InterfaceName string `json:"interface_name,omitempty"` - MTU uint32 `json:"mtu,omitempty"` - Address badoption.Listable[netip.Prefix] `json:"address,omitempty"` - AutoRoute bool `json:"auto_route,omitempty"` - IPRoute2TableIndex int `json:"iproute2_table_index,omitempty"` - IPRoute2RuleIndex int `json:"iproute2_rule_index,omitempty"` - AutoRedirect bool `json:"auto_redirect,omitempty"` - AutoRedirectInputMark FwMark `json:"auto_redirect_input_mark,omitempty"` - AutoRedirectOutputMark FwMark `json:"auto_redirect_output_mark,omitempty"` - AutoRedirectResetMark FwMark `json:"auto_redirect_reset_mark,omitempty"` - AutoRedirectNFQueue uint16 `json:"auto_redirect_nfqueue,omitempty"` - ExcludeMPTCP bool `json:"exclude_mptcp,omitempty"` - LoopbackAddress badoption.Listable[netip.Addr] `json:"loopback_address,omitempty"` - StrictRoute bool `json:"strict_route,omitempty"` - RouteAddress badoption.Listable[netip.Prefix] `json:"route_address,omitempty"` - RouteAddressSet badoption.Listable[string] `json:"route_address_set,omitempty"` - RouteExcludeAddress badoption.Listable[netip.Prefix] `json:"route_exclude_address,omitempty"` - RouteExcludeAddressSet badoption.Listable[string] `json:"route_exclude_address_set,omitempty"` - IncludeInterface badoption.Listable[string] `json:"include_interface,omitempty"` - ExcludeInterface badoption.Listable[string] `json:"exclude_interface,omitempty"` - IncludeUID badoption.Listable[uint32] `json:"include_uid,omitempty"` - IncludeUIDRange badoption.Listable[string] `json:"include_uid_range,omitempty"` - ExcludeUID badoption.Listable[uint32] `json:"exclude_uid,omitempty"` - ExcludeUIDRange badoption.Listable[string] `json:"exclude_uid_range,omitempty"` - IncludeAndroidUser badoption.Listable[int] `json:"include_android_user,omitempty"` - IncludePackage badoption.Listable[string] `json:"include_package,omitempty"` - ExcludePackage badoption.Listable[string] `json:"exclude_package,omitempty"` - UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"` - Stack string `json:"stack,omitempty"` - Platform *TunPlatformOptions `json:"platform,omitempty"` + InterfaceName string `json:"interface_name,omitempty"` + MTU uint32 `json:"mtu,omitempty"` + Address badoption.Listable[netip.Prefix] `json:"address,omitempty"` + AutoRoute bool `json:"auto_route,omitempty"` + IPRoute2TableIndex int `json:"iproute2_table_index,omitempty"` + IPRoute2RuleIndex int `json:"iproute2_rule_index,omitempty"` + AutoRedirect bool `json:"auto_redirect,omitempty"` + AutoRedirectInputMark FwMark `json:"auto_redirect_input_mark,omitempty"` + AutoRedirectOutputMark FwMark `json:"auto_redirect_output_mark,omitempty"` + AutoRedirectResetMark FwMark `json:"auto_redirect_reset_mark,omitempty"` + AutoRedirectNFQueue uint16 `json:"auto_redirect_nfqueue,omitempty"` + AutoRedirectFallbackRuleIndex int `json:"auto_redirect_iproute2_fallback_rule_index,omitempty"` + ExcludeMPTCP bool `json:"exclude_mptcp,omitempty"` + LoopbackAddress badoption.Listable[netip.Addr] `json:"loopback_address,omitempty"` + StrictRoute bool `json:"strict_route,omitempty"` + RouteAddress badoption.Listable[netip.Prefix] `json:"route_address,omitempty"` + RouteAddressSet badoption.Listable[string] `json:"route_address_set,omitempty"` + RouteExcludeAddress badoption.Listable[netip.Prefix] `json:"route_exclude_address,omitempty"` + RouteExcludeAddressSet badoption.Listable[string] `json:"route_exclude_address_set,omitempty"` + IncludeInterface badoption.Listable[string] `json:"include_interface,omitempty"` + ExcludeInterface badoption.Listable[string] `json:"exclude_interface,omitempty"` + IncludeUID badoption.Listable[uint32] `json:"include_uid,omitempty"` + IncludeUIDRange badoption.Listable[string] `json:"include_uid_range,omitempty"` + ExcludeUID badoption.Listable[uint32] `json:"exclude_uid,omitempty"` + ExcludeUIDRange badoption.Listable[string] `json:"exclude_uid_range,omitempty"` + IncludeAndroidUser badoption.Listable[int] `json:"include_android_user,omitempty"` + IncludePackage badoption.Listable[string] `json:"include_package,omitempty"` + ExcludePackage badoption.Listable[string] `json:"exclude_package,omitempty"` + UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"` + Stack string `json:"stack,omitempty"` + Platform *TunPlatformOptions `json:"platform,omitempty"` InboundOptions // Deprecated: removed diff --git a/protocol/tun/inbound.go b/protocol/tun/inbound.go index 2ab68b3ea..70f820442 100644 --- a/protocol/tun/inbound.go +++ b/protocol/tun/inbound.go @@ -174,6 +174,10 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo if ruleIndex == 0 { ruleIndex = tun.DefaultIPRoute2RuleIndex } + autoRedirectFallbackRuleIndex := options.AutoRedirectFallbackRuleIndex + if autoRedirectFallbackRuleIndex == 0 { + autoRedirectFallbackRuleIndex = tun.DefaultIPRoute2AutoRedirectFallbackRuleIndex + } inputMark := uint32(options.AutoRedirectInputMark) if inputMark == 0 { inputMark = tun.DefaultAutoRedirectInputMark @@ -200,35 +204,36 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo logger: logger, inboundOptions: options.InboundOptions, tunOptions: tun.Options{ - Name: options.InterfaceName, - MTU: tunMTU, - GSO: enableGSO, - Inet4Address: inet4Address, - Inet6Address: inet6Address, - AutoRoute: options.AutoRoute, - IPRoute2TableIndex: tableIndex, - IPRoute2RuleIndex: ruleIndex, - AutoRedirectInputMark: inputMark, - AutoRedirectOutputMark: outputMark, - AutoRedirectResetMark: resetMark, - AutoRedirectNFQueue: nfQueue, - ExcludeMPTCP: options.ExcludeMPTCP, - Inet4LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is4), - Inet6LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is6), - StrictRoute: options.StrictRoute, - IncludeInterface: options.IncludeInterface, - ExcludeInterface: options.ExcludeInterface, - Inet4RouteAddress: inet4RouteAddress, - Inet6RouteAddress: inet6RouteAddress, - Inet4RouteExcludeAddress: inet4RouteExcludeAddress, - Inet6RouteExcludeAddress: inet6RouteExcludeAddress, - IncludeUID: includeUID, - ExcludeUID: excludeUID, - IncludeAndroidUser: options.IncludeAndroidUser, - IncludePackage: options.IncludePackage, - ExcludePackage: options.ExcludePackage, - InterfaceMonitor: networkManager.InterfaceMonitor(), - EXP_MultiPendingPackets: multiPendingPackets, + Name: options.InterfaceName, + MTU: tunMTU, + GSO: enableGSO, + Inet4Address: inet4Address, + Inet6Address: inet6Address, + AutoRoute: options.AutoRoute, + IPRoute2TableIndex: tableIndex, + IPRoute2RuleIndex: ruleIndex, + IPRoute2AutoRedirectFallbackRuleIndex: autoRedirectFallbackRuleIndex, + AutoRedirectInputMark: inputMark, + AutoRedirectOutputMark: outputMark, + AutoRedirectResetMark: resetMark, + AutoRedirectNFQueue: nfQueue, + ExcludeMPTCP: options.ExcludeMPTCP, + Inet4LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is4), + Inet6LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is6), + StrictRoute: options.StrictRoute, + IncludeInterface: options.IncludeInterface, + ExcludeInterface: options.ExcludeInterface, + Inet4RouteAddress: inet4RouteAddress, + Inet6RouteAddress: inet6RouteAddress, + Inet4RouteExcludeAddress: inet4RouteExcludeAddress, + Inet6RouteExcludeAddress: inet6RouteExcludeAddress, + IncludeUID: includeUID, + ExcludeUID: excludeUID, + IncludeAndroidUser: options.IncludeAndroidUser, + IncludePackage: options.IncludePackage, + ExcludePackage: options.ExcludePackage, + InterfaceMonitor: networkManager.InterfaceMonitor(), + EXP_MultiPendingPackets: multiPendingPackets, }, udpTimeout: udpTimeout, stack: options.Stack,