Browse Source

Add process_path rule item (#51)

* process matching supports full path
* Remove strings.ToLower
dyhkwong 3 years ago
parent
commit
374743d022
7 changed files with 67 additions and 4 deletions
  1. 1 0
      option/dns.go
  2. 1 0
      option/route.go
  3. 2 2
      route/router.go
  4. 5 0
      route/rule.go
  5. 5 0
      route/rule_dns.go
  6. 2 2
      route/rule_process_name.go
  7. 51 0
      route/rule_process_path.go

+ 1 - 0
option/dns.go

@@ -94,6 +94,7 @@ type DefaultDNSRule struct {
 	Port            Listable[uint16] `json:"port,omitempty"`
 	PortRange       Listable[string] `json:"port_range,omitempty"`
 	ProcessName     Listable[string] `json:"process_name,omitempty"`
+	ProcessPath     Listable[string] `json:"process_path,omitempty"`
 	PackageName     Listable[string] `json:"package_name,omitempty"`
 	User            Listable[string] `json:"user,omitempty"`
 	UserID          Listable[int32]  `json:"user_id,omitempty"`

+ 1 - 0
option/route.go

@@ -96,6 +96,7 @@ type DefaultRule struct {
 	Port            Listable[uint16] `json:"port,omitempty"`
 	PortRange       Listable[string] `json:"port_range,omitempty"`
 	ProcessName     Listable[string] `json:"process_name,omitempty"`
+	ProcessPath     Listable[string] `json:"process_path,omitempty"`
 	PackageName     Listable[string] `json:"package_name,omitempty"`
 	User            Listable[string] `json:"user,omitempty"`
 	UserID          Listable[int32]  `json:"user_id,omitempty"`

+ 2 - 2
route/router.go

@@ -789,11 +789,11 @@ func isGeositeDNSRule(rule option.DefaultDNSRule) bool {
 }
 
 func isProcessRule(rule option.DefaultRule) bool {
-	return len(rule.ProcessName) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
+	return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
 }
 
 func isProcessDNSRule(rule option.DefaultDNSRule) bool {
-	return len(rule.ProcessName) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
+	return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
 }
 
 func notPrivateNode(code string) bool {

+ 5 - 0
route/rule.go

@@ -172,6 +172,11 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
 		rule.items = append(rule.items, item)
 		rule.allItems = append(rule.allItems, item)
 	}
+	if len(options.ProcessPath) > 0 {
+		item := NewProcessPathItem(options.ProcessPath)
+		rule.items = append(rule.items, item)
+		rule.allItems = append(rule.allItems, item)
+	}
 	if len(options.PackageName) > 0 {
 		item := NewPackageNameItem(options.PackageName)
 		rule.items = append(rule.items, item)

+ 5 - 0
route/rule_dns.go

@@ -155,6 +155,11 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
 		rule.items = append(rule.items, item)
 		rule.allItems = append(rule.allItems, item)
 	}
+	if len(options.ProcessPath) > 0 {
+		item := NewProcessPathItem(options.ProcessPath)
+		rule.items = append(rule.items, item)
+		rule.allItems = append(rule.allItems, item)
+	}
 	if len(options.PackageName) > 0 {
 		item := NewPackageNameItem(options.PackageName)
 		rule.items = append(rule.items, item)

+ 2 - 2
route/rule_process.go → route/rule_process_name.go

@@ -11,7 +11,7 @@ import (
 
 var warnProcessNameOnNonSupportedPlatform = warning.New(
 	func() bool { return !(C.IsLinux || C.IsWindows || C.IsDarwin) },
-	"rule item `process_item` is only supported on Linux, Windows, and macOS",
+	"rule item `process_name` is only supported on Linux, Windows and macOS",
 )
 
 var _ RuleItem = (*ProcessItem)(nil)
@@ -37,7 +37,7 @@ func (r *ProcessItem) Match(metadata *adapter.InboundContext) bool {
 	if metadata.ProcessInfo == nil || metadata.ProcessInfo.ProcessPath == "" {
 		return false
 	}
-	return r.processMap[strings.ToLower(filepath.Base(metadata.ProcessInfo.ProcessPath))]
+	return r.processMap[filepath.Base(metadata.ProcessInfo.ProcessPath)]
 }
 
 func (r *ProcessItem) String() string {

+ 51 - 0
route/rule_process_path.go

@@ -0,0 +1,51 @@
+package route
+
+import (
+	"strings"
+
+	"github.com/sagernet/sing-box/adapter"
+	"github.com/sagernet/sing-box/common/warning"
+	C "github.com/sagernet/sing-box/constant"
+)
+
+var warnProcessPathOnNonSupportedPlatform = warning.New(
+	func() bool { return !(C.IsLinux || C.IsWindows || C.IsDarwin) },
+	"rule item `process_path` is only supported on Linux, Windows and macOS",
+)
+
+var _ RuleItem = (*ProcessPathItem)(nil)
+
+type ProcessPathItem struct {
+	processes  []string
+	processMap map[string]bool
+}
+
+func NewProcessPathItem(processNameList []string) *ProcessPathItem {
+	warnProcessPathOnNonSupportedPlatform.Check()
+	rule := &ProcessPathItem{
+		processes:  processNameList,
+		processMap: make(map[string]bool),
+	}
+	for _, processName := range processNameList {
+		rule.processMap[processName] = true
+	}
+	return rule
+}
+
+func (r *ProcessPathItem) Match(metadata *adapter.InboundContext) bool {
+	if metadata.ProcessInfo == nil || metadata.ProcessInfo.ProcessPath == "" {
+		return false
+	}
+	return r.processMap[metadata.ProcessInfo.ProcessPath]
+}
+
+func (r *ProcessPathItem) String() string {
+	var description string
+	pLen := len(r.processes)
+	if pLen == 1 {
+		description = "process_path=" + r.processes[0]
+	} else {
+		description = "process_path=[" + strings.Join(r.processes, " ") + "]"
+	}
+	return description
+}