From ff7d8c9ba8da1d86609d6b6c80bb374486289881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 22 Jun 2024 14:11:49 +0800 Subject: [PATCH] Add custom options for TUN `auto-route` and `auto-redirect` --- docs/configuration/inbound/tun.md | 82 +++++++++++++++++++++------- docs/configuration/inbound/tun.zh.md | 80 ++++++++++++++++++++------- inbound/tun.go | 4 +- option/tun.go | 36 +++++++++++- 4 files changed, 158 insertions(+), 44 deletions(-) diff --git a/docs/configuration/inbound/tun.md b/docs/configuration/inbound/tun.md index 1e2bf400..812b20d1 100644 --- a/docs/configuration/inbound/tun.md +++ b/docs/configuration/inbound/tun.md @@ -13,7 +13,11 @@ icon: material/new-box :material-plus: [route_exclude_address](#route_address) :material-delete-clock: [inet4_route_exclude_address](#inet4_route_exclude_address) :material-delete-clock: [inet6_route_exclude_address](#inet6_route_exclude_address) + :material-plus: [iproute2_table_index](#iproute2_table_index) + :material-plus: [iproute2_rule_index](#iproute2_table_index) :material-plus: [auto_redirect](#auto_redirect) + :material-plus: [auto_redirect_input_mark](#auto_redirect_input_mark) + :material-plus: [auto_redirect_output_mark](#auto_redirect_output_mark) :material-plus: [route_address_set](#route_address_set) :material-plus: [route_exclude_address_set](#route_address_set) @@ -53,8 +57,12 @@ icon: material/new-box "mtu": 9000, "gso": false, "auto_route": true, - "strict_route": true, + "iproute2_table_index": 2022, + "iproute2_rule_index": 9000, "auto_redirect": false, + "auto_redirect_input_mark": "0x2023", + "auto_redirect_output_mark": "0x2024", + "strict_route": true, "route_address": [ "0.0.0.0/1", "128.0.0.0/1", @@ -129,8 +137,8 @@ icon: material/new-box "match_domain": [] } }, - - ... // Listen Fields + ... + // Listen Fields } ``` @@ -180,7 +188,7 @@ The maximum transmission unit. !!! quote "" - Only supported on Linux. + Only supported on Linux with `auto_route` enabled. Enable generic segmentation offload. @@ -196,24 +204,21 @@ Set the default route to the Tun. By default, VPN takes precedence over tun. To make tun go through VPN, enable `route.override_android_vpn`. -#### strict_route +#### iproute2_table_index -Enforce strict routing rules when `auto_route` is enabled: +!!! question "Since sing-box 1.10.0" -*In Linux*: +Linux iproute2 table index generated by `auto_route`. -* Let unsupported network unreachable -* Make ICMP traffic route to tun instead of upstream interfaces -* Route all connections to tun +`2022` is used by default. -It prevents IP address leaks and makes DNS hijacking work on Android. +#### iproute2_rule_index -*In Windows*: +!!! question "Since sing-box 1.10.0" -* Add firewall rules to prevent DNS leak caused by - Windows' [ordinary multihomed DNS resolution behavior](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29) +Linux iproute2 rule start index generated by `auto_route`. -It may prevent some applications (such as VirtualBox) from working properly in certain situations. +`9000` is used by default. #### auto_redirect @@ -234,6 +239,41 @@ use [VPNHotspot](https://github.com/Mygod/VPNHotspot). `auto_route` with `auto_redirect` now works as expected on routers **without intervention**. +#### auto_redirect_input_mark + +!!! question "Since sing-box 1.10.0" + +Connection input mark used by `route_address_set` and `route_exclude_address_set`. + +`0x2023` is used by default. + +#### auto_redirect_output_mark + +!!! question "Since sing-box 1.10.0" + +Connection output mark used by `route_address_set` and `route_exclude_address_set`. + +`0x2024` is used by default. + +#### strict_route + +Enforce strict routing rules when `auto_route` is enabled: + +*In Linux*: + +* Let unsupported network unreachable +* Make ICMP traffic route to tun instead of upstream interfaces +* Route all connections to tun + +It prevents IP address leaks and makes DNS hijacking work on Android. + +*In Windows*: + +* Add firewall rules to prevent DNS leak caused by + Windows' [ordinary multihomed DNS resolution behavior](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29) + +It may prevent some applications (such as VirtualBox) from working properly in certain situations. + #### route_address !!! question "Since sing-box 1.10.0" @@ -244,7 +284,8 @@ Use custom routes instead of default when `auto_route` is enabled. !!! failure "Deprecated in sing-box 1.10.0" - `inet4_route_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_address](#route_address) instead. +`inet4_route_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_address](#route_address) +instead. Use custom routes instead of default when `auto_route` is enabled. @@ -252,7 +293,8 @@ Use custom routes instead of default when `auto_route` is enabled. !!! failure "Deprecated in sing-box 1.10.0" - `inet6_route_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_address](#route_address) instead. +`inet6_route_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_address](#route_address) +instead. Use custom routes instead of default when `auto_route` is enabled. @@ -266,7 +308,8 @@ Exclude custom routes when `auto_route` is enabled. !!! failure "Deprecated in sing-box 1.10.0" - `inet4_route_exclude_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_exclude_address](#route_exclude_address) instead. +`inet4_route_exclude_address` is deprecated and will be removed in sing-box 1.11.0, please +use [route_exclude_address](#route_exclude_address) instead. Exclude custom routes when `auto_route` is enabled. @@ -274,7 +317,8 @@ Exclude custom routes when `auto_route` is enabled. !!! failure "Deprecated in sing-box 1.10.0" - `inet6_route_exclude_address` is deprecated and will be removed in sing-box 1.11.0, please use [route_exclude_address](#route_exclude_address) instead. +`inet6_route_exclude_address` is deprecated and will be removed in sing-box 1.11.0, please +use [route_exclude_address](#route_exclude_address) instead. Exclude custom routes when `auto_route` is enabled. diff --git a/docs/configuration/inbound/tun.zh.md b/docs/configuration/inbound/tun.zh.md index 5b1d35af..bff493d4 100644 --- a/docs/configuration/inbound/tun.zh.md +++ b/docs/configuration/inbound/tun.zh.md @@ -12,8 +12,12 @@ icon: material/new-box :material-delete-clock: [inet6_route_address](#inet6_route_address) :material-plus: [route_exclude_address](#route_address) :material-delete-clock: [inet4_route_exclude_address](#inet4_route_exclude_address) - :material-delete-clock: [inet6_route_exclude_address](#inet6_route_exclude_address) + :material-delete-clock: [inet6_route_exclude_address](#inet6_route_exclude_address) + :material-plus: [iproute2_table_index](#iproute2_table_index) + :material-plus: [iproute2_rule_index](#iproute2_table_index) :material-plus: [auto_redirect](#auto_redirect) + :material-plus: [auto_redirect_input_mark](#auto_redirect_input_mark) + :material-plus: [auto_redirect_output_mark](#auto_redirect_output_mark) :material-plus: [route_address_set](#route_address_set) :material-plus: [route_exclude_address_set](#route_address_set) @@ -53,8 +57,12 @@ icon: material/new-box "mtu": 9000, "gso": false, "auto_route": true, - "strict_route": true, + "iproute2_table_index": 2022, + "iproute2_rule_index": 9000, "auto_redirect": false, + "auto_redirect_input_mark": "0x2023", + "auto_redirect_output_mark": "0x2024", + "strict_route": true, "route_address": [ "0.0.0.0/1", "128.0.0.0/1", @@ -200,6 +208,56 @@ tun 接口的 IPv6 前缀。 VPN 默认优先于 tun。要使 tun 经过 VPN,启用 `route.override_android_vpn`。 +#### iproute2_table_index + +!!! question "自 sing-box 1.10.0 起" + +`auto_route` 生成的 iproute2 路由表索引。 + +默认使用 `2022`。 + +#### iproute2_rule_index + +!!! question "自 sing-box 1.10.0 起" + +`auto_route` 生成的 iproute2 规则起始索引。 + +默认使用 `9000`。 + +#### auto_redirect + +!!! question "自 sing-box 1.10.0 起" + +!!! quote "" + + 仅支持 Linux,且需要 `auto_route` 已启用。 + +自动配置 iptables 以重定向 TCP 连接。 + +*在 Android 中*: + +仅转发本地 IPv4 连接。 要通过热点或中继共享您的 VPN 连接,请使用 [VPNHotspot](https://github.com/Mygod/VPNHotspot)。 + +*在 Linux 中*: + +带有 `auto_redirect `的 `auto_route` 现在可以在路由器上按预期工作,**无需干预**。 + +#### auto_redirect_input_mark + +!!! question "自 sing-box 1.10.0 起" + +`route_address_set` 和 `route_exclude_address_set` 使用的连接输入标记。 + +默认使用 `0x2023`。 + +#### auto_redirect_output_mark + +!!! question "自 sing-box 1.10.0 起" + +`route_address_set` 和 `route_exclude_address_set` 使用的连接输出标记。 + +默认使用 `0x2024`。 + #### strict_route 启用 `auto_route` 时执行严格的路由规则。 @@ -220,24 +278,6 @@ tun 接口的 IPv6 前缀。 它可能会使某些应用程序(如 VirtualBox)在某些情况下无法正常工作。 -#### auto_redirect - -!!! question "自 sing-box 1.10.0 起" - -!!! quote "" - - 仅支持 Linux。 - -自动配置 iptables 以重定向 TCP 连接。 - -*在 Android 中*: - -仅转发本地 IPv4 连接。 要通过热点或中继共享您的 VPN 连接,请使用 [VPNHotspot](https://github.com/Mygod/VPNHotspot)。 - -*在 Linux 中*: - -带有 `auto_redirect `的 `auto_route` 现在可以在路由器上按预期工作,**无需干预**。 - #### route_address !!! question "自 sing-box 1.10.0 起" diff --git a/inbound/tun.go b/inbound/tun.go index cb6a02c3..6cb65de2 100644 --- a/inbound/tun.go +++ b/inbound/tun.go @@ -141,11 +141,11 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger if ruleIndex == 0 { ruleIndex = tun.DefaultIPRoute2RuleIndex } - inputMark := options.AutoRedirectInputMark + inputMark := uint32(options.AutoRedirectInputMark) if inputMark == 0 { inputMark = tun.DefaultAutoRedirectInputMark } - outputMark := options.AutoRedirectOutputMark + outputMark := uint32(options.AutoRedirectOutputMark) if outputMark == 0 { outputMark = tun.DefaultAutoRedirectOutputMark } diff --git a/option/tun.go b/option/tun.go index cbc73e7d..dbb1bfea 100644 --- a/option/tun.go +++ b/option/tun.go @@ -1,6 +1,13 @@ package option -import "net/netip" +import ( + "net/netip" + "strconv" + + E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" + "github.com/sagernet/sing/common/json" +) type TunInboundOptions struct { InterfaceName string `json:"interface_name,omitempty"` @@ -11,8 +18,8 @@ type TunInboundOptions struct { IPRoute2TableIndex int `json:"iproute2_table_index,omitempty"` IPRoute2RuleIndex int `json:"iproute2_rule_index,omitempty"` AutoRedirect bool `json:"auto_redirect,omitempty"` - AutoRedirectInputMark uint32 `json:"auto_redirect_input_mark,omitempty"` - AutoRedirectOutputMark uint32 `json:"auto_redirect_output_mark,omitempty"` + AutoRedirectInputMark FwMark `json:"auto_redirect_input_mark,omitempty"` + AutoRedirectOutputMark FwMark `json:"auto_redirect_output_mark,omitempty"` StrictRoute bool `json:"strict_route,omitempty"` RouteAddress Listable[netip.Prefix] `json:"route_address,omitempty"` RouteAddressSet Listable[string] `json:"route_address_set,omitempty"` @@ -46,3 +53,26 @@ type TunInboundOptions struct { // Deprecated: merged to RouteExcludeAddress Inet6RouteExcludeAddress Listable[netip.Prefix] `json:"inet6_route_exclude_address,omitempty"` } + +type FwMark uint32 + +func (f FwMark) MarshalJSON() ([]byte, error) { + return json.Marshal(F.ToString("0x", strconv.FormatUint(uint64(f), 16))) +} + +func (f *FwMark) UnmarshalJSON(bytes []byte) error { + var stringValue string + err := json.Unmarshal(bytes, &stringValue) + if err != nil { + if rawErr := json.Unmarshal(bytes, (*uint32)(f)); rawErr == nil { + return nil + } + return E.Cause(err, "invalid number or string mark") + } + intValue, err := strconv.ParseUint(stringValue, 0, 32) + if err != nil { + return err + } + *f = FwMark(intValue) + return nil +}