From bf1d4d045c8777c1a81ff34d772c5e30f6dece68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 24 Mar 2024 19:23:11 +0800 Subject: [PATCH] Add `rule-set match` command --- adapter/router.go | 2 +- cmd/sing-box/cmd_rule_set_match.go | 86 ++++++++++++++++++++++++++++++ route/rule_headless.go | 16 +++--- 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 cmd/sing-box/cmd_rule_set_match.go diff --git a/adapter/router.go b/adapter/router.go index 73849b97..786a777e 100644 --- a/adapter/router.go +++ b/adapter/router.go @@ -71,6 +71,7 @@ func RouterFromContext(ctx context.Context) Router { type HeadlessRule interface { Match(metadata *InboundContext) bool + String() string } type Rule interface { @@ -79,7 +80,6 @@ type Rule interface { Type() string UpdateGeosite() error Outbound() string - String() string } type DNSRule interface { diff --git a/cmd/sing-box/cmd_rule_set_match.go b/cmd/sing-box/cmd_rule_set_match.go new file mode 100644 index 00000000..473c8222 --- /dev/null +++ b/cmd/sing-box/cmd_rule_set_match.go @@ -0,0 +1,86 @@ +package main + +import ( + "bytes" + "io" + "os" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/srs" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/route" + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/json" + + "github.com/spf13/cobra" +) + +var flagRuleSetMatchFormat string + +var commandRuleSetMatch = &cobra.Command{ + Use: "match ", + Short: "Check if a domain matches the rule set", + Args: cobra.ExactArgs(2), + Run: func(cmd *cobra.Command, args []string) { + err := ruleSetMatch(args[0], args[1]) + if err != nil { + log.Fatal(err) + } + }, +} + +func init() { + commandRuleSetMatch.Flags().StringVarP(&flagRuleSetMatchFormat, "format", "f", "source", "rule-set format") + commandRuleSet.AddCommand(commandRuleSetMatch) +} + +func ruleSetMatch(sourcePath string, domain string) error { + var ( + reader io.Reader + err error + ) + if sourcePath == "stdin" { + reader = os.Stdin + } else { + reader, err = os.Open(sourcePath) + if err != nil { + return E.Cause(err, "read rule-set") + } + } + content, err := io.ReadAll(reader) + if err != nil { + return E.Cause(err, "read rule-set") + } + var plainRuleSet option.PlainRuleSet + switch flagRuleSetMatchFormat { + case C.RuleSetFormatSource: + var compat option.PlainRuleSetCompat + compat, err = json.UnmarshalExtended[option.PlainRuleSetCompat](content) + if err != nil { + return err + } + plainRuleSet = compat.Upgrade() + case C.RuleSetFormatBinary: + plainRuleSet, err = srs.Read(bytes.NewReader(content), false) + if err != nil { + return err + } + default: + return E.New("unknown rule set format: ", flagRuleSetMatchFormat) + } + for i, ruleOptions := range plainRuleSet.Rules { + var currentRule adapter.HeadlessRule + currentRule, err = route.NewHeadlessRule(nil, ruleOptions) + if err != nil { + return E.Cause(err, "parse rule_set.rules.[", i, "]") + } + if currentRule.Match(&adapter.InboundContext{ + Domain: domain, + }) { + println("match rules.[", i, "]: "+currentRule.String()) + } + } + return nil +} diff --git a/route/rule_headless.go b/route/rule_headless.go index 92b6720c..67ac3a1e 100644 --- a/route/rule_headless.go +++ b/route/rule_headless.go @@ -129,14 +129,18 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles rule.allItems = append(rule.allItems, item) } if len(options.WIFISSID) > 0 { - item := NewWIFISSIDItem(router, options.WIFISSID) - rule.items = append(rule.items, item) - rule.allItems = append(rule.allItems, item) + if router != nil { + item := NewWIFISSIDItem(router, options.WIFISSID) + rule.items = append(rule.items, item) + rule.allItems = append(rule.allItems, item) + } } if len(options.WIFIBSSID) > 0 { - item := NewWIFIBSSIDItem(router, options.WIFIBSSID) - rule.items = append(rule.items, item) - rule.allItems = append(rule.allItems, item) + if router != nil { + item := NewWIFIBSSIDItem(router, options.WIFIBSSID) + rule.items = append(rule.items, item) + rule.allItems = append(rule.allItems, item) + } } return rule, nil }