From 2f234cf6bcb0b5e63c07df75584b3024311ebe26 Mon Sep 17 00:00:00 2001 From: yaling888 <73897884+yaling888@users.noreply.github.com> Date: Wed, 23 Feb 2022 14:01:53 +0800 Subject: [PATCH] Feature: process condition for rules --- README.md | 11 +++++++---- constant/rule_extra.go | 19 +++++++++++++++++-- rule/base.go | 19 +++++++++++++++++-- rule/geoip.go | 9 +++++++-- rule/parser.go | 5 +++-- tunnel/tunnel.go | 4 ++++ 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2239ffdb..c9d5c0d8 100644 --- a/README.md +++ b/README.md @@ -82,17 +82,20 @@ tun: ### Rules configuration - Support rule `GEOSITE`. - Support `multiport` condition for rule `SRC-PORT` and `DST-PORT`. -- Support not match condition for rule `GEOIP`. - 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. ```yaml rules: # network condition for all rules - - DOMAIN-SUFFIX,bilibili.com,DIRECT,tcp - - DOMAIN-SUFFIX,bilibili.com,REJECT,udp - + - DOMAIN-SUFFIX,example.com,DIRECT,tcp + - DOMAIN-SUFFIX,example.com,REJECT,udp + + # process(add 'P:' prefix) condition for all rules + - DOMAIN-SUFFIX,example.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/geoip.go b/rule/geoip.go index 1783b7b7..86114acc 100644 --- a/rule/geoip.go +++ b/rule/geoip.go @@ -24,9 +24,14 @@ func (g *GEOIP) Match(metadata *C.Metadata) bool { return false } - if strings.EqualFold(g.country, "LAN") || C.TunBroadcastAddr.Equal(ip) { - return ip.IsPrivate() + if strings.EqualFold(g.country, "LAN") { + return ip.IsPrivate() || + ip.IsUnspecified() || + ip.IsLoopback() || + ip.IsMulticast() || + C.TunBroadcastAddr.Equal(ip) } + record, _ := mmdb.Instance().Country(ip) return strings.EqualFold(record.Country.IsoCode, g.country) } diff --git a/rule/parser.go b/rule/parser.go index fa73c2ae..bfd056e1 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 4e2dceb6..907d06bd 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -353,6 +353,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