diff --git a/adapter/outboundgroup/common.go b/adapter/outboundgroup/common.go index fdd5a043ac..98b289773a 100644 --- a/adapter/outboundgroup/common.go +++ b/adapter/outboundgroup/common.go @@ -43,7 +43,7 @@ func getProvidersProxies(providers []provider.ProxyProvider, touch bool, filter for _, filterReg := range filterRegs { for _, p := range proxies { name := p.Name() - if mat, _ := filterReg.FindStringMatch(name); mat != nil { + if mat, _ := filterReg.MatchString(name); mat { if _, ok := proxiesSet[name]; !ok { proxiesSet[name] = struct{}{} matchedProxies = append(matchedProxies, p) diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go index 65393f64c5..caac8f452f 100644 --- a/adapter/provider/provider.go +++ b/adapter/provider/provider.go @@ -161,12 +161,12 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, exc continue } if len(excludeFilter) > 0 { - if mat, _ := excludeFilterReg.FindStringMatch(name); mat != nil { + if mat, _ := excludeFilterReg.MatchString(name); mat { continue } } if len(filter) > 0 { - if mat, _ := filterReg.FindStringMatch(name); mat == nil { + if mat, _ := filterReg.MatchString(name); !mat { continue } } diff --git a/constant/rule.go b/constant/rule.go index 1014dd6b14..34436bb12a 100644 --- a/constant/rule.go +++ b/constant/rule.go @@ -14,8 +14,10 @@ const ( InUser InName InType - Process + ProcessName ProcessPath + ProcessNameRegex + ProcessPathRegex Network Type_ IPSet @@ -61,10 +63,14 @@ func (rt RuleType) String() string { return "Network" case Type_: return "Type" - case Process: - return "Process" + case ProcessName: + return "ProcessName" case ProcessPath: return "ProcessPath" + case ProcessNameRegex: + return "ProcessNameRegex" + case ProcessPathRegex: + return "ProcessPathRegex" case IPSet: return "IPSet" case MATCH: diff --git a/rule/parser.go b/rule/parser.go index 84398f001c..b946ba9e19 100644 --- a/rule/parser.go +++ b/rule/parser.go @@ -42,9 +42,13 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string] case "IN-PORT": parsed, parseErr = NewPort(payload, target, C.InPort) case "PROCESS-NAME": - parsed, parseErr = NewProcess(payload, target, true) + parsed, parseErr = NewProcess(payload, target, true, false) case "PROCESS-PATH": - parsed, parseErr = NewProcess(payload, target, false) + parsed, parseErr = NewProcess(payload, target, false, false) + case "PROCESS-NAME-REGEX": + parsed, parseErr = NewProcess(payload, target, true, true) + case "PROCESS-PATH-REGEX": + parsed, parseErr = NewProcess(payload, target, false, true) case "NETWORK": parsed, parseErr = NewNetwork(payload, target) case "IN-TYPE": diff --git a/rule/process.go b/rule/process.go index 5cb70fe421..469ea2da8e 100644 --- a/rule/process.go +++ b/rule/process.go @@ -4,27 +4,44 @@ import ( "strings" C "github.com/metacubex/mihomo/constant" + + "github.com/dlclark/regexp2" ) type Process struct { adapter string process string nameOnly bool + regexp *regexp2.Regexp } func (ps *Process) RuleType() C.RuleType { if ps.nameOnly { - return C.Process + if ps.regexp != nil { + return C.ProcessNameRegex + } + return C.ProcessName } + if ps.regexp != nil { + return C.ProcessPathRegex + } return C.ProcessPath } func (ps *Process) Match(metadata *C.Metadata) (bool, string) { if ps.nameOnly { + if ps.regexp != nil { + match, _ := ps.regexp.MatchString(metadata.Process) + return match, ps.adapter + } return strings.EqualFold(metadata.Process, ps.process), ps.adapter } + if ps.regexp != nil { + match, _ := ps.regexp.MatchString(metadata.ProcessPath) + return match, ps.adapter + } return strings.EqualFold(metadata.ProcessPath, ps.process), ps.adapter } @@ -44,10 +61,19 @@ func (ps *Process) ShouldFindProcess() bool { return true } -func NewProcess(process string, adapter string, nameOnly bool) (*Process, error) { +func NewProcess(process string, adapter string, nameOnly bool, regex bool) (*Process, error) { + var r *regexp2.Regexp + var err error + if regex { + r, err = regexp2.Compile(process, regexp2.IgnoreCase) + if err != nil { + return nil, err + } + } return &Process{ adapter: adapter, process: process, nameOnly: nameOnly, + regexp: r, }, nil }