From 25e115d042656260b1260780fba1b942d0b4b55c Mon Sep 17 00:00:00 2001 From: yaling888 <73897884+yaling888@users.noreply.github.com> Date: Fri, 28 Jan 2022 22:52:35 +0800 Subject: [PATCH] Feature: process condition for rules --- README.md | 6 +++++- constant/rule_extra.go | 19 +++++++++++++++++-- rule/base.go | 19 +++++++++++++++++-- rule/parser.go | 5 +++-- tunnel/tunnel.go | 4 ++++ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7090f752..037ef0a7 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ tun: - Support rule `SCRIPT`. - Support `multiport` condition for rule `SRC-PORT` and `DST-PORT`. - Support `network` condition for all rules. +- Support `process` condition for all rules. - Support source IPCIDR condition for all rules, just append to the end. The `GEOSITE` databases via https://github.com/Loyalsoldier/v2ray-rules-dat. @@ -105,7 +106,10 @@ rules: # network(tcp/udp) condition for all rules - DOMAIN-SUFFIX,bilibili.com,DIRECT,tcp - DOMAIN-SUFFIX,bilibili.com,REJECT,udp - + + # process(add 'P:' prefix) condition for all rules + - DOMAIN-SUFFIX,qq.com,REJECT,P:Google Chrome Helper + # multiport condition for rules SRC-PORT and DST-PORT - DST-PORT,123/136/137-139,DIRECT,udp diff --git a/constant/rule_extra.go b/constant/rule_extra.go index 119b42ca..9df17418 100644 --- a/constant/rule_extra.go +++ b/constant/rule_extra.go @@ -2,6 +2,7 @@ package constant import ( "net" + "strings" "github.com/Dreamacro/clash/component/geodata/router" ) @@ -9,8 +10,9 @@ import ( var TunBroadcastAddr = net.IPv4(198, 18, 255, 255) type RuleExtra struct { - Network NetWork - SourceIPs []*net.IPNet + Network NetWork + SourceIPs []*net.IPNet + ProcessNames []string } func (re *RuleExtra) NotMatchNetwork(network NetWork) bool { @@ -30,6 +32,19 @@ func (re *RuleExtra) NotMatchSourceIP(srcIP net.IP) bool { return true } +func (re *RuleExtra) NotMatchProcessName(processName string) bool { + if re.ProcessNames == nil { + return false + } + + for _, pn := range re.ProcessNames { + if strings.EqualFold(pn, processName) { + return false + } + } + return true +} + type RuleGeoSite interface { GetDomainMatcher() *router.DomainMatcher } diff --git a/rule/base.go b/rule/base.go index 96d8bfe5..beee7797 100644 --- a/rule/base.go +++ b/rule/base.go @@ -3,6 +3,7 @@ package rules import ( "errors" "net" + "strings" C "github.com/Dreamacro/clash/constant" ) @@ -24,9 +25,9 @@ func HasNoResolve(params []string) bool { func findNetwork(params []string) C.NetWork { for _, p := range params { - if p == "tcp" { + if strings.EqualFold(p, "tcp") { return C.TCP - } else if p == "udp" { + } else if strings.EqualFold(p, "udp") { return C.UDP } } @@ -51,3 +52,17 @@ func findSourceIPs(params []string) []*net.IPNet { } return nil } + +func findProcessName(params []string) []string { + var processNames []string + for _, p := range params { + if strings.HasPrefix(p, "P:") { + processNames = append(processNames, strings.TrimPrefix(p, "P:")) + } + } + + if len(processNames) > 0 { + return processNames + } + return nil +} diff --git a/rule/parser.go b/rule/parser.go index 60bffefb..a95d4ede 100644 --- a/rule/parser.go +++ b/rule/parser.go @@ -13,8 +13,9 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) { ) ruleExtra := &C.RuleExtra{ - Network: findNetwork(params), - SourceIPs: findSourceIPs(params), + Network: findNetwork(params), + SourceIPs: findSourceIPs(params), + ProcessNames: findProcessName(params), } switch tp { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 73b2b499..97a56fba 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -360,6 +360,10 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { if extra.NotMatchSourceIP(metadata.SrcIP) { continue } + + if extra.NotMatchProcessName(metadata.Process) { + continue + } } return adapter, rule, nil