Feature: process condition for rules

This commit is contained in:
yaling888 2022-02-23 14:01:53 +08:00
parent d876d6e74c
commit 2f234cf6bc
6 changed files with 55 additions and 12 deletions

View file

@ -82,16 +82,19 @@ tun:
### Rules configuration ### Rules configuration
- Support rule `GEOSITE`. - Support rule `GEOSITE`.
- Support `multiport` condition for rule `SRC-PORT` and `DST-PORT`. - Support `multiport` condition for rule `SRC-PORT` and `DST-PORT`.
- Support not match condition for rule `GEOIP`.
- Support `network` condition for all rules. - Support `network` condition for all rules.
- Support `process` condition for all rules.
- Support source IPCIDR condition for all rules, just append to the end. - Support source IPCIDR condition for all rules, just append to the end.
The `GEOSITE` databases via https://github.com/Loyalsoldier/v2ray-rules-dat. The `GEOSITE` databases via https://github.com/Loyalsoldier/v2ray-rules-dat.
```yaml ```yaml
rules: rules:
# network condition for all rules # network condition for all rules
- DOMAIN-SUFFIX,bilibili.com,DIRECT,tcp - DOMAIN-SUFFIX,example.com,DIRECT,tcp
- DOMAIN-SUFFIX,bilibili.com,REJECT,udp - 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 # multiport condition for rules SRC-PORT and DST-PORT
- DST-PORT,123/136/137-139,DIRECT,udp - DST-PORT,123/136/137-139,DIRECT,udp

View file

@ -2,6 +2,7 @@ package constant
import ( import (
"net" "net"
"strings"
"github.com/Dreamacro/clash/component/geodata/router" "github.com/Dreamacro/clash/component/geodata/router"
) )
@ -9,8 +10,9 @@ import (
var TunBroadcastAddr = net.IPv4(198, 18, 255, 255) var TunBroadcastAddr = net.IPv4(198, 18, 255, 255)
type RuleExtra struct { type RuleExtra struct {
Network NetWork Network NetWork
SourceIPs []*net.IPNet SourceIPs []*net.IPNet
ProcessNames []string
} }
func (re *RuleExtra) NotMatchNetwork(network NetWork) bool { func (re *RuleExtra) NotMatchNetwork(network NetWork) bool {
@ -30,6 +32,19 @@ func (re *RuleExtra) NotMatchSourceIP(srcIP net.IP) bool {
return true 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 { type RuleGeoSite interface {
GetDomainMatcher() *router.DomainMatcher GetDomainMatcher() *router.DomainMatcher
} }

View file

@ -3,6 +3,7 @@ package rules
import ( import (
"errors" "errors"
"net" "net"
"strings"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
) )
@ -24,9 +25,9 @@ func HasNoResolve(params []string) bool {
func findNetwork(params []string) C.NetWork { func findNetwork(params []string) C.NetWork {
for _, p := range params { for _, p := range params {
if p == "tcp" { if strings.EqualFold(p, "tcp") {
return C.TCP return C.TCP
} else if p == "udp" { } else if strings.EqualFold(p, "udp") {
return C.UDP return C.UDP
} }
} }
@ -51,3 +52,17 @@ func findSourceIPs(params []string) []*net.IPNet {
} }
return nil 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
}

View file

@ -24,9 +24,14 @@ func (g *GEOIP) Match(metadata *C.Metadata) bool {
return false return false
} }
if strings.EqualFold(g.country, "LAN") || C.TunBroadcastAddr.Equal(ip) { if strings.EqualFold(g.country, "LAN") {
return ip.IsPrivate() return ip.IsPrivate() ||
ip.IsUnspecified() ||
ip.IsLoopback() ||
ip.IsMulticast() ||
C.TunBroadcastAddr.Equal(ip)
} }
record, _ := mmdb.Instance().Country(ip) record, _ := mmdb.Instance().Country(ip)
return strings.EqualFold(record.Country.IsoCode, g.country) return strings.EqualFold(record.Country.IsoCode, g.country)
} }

View file

@ -13,8 +13,9 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
) )
ruleExtra := &C.RuleExtra{ ruleExtra := &C.RuleExtra{
Network: findNetwork(params), Network: findNetwork(params),
SourceIPs: findSourceIPs(params), SourceIPs: findSourceIPs(params),
ProcessNames: findProcessName(params),
} }
switch tp { switch tp {

View file

@ -353,6 +353,10 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
if extra.NotMatchSourceIP(metadata.SrcIP) { if extra.NotMatchSourceIP(metadata.SrcIP) {
continue continue
} }
if extra.NotMatchProcessName(metadata.Process) {
continue
}
} }
return adapter, rule, nil return adapter, rule, nil