瀏覽代碼

Add `rule-set match` command

世界 1 年之前
父節點
當前提交
d612620c5d
共有 3 個文件被更改,包括 97 次插入7 次删除
  1. 1 1
      adapter/router.go
  2. 86 0
      cmd/sing-box/cmd_rule_set_match.go
  3. 10 6
      route/rule_headless.go

+ 1 - 1
adapter/router.go

@@ -71,6 +71,7 @@ func RouterFromContext(ctx context.Context) Router {
 
 
 type HeadlessRule interface {
 type HeadlessRule interface {
 	Match(metadata *InboundContext) bool
 	Match(metadata *InboundContext) bool
+	String() string
 }
 }
 
 
 type Rule interface {
 type Rule interface {
@@ -79,7 +80,6 @@ type Rule interface {
 	Type() string
 	Type() string
 	UpdateGeosite() error
 	UpdateGeosite() error
 	Outbound() string
 	Outbound() string
-	String() string
 }
 }
 
 
 type DNSRule interface {
 type DNSRule interface {

+ 86 - 0
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 <rule-set path> <domain>",
+	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
+}

+ 10 - 6
route/rule_headless.go

@@ -129,14 +129,18 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles
 		rule.allItems = append(rule.allItems, item)
 		rule.allItems = append(rule.allItems, item)
 	}
 	}
 	if len(options.WIFISSID) > 0 {
 	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 {
 	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
 	return rule, nil
 }
 }