github.com/sagernet/sing-box@v1.9.0-rc.20/cmd/sing-box/cmd_rule_set_match.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"os"
     7  
     8  	"github.com/sagernet/sing-box/adapter"
     9  	"github.com/sagernet/sing-box/common/srs"
    10  	C "github.com/sagernet/sing-box/constant"
    11  	"github.com/sagernet/sing-box/log"
    12  	"github.com/sagernet/sing-box/option"
    13  	"github.com/sagernet/sing-box/route"
    14  	E "github.com/sagernet/sing/common/exceptions"
    15  	"github.com/sagernet/sing/common/json"
    16  
    17  	"github.com/spf13/cobra"
    18  )
    19  
    20  var flagRuleSetMatchFormat string
    21  
    22  var commandRuleSetMatch = &cobra.Command{
    23  	Use:   "match <rule-set path> <domain>",
    24  	Short: "Check if a domain matches the rule set",
    25  	Args:  cobra.ExactArgs(2),
    26  	Run: func(cmd *cobra.Command, args []string) {
    27  		err := ruleSetMatch(args[0], args[1])
    28  		if err != nil {
    29  			log.Fatal(err)
    30  		}
    31  	},
    32  }
    33  
    34  func init() {
    35  	commandRuleSetMatch.Flags().StringVarP(&flagRuleSetMatchFormat, "format", "f", "source", "rule-set format")
    36  	commandRuleSet.AddCommand(commandRuleSetMatch)
    37  }
    38  
    39  func ruleSetMatch(sourcePath string, domain string) error {
    40  	var (
    41  		reader io.Reader
    42  		err    error
    43  	)
    44  	if sourcePath == "stdin" {
    45  		reader = os.Stdin
    46  	} else {
    47  		reader, err = os.Open(sourcePath)
    48  		if err != nil {
    49  			return E.Cause(err, "read rule-set")
    50  		}
    51  	}
    52  	content, err := io.ReadAll(reader)
    53  	if err != nil {
    54  		return E.Cause(err, "read rule-set")
    55  	}
    56  	var plainRuleSet option.PlainRuleSet
    57  	switch flagRuleSetMatchFormat {
    58  	case C.RuleSetFormatSource:
    59  		var compat option.PlainRuleSetCompat
    60  		compat, err = json.UnmarshalExtended[option.PlainRuleSetCompat](content)
    61  		if err != nil {
    62  			return err
    63  		}
    64  		plainRuleSet = compat.Upgrade()
    65  	case C.RuleSetFormatBinary:
    66  		plainRuleSet, err = srs.Read(bytes.NewReader(content), false)
    67  		if err != nil {
    68  			return err
    69  		}
    70  	default:
    71  		return E.New("unknown rule set format: ", flagRuleSetMatchFormat)
    72  	}
    73  	for i, ruleOptions := range plainRuleSet.Rules {
    74  		var currentRule adapter.HeadlessRule
    75  		currentRule, err = route.NewHeadlessRule(nil, ruleOptions)
    76  		if err != nil {
    77  			return E.Cause(err, "parse rule_set.rules.[", i, "]")
    78  		}
    79  		if currentRule.Match(&adapter.InboundContext{
    80  			Domain: domain,
    81  		}) {
    82  			println("match rules.[", i, "]: "+currentRule.String())
    83  		}
    84  	}
    85  	return nil
    86  }