diff --git a/cmd/serenity/main.go b/cmd/serenity/main.go index 16258b9..49aeba9 100644 --- a/cmd/serenity/main.go +++ b/cmd/serenity/main.go @@ -5,7 +5,7 @@ import ( "os" "time" - box "github.com/sagernet/sing-box" + "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/include" _ "github.com/sagernet/sing-box/include" "github.com/sagernet/sing-box/log" diff --git a/docs/configuration/shared/rule-set.md b/docs/configuration/shared/rule-set.md index 9c495ff..8e09600 100644 --- a/docs/configuration/shared/rule-set.md +++ b/docs/configuration/shared/rule-set.md @@ -31,7 +31,7 @@ RuleSet generate configuration. { "type": "github", "repository": "SagerNet/sing-geosite", - "path": "rule-set", + "path": "rule-set/geosite-", "prefix": "geosite-", "rule_set": [ "apple", @@ -47,7 +47,7 @@ RuleSet generate configuration. { "type": "github", "repository": "MetaCubeX/meta-rules-dat", - "path": "sing/geo/geosite", + "path": "sing/geo/geosite/", "prefix": "geosite-", "rule_set": [ "apple", diff --git a/docs/configuration/template.md b/docs/configuration/template.md index b283862..fc0ce46 100644 --- a/docs/configuration/template.md +++ b/docs/configuration/template.md @@ -11,7 +11,8 @@ "domain_strategy": "", "domain_strategy_local": "", "disable_traffic_bypass": false, - "disable_rule_set": false, + "disable_sniff": false, + "disable_rule_action": false, "remote_resolve": false, // DNS @@ -113,9 +114,13 @@ Local sing-box domain strategy. `prefer_ipv4` is used by default. -#### disable_rule_set +#### disable_sniff -Use `geoip` and `geosite` for traffic bypassing instead of rule sets. +Don`t generate protocol sniffing options. + +#### disable_rule_action + +Don`t generate rule action options. #### disable_traffic_bypass diff --git a/go.mod b/go.mod index ac3740f..9c5c805 100644 --- a/go.mod +++ b/go.mod @@ -11,13 +11,13 @@ require ( github.com/go-chi/render v1.0.3 github.com/miekg/dns v1.1.62 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a - github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f - github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f - github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab + github.com/sagernet/sing v0.6.0-alpha.16 + github.com/sagernet/sing-box v1.11.0-alpha.17 + github.com/sagernet/sing-dns v0.4.0-alpha.2 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 golang.org/x/mod v0.21.0 - golang.org/x/net v0.30.0 + golang.org/x/net v0.31.0 ) require ( @@ -68,12 +68,12 @@ require ( github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/quic-go v0.48.1-beta.1 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec // indirect - github.com/sagernet/sing-quic v0.3.0-rc.2 // indirect + github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect + github.com/sagernet/sing-quic v0.4.0-alpha.3 // indirect github.com/sagernet/sing-shadowsocks v0.2.7 // indirect github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect - github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f // indirect + github.com/sagernet/sing-tun v0.6.0-alpha.8 // indirect github.com/sagernet/sing-vmess v0.1.12 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/sagernet/utls v1.6.7 // indirect @@ -91,11 +91,11 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.28.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect diff --git a/go.sum b/go.sum index 0bb09ef..101e9e9 100644 --- a/go.sum +++ b/go.sum @@ -121,24 +121,24 @@ github.com/sagernet/quic-go v0.48.1-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f h1:A6+OeV5P1mok0eEEbLh4PidymZ6VZnTZ2uHwfapXgdU= -github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f h1:CkGSNvQvZlzm5VuKmc23DiY2WxxHbp1jYux0fh3xRW4= -github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f/go.mod h1:3Ujxk8+gNR1Kve68iZFjzxDHLGrFODdsvnth8oakrwk= -github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab h1:djP4EY/KM5T62xscormLflVi7eDlHv6p7md1FHMSArE= -github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M= -github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec h1:6Fd/VsEsw9qIjaGi1IBTZSb4b4v5JYtNcoiBtGsQC48= -github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec/go.mod h1:RSwqqHwbtTOX3vs6ms8vMtBGH/0ZNyLm/uwt6TlmR84= -github.com/sagernet/sing-quic v0.3.0-rc.2 h1:7vcC4bdS1GBJzHZhfmJiH0CfzQ4mYLUW51Z2RNHcGwc= -github.com/sagernet/sing-quic v0.3.0-rc.2/go.mod h1:3UOq51WVqzra7eCgod7t4hqnTaOiZzFUci9avMrtOqs= +github.com/sagernet/sing v0.6.0-alpha.16 h1:Ml+nJa8J9d+Svqv2pBvJoet+8PF302Snb6wcMUXaoy4= +github.com/sagernet/sing v0.6.0-alpha.16/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-box v1.11.0-alpha.17 h1:j7+LwRgXvcs1qqmNcj0ckQTzBnEl9FO3eEc5AQOdj3g= +github.com/sagernet/sing-box v1.11.0-alpha.17/go.mod h1:5Gekm6mVOgaL+9JTmNu0vngMuSltxwjLUiHLCQ6gc6w= +github.com/sagernet/sing-dns v0.4.0-alpha.2 h1:0x5WjrO+Ifk9sqJlHRz/tKENHwoEinQ8HQCHAhpJHAQ= +github.com/sagernet/sing-dns v0.4.0-alpha.2/go.mod h1:ZiXcacKL54jSSYZMbYF3qKNFkkW674Jt+85YCmK64K8= +github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg= +github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE= +github.com/sagernet/sing-quic v0.4.0-alpha.3 h1:2svvOqgQCJg7FNrIrLTaRB6oDzXPiIyWIt9csjZxD6Q= +github.com/sagernet/sing-quic v0.4.0-alpha.3/go.mod h1:Fmnpy0XoyYdjJrxNqEyl3LC9uLibMNNbxG7dt6HATY4= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f h1:gQwTgN/E4oHe3VlseD3/RhPs866cWcTsPG4dP6a8f8o= -github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f/go.mod h1:Ehs5mZ3T8tTgV3H1Tx4Va5ixvyKjTAUPJ3G11dq7B/g= +github.com/sagernet/sing-tun v0.6.0-alpha.8 h1:HhXyUvXxtaXgT+IILZMq6kbrAyDbUwbN+Df/XxpL7Vo= +github.com/sagernet/sing-tun v0.6.0-alpha.8/go.mod h1:JkgiLLnQUXln1zLGVoJqUwAulJGT0xoiPU4/pYF1fhU= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= @@ -188,18 +188,18 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -210,15 +210,15 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/option/options.go b/option/options.go index a674910..a265a32 100644 --- a/option/options.go +++ b/option/options.go @@ -36,10 +36,10 @@ func (o *Options) UnmarshalJSONContext(ctx context.Context, content []byte) erro } type User struct { - Name string `json:"name,omitempty"` - Password string `json:"password,omitempty"` - Profile option.Listable[string] `json:"profile,omitempty"` - DefaultProfile string `json:"default_profile,omitempty"` + Name string `json:"name,omitempty"` + Password string `json:"password,omitempty"` + Profile badoption.Listable[string] `json:"profile,omitempty"` + DefaultProfile string `json:"default_profile,omitempty"` } const ( @@ -47,24 +47,24 @@ const ( ) type Subscription struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` - UserAgent string `json:"user_agent,omitempty"` - UpdateInterval option.Duration `json:"update_interval,omitempty"` - Process option.Listable[OutboundProcessOptions] `json:"process,omitempty"` - DeDuplication bool `json:"deduplication,omitempty"` - GenerateSelector bool `json:"generate_selector,omitempty"` - GenerateURLTest bool `json:"generate_urltest,omitempty"` - URLTestTagSuffix string `json:"urltest_suffix,omitempty"` - CustomSelector *option.SelectorOutboundOptions `json:"custom_selector,omitempty"` - CustomURLTest *option.URLTestOutboundOptions `json:"custom_urltest,omitempty"` + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` + UserAgent string `json:"user_agent,omitempty"` + UpdateInterval badoption.Duration `json:"update_interval,omitempty"` + Process badoption.Listable[OutboundProcessOptions] `json:"process,omitempty"` + DeDuplication bool `json:"deduplication,omitempty"` + GenerateSelector bool `json:"generate_selector,omitempty"` + GenerateURLTest bool `json:"generate_urltest,omitempty"` + URLTestTagSuffix string `json:"urltest_suffix,omitempty"` + CustomSelector *option.SelectorOutboundOptions `json:"custom_selector,omitempty"` + CustomURLTest *option.URLTestOutboundOptions `json:"custom_urltest,omitempty"` } type OutboundProcessOptions struct { - Filter option.Listable[string] `json:"filter,omitempty"` - Exclude option.Listable[string] `json:"exclude,omitempty"` - FilterType option.Listable[string] `json:"filter_type,omitempty"` - ExcludeType option.Listable[string] `json:"exclude_type,omitempty"` + Filter badoption.Listable[string] `json:"filter,omitempty"` + Exclude badoption.Listable[string] `json:"exclude,omitempty"` + FilterType badoption.Listable[string] `json:"filter_type,omitempty"` + ExcludeType badoption.Listable[string] `json:"exclude_type,omitempty"` Invert bool `json:"invert,omitempty"` Remove bool `json:"remove,omitempty"` Rename *badjson.TypedMap[string, string] `json:"rename,omitempty"` @@ -77,6 +77,6 @@ type Profile struct { Template string `json:"template,omitempty"` TemplateForPlatform *badjson.TypedMap[string, string] `json:"template_for_platform,omitempty"` TemplateForUserAgent *badjson.TypedMap[string, string] `json:"template_for_user_agent,omitempty"` - Outbound option.Listable[string] `json:"outbound,omitempty"` - Subscription option.Listable[string] `json:"subscription,omitempty"` + Outbound badoption.Listable[string] `json:"outbound,omitempty"` + Subscription badoption.Listable[string] `json:"subscription,omitempty"` } diff --git a/option/template.go b/option/template.go index 210db6f..fa34a0e 100644 --- a/option/template.go +++ b/option/template.go @@ -9,6 +9,7 @@ import ( E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json/badjson" + "github.com/sagernet/sing/common/json/badoption" ) type _Template struct { @@ -22,7 +23,8 @@ type _Template struct { DomainStrategy option.DomainStrategy `json:"domain_strategy,omitempty"` DomainStrategyLocal option.DomainStrategy `json:"domain_strategy_local,omitempty"` DisableTrafficBypass bool `json:"disable_traffic_bypass,omitempty"` - DisableRuleSet bool `json:"disable_rule_set,omitempty"` + DisableSniff bool `json:"disable_sniff,omitempty"` + DisableRuleAction bool `json:"disable_rule_action,omitempty"` RemoteResolve bool `json:"remote_resolve,omitempty"` // DNS @@ -53,14 +55,12 @@ type _Template struct { CustomURLTest *option.URLTestOutboundOptions `json:"custom_urltest,omitempty"` // Route - DisableDefaultRules bool `json:"disable_default_rules,omitempty"` - PreRules []option.Rule `json:"pre_rules,omitempty"` - CustomRules []option.Rule `json:"custom_rules,omitempty"` - EnableJSDelivr bool `json:"enable_jsdelivr,omitempty"` - CustomGeoIP *option.GeoIPOptions `json:"custom_geoip,omitempty"` - CustomGeosite *option.GeositeOptions `json:"custom_geosite,omitempty"` - CustomRuleSet []RuleSet `json:"custom_rule_set,omitempty"` - PostRuleSet []RuleSet `json:"post_rule_set,omitempty"` + DisableDefaultRules bool `json:"disable_default_rules,omitempty"` + PreRules []option.Rule `json:"pre_rules,omitempty"` + CustomRules []option.Rule `json:"custom_rules,omitempty"` + EnableJSDelivr bool `json:"enable_jsdelivr,omitempty"` + CustomRuleSet []RuleSet `json:"custom_rule_set,omitempty"` + PostRuleSet []RuleSet `json:"post_rule_set,omitempty"` // Experimental DisableCacheFile bool `json:"disable_cache_file,omitempty"` @@ -122,10 +122,10 @@ func (r *RuleSet) UnmarshalJSON(content []byte) error { } type GitHubRuleSetOptions struct { - Repository string `json:"repository,omitempty"` - Path string `json:"path,omitempty"` - Prefix string `json:"prefix,omitempty"` - RuleSet option.Listable[string] `json:"rule_set,omitempty"` + Repository string `json:"repository,omitempty"` + Path string `json:"path,omitempty"` + Prefix string `json:"prefix,omitempty"` + RuleSet badoption.Listable[string] `json:"rule_set,omitempty"` } func (t Template) DisableIPv6() bool { @@ -137,8 +137,8 @@ type ExtraGroup struct { Target ExtraGroupTarget `json:"target,omitempty"` TagPerSubscription string `json:"tag_per_subscription,omitempty"` Type string `json:"type,omitempty"` - Filter option.Listable[string] `json:"filter,omitempty"` - Exclude option.Listable[string] `json:"exclude,omitempty"` + Filter badoption.Listable[string] `json:"filter,omitempty"` + Exclude badoption.Listable[string] `json:"exclude,omitempty"` CustomSelector *option.SelectorOutboundOptions `json:"custom_selector,omitempty"` CustomURLTest *option.URLTestOutboundOptions `json:"custom_urltest,omitempty"` } diff --git a/server/profile.go b/server/profile.go index 05c277a..942267c 100644 --- a/server/profile.go +++ b/server/profile.go @@ -138,9 +138,16 @@ func (p *Profile) Render(metadata metadata.Metadata) (*boxOption.Options, error) outbounds := common.Filter(p.manager.outbounds, func(it []boxOption.Outbound) bool { return common.Contains(p.Outbound, it[0].Tag) }) - subscriptions := common.Filter(p.manager.subscription.Subscriptions(), func(it *subscription.Subscription) bool { - return common.Contains(p.Subscription, it.Name) - }) + var subscriptions []*subscription.Subscription + for _, subscriptionName := range p.Subscription { + subscription := common.Find(p.manager.subscription.Subscriptions(), func(it *subscription.Subscription) bool { + return it.Name == subscriptionName + }) + if subscription == nil { + return nil, E.New("render profile[", p.Name, "]: subscription not found: ", subscriptionName) + } + subscriptions = append(subscriptions, subscription) + } options, err := selectedTemplate.Render(p.manager.ctx, metadata, p.Name, outbounds, subscriptions) if err != nil { return nil, err diff --git a/subscription/parser/clash.go b/subscription/parser/clash.go index 41def33..2d7088d 100644 --- a/subscription/parser/clash.go +++ b/subscription/parser/clash.go @@ -8,6 +8,7 @@ import ( "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/format" + "github.com/sagernet/sing/common/json/badoption" N "github.com/sagernet/sing/common/network" "github.com/Dreamacro/clash/adapter" @@ -224,10 +225,10 @@ func clashPluginOptions(plugin string, opts map[string]any) string { func clashTransport(network string, httpOpts clash_outbound.HTTPOptions, h2Opts clash_outbound.HTTP2Options, grpcOpts clash_outbound.GrpcOptions, wsOpts clash_outbound.WSOptions) *option.V2RayTransportOptions { switch network { case "http": - var headers map[string]option.Listable[string] + var headers map[string]badoption.Listable[string] for key, values := range httpOpts.Headers { if headers == nil { - headers = make(map[string]option.Listable[string]) + headers = make(map[string]badoption.Listable[string]) } headers[key] = values } @@ -255,10 +256,10 @@ func clashTransport(network string, httpOpts clash_outbound.HTTPOptions, h2Opts }, } case "ws": - var headers map[string]option.Listable[string] + var headers map[string]badoption.Listable[string] for key, value := range wsOpts.Headers { if headers == nil { - headers = make(map[string]option.Listable[string]) + headers = make(map[string]badoption.Listable[string]) } headers[key] = []string{value} } diff --git a/template/filter/filter_test.go b/template/filter/filter_test.go index d61b6a0..603434f 100644 --- a/template/filter/filter_test.go +++ b/template/filter/filter_test.go @@ -19,8 +19,15 @@ func TestFilter1100(t *testing.T) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - RuleSet: []string{"test"}, - Server: "test", + RawDefaultDNSRule: option.RawDefaultDNSRule{ + RuleSet: []string{"test"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: "test", + }, + }, }, }, }, @@ -30,8 +37,15 @@ func TestFilter1100(t *testing.T) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - RuleSet: []string{"test"}, - Outbound: "test", + RawDefaultRule: option.RawDefaultRule{ + Domain: []string{"example.com"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: "test", + }, + }, }, }, }, @@ -61,8 +75,15 @@ func TestFilter1100(t *testing.T) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - Domain: []string{"example.com"}, - Server: "test", + RawDefaultDNSRule: option.RawDefaultDNSRule{ + Domain: []string{"example.com"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: "test", + }, + }, }, }, }, @@ -72,8 +93,15 @@ func TestFilter1100(t *testing.T) { { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - Domain: []string{"example.com"}, - Outbound: "test", + RawDefaultRule: option.RawDefaultRule{ + Domain: []string{"example.com"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: "test", + }, + }, }, }, }, diff --git a/template/render_dns.go b/template/render_dns.go index bb4880a..820e8b3 100644 --- a/template/render_dns.go +++ b/template/render_dns.go @@ -167,37 +167,21 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error options.DNS.Rules = append(options.DNS.Rules, t.PreDNSRules...) if len(t.CustomDNSRules) == 0 { if !t.DisableTrafficBypass { - if t.DisableRuleSet || (metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.8.0-alpha.10"))) { - options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultDNSRule{ - RawDefaultDNSRule: option.RawDefaultDNSRule{ - Geosite: []string{"geolocation-cn"}, - }, - DNSRuleAction: option.DNSRuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.DNSRouteActionOptions{ - Server: DNSLocalTag, - }, + + options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultDNSRule{ + RawDefaultDNSRule: option.RawDefaultDNSRule{ + RuleSet: []string{"geosite-geolocation-cn"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, }, }, - }) - } else { - options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultDNSRule{ - RawDefaultDNSRule: option.RawDefaultDNSRule{ - RuleSet: []string{"geosite-geolocation-cn"}, - }, - DNSRuleAction: option.DNSRuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.DNSRouteActionOptions{ - Server: DNSLocalTag, - }, - }, - }, - }) - } + }, + }) if !t.DisableDNSLeak && (metadata.Version == nil || metadata.Version.GreaterThanOrEqual(semver.ParseVersion("1.9.0-alpha.1"))) { options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, @@ -224,12 +208,6 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error RawDefaultDNSRule: option.RawDefaultDNSRule{ RuleSet: []string{"geosite-geolocation-!cn"}, }, - DNSRuleAction: option.DNSRuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.DNSRouteActionOptions{ - Server: DNSDefaultTag, - }, - }, }, }, { @@ -238,12 +216,6 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error RawDefaultDNSRule: option.RawDefaultDNSRule{ RuleSet: []string{"geoip-cn"}, }, - DNSRuleAction: option.DNSRuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.DNSRouteActionOptions{ - Server: DNSLocalTag, - }, - }, }, }, }, diff --git a/template/render_geo_resources.go b/template/render_geo_resources.go index b1eec86..aa1e746 100644 --- a/template/render_geo_resources.go +++ b/template/render_geo_resources.go @@ -2,7 +2,6 @@ package template import ( M "github.com/sagernet/serenity/common/metadata" - "github.com/sagernet/serenity/common/semver" "github.com/sagernet/serenity/constant" "github.com/sagernet/serenity/option" C "github.com/sagernet/sing-box/constant" @@ -10,87 +9,55 @@ import ( ) func (t *Template) renderGeoResources(metadata M.Metadata, options *boxOption.Options) { - if t.DisableRuleSet || (metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.8.0-alpha.10"))) { + if len(t.CustomRuleSet) == 0 { var ( - geoipDownloadURL string - geositeDownloadURL string - downloadDetour string + downloadURL string + downloadDetour string + branchSplit string ) if t.EnableJSDelivr { - geoipDownloadURL = "https://testingcf.jsdelivr.net/gh/SagerNet/sing-geoip@release/geoip-cn.db" - geositeDownloadURL = "https://testingcf.jsdelivr.net/gh/SagerNet/sing-geosite@release/geosite-cn.db" + downloadURL = "https://testingcf.jsdelivr.net/gh/" if t.DirectTag != "" { downloadDetour = t.DirectTag } else { downloadDetour = DefaultDirectTag } + branchSplit = "@" } else { - geoipDownloadURL = "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip-cn.db" - geositeDownloadURL = "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite-cn.db" + downloadURL = "https://raw.githubusercontent.com/" + branchSplit = "/" } - if t.CustomGeoIP == nil { - options.Route.GeoIP = &boxOption.GeoIPOptions{ - DownloadURL: geoipDownloadURL, - DownloadDetour: downloadDetour, - } - } - if t.CustomGeosite == nil { - options.Route.Geosite = &boxOption.GeositeOptions{ - DownloadURL: geositeDownloadURL, - DownloadDetour: downloadDetour, - } - } - } else { - if len(t.CustomRuleSet) == 0 { - var ( - downloadURL string - downloadDetour string - branchSplit string - ) - if t.EnableJSDelivr { - downloadURL = "https://testingcf.jsdelivr.net/gh/" - if t.DirectTag != "" { - downloadDetour = t.DirectTag - } else { - downloadDetour = DefaultDirectTag - } - branchSplit = "@" - } else { - downloadURL = "https://raw.githubusercontent.com/" - branchSplit = "/" - } - options.Route.RuleSet = []boxOption.RuleSet{ - { - Type: C.RuleSetTypeRemote, - Tag: "geoip-cn", - Format: C.RuleSetFormatBinary, - RemoteOptions: boxOption.RemoteRuleSet{ - URL: downloadURL + "SagerNet/sing-geoip" + branchSplit + "rule-set/geoip-cn.srs", - DownloadDetour: downloadDetour, - }, + options.Route.RuleSet = []boxOption.RuleSet{ + { + Type: C.RuleSetTypeRemote, + Tag: "geoip-cn", + Format: C.RuleSetFormatBinary, + RemoteOptions: boxOption.RemoteRuleSet{ + URL: downloadURL + "SagerNet/sing-geoip" + branchSplit + "rule-set/geoip-cn.srs", + DownloadDetour: downloadDetour, }, - { - Type: C.RuleSetTypeRemote, - Tag: "geosite-geolocation-cn", - Format: C.RuleSetFormatBinary, - RemoteOptions: boxOption.RemoteRuleSet{ - URL: downloadURL + "SagerNet/sing-geosite" + branchSplit + "rule-set/geosite-geolocation-cn.srs", - DownloadDetour: downloadDetour, - }, + }, + { + Type: C.RuleSetTypeRemote, + Tag: "geosite-geolocation-cn", + Format: C.RuleSetFormatBinary, + RemoteOptions: boxOption.RemoteRuleSet{ + URL: downloadURL + "SagerNet/sing-geosite" + branchSplit + "rule-set/geosite-geolocation-cn.srs", + DownloadDetour: downloadDetour, }, - { - Type: C.RuleSetTypeRemote, - Tag: "geosite-geolocation-!cn", - Format: C.RuleSetFormatBinary, - RemoteOptions: boxOption.RemoteRuleSet{ - URL: downloadURL + "SagerNet/sing-geosite" + branchSplit + "rule-set/geosite-geolocation-!cn.srs", - DownloadDetour: downloadDetour, - }, + }, + { + Type: C.RuleSetTypeRemote, + Tag: "geosite-geolocation-!cn", + Format: C.RuleSetFormatBinary, + RemoteOptions: boxOption.RemoteRuleSet{ + URL: downloadURL + "SagerNet/sing-geosite" + branchSplit + "rule-set/geosite-geolocation-!cn.srs", + DownloadDetour: downloadDetour, }, - } + }, } - options.Route.RuleSet = append(options.Route.RuleSet, t.renderRuleSet(t.PostRuleSet)...) } + options.Route.RuleSet = append(options.Route.RuleSet, t.renderRuleSet(t.PostRuleSet)...) } func (t *Template) renderRuleSet(ruleSets []option.RuleSet) []boxOption.RuleSet { diff --git a/template/render_inbounds.go b/template/render_inbounds.go index 9de41ad..25671d3 100644 --- a/template/render_inbounds.go +++ b/template/render_inbounds.go @@ -9,16 +9,14 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-dns" + "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/json/badjson" + "github.com/sagernet/sing/common/json/badoption" ) func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) error { options.Inbounds = t.Inbounds - var needSniff bool - if !t.DisableTrafficBypass { - needSniff = true - } var domainStrategy option.DomainStrategy if !t.RemoteResolve { if t.DomainStrategy != option.DomainStrategy(dns.DomainStrategyAsIS) { @@ -27,6 +25,7 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) domainStrategy = option.DomainStrategy(dns.DomainStrategyPreferIPv4) } } + disableRuleAction := t.DisableRuleAction || (metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.11.0-alpha.7"))) autoRedirect := t.AutoRedirect && !metadata.Platform.IsApple() && (metadata.Version == nil || metadata.Version.GreaterThanOrEqual(semver.ParseVersion("1.10.0-alpha.2"))) @@ -40,9 +39,6 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) tunOptions := &option.TunInboundOptions{ AutoRoute: true, Address: address, - InboundOptions: option.InboundOptions{ - SniffEnabled: needSniff, - }, } tunInbound := option.Inbound{ Type: C.TypeTun, @@ -54,12 +50,17 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) tunOptions.RouteExcludeAddressSet = []string{"geoip-cn"} } } - if t.EnableFakeIP { - tunOptions.DomainStrategy = domainStrategy - } if metadata.Platform == M.PlatformUnknown { tunOptions.StrictRoute = true } + if disableRuleAction { + tunOptions.InboundOptions = option.InboundOptions{ + SniffEnabled: !t.DisableSniff, + } + if t.EnableFakeIP { + tunOptions.DomainStrategy = domainStrategy + } + } if !t.DisableSystemProxy && metadata.Platform != M.PlatformUnknown { var httpPort uint16 if t.CustomMixed != nil { @@ -90,15 +91,17 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) if disableTun || !t.DisableSystemProxy { mixedOptions := &option.HTTPMixedInboundOptions{ ListenOptions: option.ListenOptions{ - Listen: option.NewListenAddress(netip.AddrFrom4([4]byte{127, 0, 0, 1})), + Listen: common.Ptr(badoption.Addr(netip.AddrFrom4([4]byte{127, 0, 0, 1}))), ListenPort: DefaultMixedPort, - InboundOptions: option.InboundOptions{ - SniffEnabled: needSniff, - DomainStrategy: domainStrategy, - }, }, SetSystemProxy: metadata.Platform == M.PlatformUnknown && disableTun && !t.DisableSystemProxy, } + if disableRuleAction { + mixedOptions.InboundOptions = option.InboundOptions{ + SniffEnabled: !t.DisableSniff, + DomainStrategy: domainStrategy, + } + } mixedInbound := option.Inbound{ Type: C.TypeMixed, Options: mixedOptions, diff --git a/template/render_outbounds.go b/template/render_outbounds.go index 955a6d8..4a68ff2 100644 --- a/template/render_outbounds.go +++ b/template/render_outbounds.go @@ -6,6 +6,7 @@ import ( "text/template" M "github.com/sagernet/serenity/common/metadata" + "github.com/sagernet/serenity/common/semver" "github.com/sagernet/serenity/option" "github.com/sagernet/serenity/subscription" C "github.com/sagernet/sing-box/constant" @@ -16,6 +17,7 @@ import ( ) func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Options, outbounds [][]boxOption.Outbound, subscriptions []*subscription.Subscription) error { + disableRuleAction := t.DisableRuleAction || (metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.11.0-alpha.7"))) defaultTag := t.DefaultTag if defaultTag == "" { defaultTag = DefaultDefaultTag @@ -35,22 +37,26 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio Type: C.TypeDirect, Options: common.Ptr(common.PtrValueOrDefault(t.CustomDirect)), }, - { - Tag: blockTag, - Type: C.TypeBlock, - Options: &boxOption.StubOptions{}, - }, - { - Tag: DNSTag, - Type: C.TypeDNS, - Options: &boxOption.StubOptions{}, - }, { Tag: defaultTag, Type: C.TypeSelector, Options: common.Ptr(common.PtrValueOrDefault(t.CustomSelector)), }, } + if disableRuleAction { + options.Outbounds = append(options.Outbounds, + boxOption.Outbound{ + Tag: blockTag, + Type: C.TypeBlock, + Options: &boxOption.StubOptions{}, + }, + boxOption.Outbound{ + Tag: DNSTag, + Type: C.TypeDNS, + Options: &boxOption.StubOptions{}, + }, + ) + } urlTestTag := t.URLTestTag if urlTestTag == "" { urlTestTag = DefaultURLTestTag diff --git a/template/render_route.go b/template/render_route.go index 1e9b1ed..cb82fdb 100644 --- a/template/render_route.go +++ b/template/render_route.go @@ -11,49 +11,90 @@ import ( func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) error { if options.Route == nil { options.Route = &option.RouteOptions{ - GeoIP: t.CustomGeoIP, - Geosite: t.CustomGeosite, RuleSet: t.renderRuleSet(t.CustomRuleSet), } } if !t.DisableTrafficBypass { t.renderGeoResources(metadata, options) } - disable18Features := metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.8.0-alpha.10")) - options.Route.Rules = []option.Rule{ - { - Type: C.RuleTypeLogical, - LogicalOptions: option.LogicalRule{ - RawLogicalRule: option.RawLogicalRule{ - Mode: C.LogicalTypeOr, - Rules: []option.Rule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - Network: []string{N.NetworkUDP}, - Port: []uint16{53}, + disableRuleAction := t.DisableRuleAction || (metadata.Version != nil && metadata.Version.LessThan(semver.ParseVersion("1.11.0-alpha.7"))) + if disableRuleAction { + options.Route.Rules = []option.Rule{ + { + Type: C.RuleTypeLogical, + LogicalOptions: option.LogicalRule{ + RawLogicalRule: option.RawLogicalRule{ + Mode: C.LogicalTypeOr, + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Network: []string{N.NetworkUDP}, + Port: []uint16{53}, + }, }, }, - }, - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - Protocol: []string{C.ProtocolDNS}, + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Protocol: []string{C.ProtocolDNS}, + }, }, }, }, }, - }, - RuleAction: option.RuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.RouteActionOptions{ - Outbound: DNSTag, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: DNSTag, + }, }, }, }, - }, + } + } else { + options.Route.Rules = []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeSniff, + }, + }, + }, + { + Type: C.RuleTypeLogical, + LogicalOptions: option.LogicalRule{ + RawLogicalRule: option.RawLogicalRule{ + Mode: C.LogicalTypeOr, + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Network: []string{N.NetworkUDP}, + Port: []uint16{53}, + }, + }, + }, + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Protocol: []string{C.ProtocolDNS}, + }, + }, + }, + }, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeHijackDNS, + }, + }, + }, + } } directTag := t.DirectTag defaultTag := t.DefaultTag @@ -63,37 +104,20 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err if defaultTag == "" { defaultTag = DefaultDefaultTag } - if disable18Features { - options.Route.Rules = append(options.Route.Rules, option.Rule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - GeoIP: []string{"private"}, - }, - RuleAction: option.RuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.RouteActionOptions{ - Outbound: directTag, - }, + options.Route.Rules = append(options.Route.Rules, option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + IPIsPrivate: true, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, }, }, - }) - } else { - options.Route.Rules = append(options.Route.Rules, option.Rule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - IPIsPrivate: true, - }, - RuleAction: option.RuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.RouteActionOptions{ - Outbound: directTag, - }, - }, - }, - }) - } + }, + }) if !t.DisableClashMode { modeGlobal := t.ClashModeGlobal modeDirect := t.ClashModeDirect @@ -131,41 +155,33 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err }, }) } + if disableRuleAction { + options.Route.Rules = append(options.Route.Rules, option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeResolve, + }, + }, + }) + } options.Route.Rules = append(options.Route.Rules, t.PreRules...) if len(t.CustomRules) == 0 { if !t.DisableTrafficBypass { - if t.DisableRuleSet || disable18Features { - options.Route.Rules = append(options.Route.Rules, option.Rule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - GeoIP: []string{"cn"}, - Geosite: []string{"geolocation-cn"}, - }, - RuleAction: option.RuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.RouteActionOptions{ - Outbound: directTag, - }, + options.Route.Rules = append(options.Route.Rules, option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + RuleSet: []string{"geoip-cn", "geosite-geolocation-cn"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, }, }, - }) - } else { - options.Route.Rules = append(options.Route.Rules, option.Rule{ - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - RawDefaultRule: option.RawDefaultRule{ - RuleSet: []string{"geoip-cn", "geosite-geolocation-cn"}, - }, - RuleAction: option.RuleAction{ - Action: C.RuleActionTypeRoute, - RouteOptions: option.RouteActionOptions{ - Outbound: directTag, - }, - }, - }, - }) - } + }, + }) } } else { options.Route.Rules = append(options.Route.Rules, t.CustomRules...)