Refactor(constant): added rule string enums in configs as RuleConfig for better outside integrations (#2878)
This commit is contained in:
parent
cb8c732375
commit
218c3b4e89
@ -11,6 +11,7 @@ linters:
|
||||
- unconvert
|
||||
- unused
|
||||
- usestdlibvars
|
||||
- exhaustive
|
||||
|
||||
linters-settings:
|
||||
gci:
|
||||
@ -21,3 +22,5 @@ linters-settings:
|
||||
- default
|
||||
staticcheck:
|
||||
go: '1.21'
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
|
@ -52,6 +52,8 @@ func (t Type) String() string {
|
||||
return "Redir"
|
||||
case TPROXY:
|
||||
return "TProxy"
|
||||
case TUNNEL:
|
||||
return "Tunnel"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
@ -1,5 +1,27 @@
|
||||
package constant
|
||||
|
||||
const (
|
||||
RuleConfigDomain RuleConfig = "DOMAIN"
|
||||
RuleConfigDomainSuffix RuleConfig = "DOMAIN-SUFFIX"
|
||||
RuleConfigDomainKeyword RuleConfig = "DOMAIN-KEYWORD"
|
||||
RuleConfigGeoIP RuleConfig = "GEOIP"
|
||||
RuleConfigIPCIDR RuleConfig = "IP-CIDR"
|
||||
RuleConfigIPCIDR6 RuleConfig = "IP-CIDR6"
|
||||
RuleConfigSrcIPCIDR RuleConfig = "SRC-IP-CIDR"
|
||||
RuleConfigSrcPort RuleConfig = "SRC-PORT"
|
||||
RuleConfigDstPort RuleConfig = "DST-PORT"
|
||||
RuleConfigInboundPort RuleConfig = "INBOUND-PORT"
|
||||
RuleConfigProcessName RuleConfig = "PROCESS-NAME"
|
||||
RuleConfigProcessPath RuleConfig = "PROCESS-PATH"
|
||||
RuleConfigIPSet RuleConfig = "IPSET"
|
||||
RuleConfigRuleSet RuleConfig = "RULE-SET"
|
||||
RuleConfigScript RuleConfig = "SCRIPT"
|
||||
RuleConfigMatch RuleConfig = "MATCH"
|
||||
)
|
||||
|
||||
// Rule Config Type String represents a rule type in configuration files.
|
||||
type RuleConfig string
|
||||
|
||||
// Rule Type
|
||||
const (
|
||||
Domain RuleType = iota
|
||||
|
@ -88,6 +88,8 @@ func print(data Event) {
|
||||
log.Errorln(data.Payload)
|
||||
case DEBUG:
|
||||
log.Debugln(data.Payload)
|
||||
case SILENT:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*Domain)(nil)
|
||||
|
||||
type Domain struct {
|
||||
domain string
|
||||
adapter string
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*DomainKeyword)(nil)
|
||||
|
||||
type DomainKeyword struct {
|
||||
keyword string
|
||||
adapter string
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*DomainSuffix)(nil)
|
||||
|
||||
type DomainSuffix struct {
|
||||
suffix string
|
||||
adapter string
|
||||
|
@ -4,6 +4,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*Match)(nil)
|
||||
|
||||
type Match struct {
|
||||
adapter string
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*GEOIP)(nil)
|
||||
|
||||
type GEOIP struct {
|
||||
country string
|
||||
adapter string
|
||||
|
@ -20,6 +20,9 @@ func WithIPCIDRNoResolve(noResolve bool) IPCIDROption {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*IPCIDR)(nil)
|
||||
|
||||
type IPCIDR struct {
|
||||
ipnet *net.IPNet
|
||||
adapter string
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*IPSet)(nil)
|
||||
|
||||
type IPSet struct {
|
||||
name string
|
||||
adapter string
|
||||
|
@ -12,36 +12,40 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
||||
parsed C.Rule
|
||||
)
|
||||
|
||||
switch tp {
|
||||
case "DOMAIN":
|
||||
ruleConfigType := C.RuleConfig(tp)
|
||||
|
||||
switch ruleConfigType {
|
||||
case C.RuleConfigDomain:
|
||||
parsed = NewDomain(payload, target)
|
||||
case "DOMAIN-SUFFIX":
|
||||
case C.RuleConfigDomainSuffix:
|
||||
parsed = NewDomainSuffix(payload, target)
|
||||
case "DOMAIN-KEYWORD":
|
||||
case C.RuleConfigDomainKeyword:
|
||||
parsed = NewDomainKeyword(payload, target)
|
||||
case "GEOIP":
|
||||
case C.RuleConfigGeoIP:
|
||||
noResolve := HasNoResolve(params)
|
||||
parsed = NewGEOIP(payload, target, noResolve)
|
||||
case "IP-CIDR", "IP-CIDR6":
|
||||
case C.RuleConfigIPCIDR, C.RuleConfigIPCIDR6:
|
||||
noResolve := HasNoResolve(params)
|
||||
parsed, parseErr = NewIPCIDR(payload, target, WithIPCIDRNoResolve(noResolve))
|
||||
case "SRC-IP-CIDR":
|
||||
case C.RuleConfigSrcIPCIDR:
|
||||
parsed, parseErr = NewIPCIDR(payload, target, WithIPCIDRSourceIP(true), WithIPCIDRNoResolve(true))
|
||||
case "SRC-PORT":
|
||||
case C.RuleConfigSrcPort:
|
||||
parsed, parseErr = NewPort(payload, target, PortTypeSrc)
|
||||
case "DST-PORT":
|
||||
case C.RuleConfigDstPort:
|
||||
parsed, parseErr = NewPort(payload, target, PortTypeDest)
|
||||
case "INBOUND-PORT":
|
||||
case C.RuleConfigInboundPort:
|
||||
parsed, parseErr = NewPort(payload, target, PortTypeInbound)
|
||||
case "PROCESS-NAME":
|
||||
case C.RuleConfigProcessName:
|
||||
parsed, parseErr = NewProcess(payload, target, true)
|
||||
case "PROCESS-PATH":
|
||||
case C.RuleConfigProcessPath:
|
||||
parsed, parseErr = NewProcess(payload, target, false)
|
||||
case "IPSET":
|
||||
case C.RuleConfigIPSet:
|
||||
noResolve := HasNoResolve(params)
|
||||
parsed, parseErr = NewIPSet(payload, target, noResolve)
|
||||
case "MATCH":
|
||||
case C.RuleConfigMatch:
|
||||
parsed = NewMatch(target)
|
||||
case C.RuleConfigRuleSet, C.RuleConfigScript:
|
||||
parseErr = fmt.Errorf("unsupported rule type %s", tp)
|
||||
default:
|
||||
parseErr = fmt.Errorf("unsupported rule type %s", tp)
|
||||
}
|
||||
|
171
rule/parser_test.go
Normal file
171
rule/parser_test.go
Normal file
@ -0,0 +1,171 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseRule(t *testing.T) {
|
||||
type testCase struct {
|
||||
tp C.RuleConfig
|
||||
payload string
|
||||
target string
|
||||
params []string
|
||||
expectedRule C.Rule
|
||||
expectedError error
|
||||
}
|
||||
|
||||
policy := "DIRECT"
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
tp: C.RuleConfigDomain,
|
||||
payload: "example.com",
|
||||
target: policy,
|
||||
expectedRule: NewDomain("example.com", policy),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigDomainSuffix,
|
||||
payload: "example.com",
|
||||
target: policy,
|
||||
expectedRule: NewDomainSuffix("example.com", policy),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigDomainKeyword,
|
||||
payload: "example.com",
|
||||
target: policy,
|
||||
expectedRule: NewDomainKeyword("example.com", policy),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigGeoIP,
|
||||
payload: "CN",
|
||||
target: policy, params: []string{noResolve},
|
||||
expectedRule: NewGEOIP("CN", policy, true),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPCIDR,
|
||||
payload: "127.0.0.0/8",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewIPCIDR("127.0.0.0/8", policy, WithIPCIDRNoResolve(false))),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPCIDR,
|
||||
payload: "127.0.0.0/8",
|
||||
target: policy, params: []string{noResolve},
|
||||
expectedRule: lo.Must(NewIPCIDR("127.0.0.0/8", policy, WithIPCIDRNoResolve(true))),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPCIDR6,
|
||||
payload: "2001:db8::/32",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewIPCIDR("2001:db8::/32", policy, WithIPCIDRNoResolve(false))),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPCIDR6,
|
||||
payload: "2001:db8::/32",
|
||||
target: policy, params: []string{noResolve},
|
||||
expectedRule: lo.Must(NewIPCIDR("2001:db8::/32", policy, WithIPCIDRNoResolve(true))),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigSrcIPCIDR,
|
||||
payload: "192.168.1.201/32",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewIPCIDR("192.168.1.201/32", policy, WithIPCIDRSourceIP(true), WithIPCIDRNoResolve(true))),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigSrcPort,
|
||||
payload: "80",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewPort("80", policy, PortTypeSrc)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigDstPort,
|
||||
payload: "80",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewPort("80", policy, PortTypeDest)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigInboundPort,
|
||||
payload: "80",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewPort("80", policy, PortTypeInbound)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigProcessName,
|
||||
payload: "example.exe",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewProcess("example.exe", policy, true)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigProcessPath,
|
||||
payload: "C:\\Program Files\\example.exe",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewProcess("C:\\Program Files\\example.exe", policy, false)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigProcessPath,
|
||||
payload: "/opt/example/example",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewProcess("/opt/example/example", policy, false)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPSet,
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedRule: lo.Must(NewIPSet("example", policy, true)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigIPSet,
|
||||
payload: "example",
|
||||
target: policy, params: []string{noResolve},
|
||||
expectedRule: lo.Must(NewIPSet("example", policy, false)),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigMatch,
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedRule: NewMatch(policy),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigRuleSet,
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedError: fmt.Errorf("unsupported rule type %s", C.RuleConfigRuleSet),
|
||||
},
|
||||
{
|
||||
tp: C.RuleConfigScript,
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedError: fmt.Errorf("unsupported rule type %s", C.RuleConfigScript),
|
||||
},
|
||||
{
|
||||
tp: "UNKNOWN",
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedError: errors.New("unsupported rule type UNKNOWN"),
|
||||
},
|
||||
{
|
||||
tp: "ABCD",
|
||||
payload: "example",
|
||||
target: policy,
|
||||
expectedError: errors.New("unsupported rule type ABCD"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
_, err := ParseRule(string(tc.tp), tc.payload, tc.target, tc.params)
|
||||
if tc.expectedError != nil {
|
||||
require.Error(t, err)
|
||||
assert.EqualError(t, err, tc.expectedError.Error())
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,9 @@ const (
|
||||
PortTypeInbound
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*Port)(nil)
|
||||
|
||||
type Port struct {
|
||||
adapter string
|
||||
port C.Port
|
||||
|
@ -7,6 +7,9 @@ import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// Implements C.Rule
|
||||
var _ C.Rule = (*Process)(nil)
|
||||
|
||||
type Process struct {
|
||||
adapter string
|
||||
process string
|
||||
|
@ -165,10 +165,12 @@ func resolveMetadata(ctx C.PlainContext, metadata *C.Metadata) (proxy C.Proxy, r
|
||||
proxy = proxies["DIRECT"]
|
||||
case Global:
|
||||
proxy = proxies["GLOBAL"]
|
||||
// Rule
|
||||
default:
|
||||
case Rule:
|
||||
proxy, rule, err = match(metadata)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown mode: %s", mode))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user