feat: IP-SUFFIX
eg. IP-SUFFIX,0.0.0.124/6,匹配ip二进制后四位(IP-CIDR的倒序),支持ipv6
This commit is contained in:
parent
1af39cb228
commit
04e5d02ab9
5 changed files with 100 additions and 0 deletions
|
@ -9,6 +9,8 @@ const (
|
||||||
GEOIP
|
GEOIP
|
||||||
IPCIDR
|
IPCIDR
|
||||||
SrcIPCIDR
|
SrcIPCIDR
|
||||||
|
IPSuffix
|
||||||
|
SrcIPSuffix
|
||||||
SrcPort
|
SrcPort
|
||||||
DstPort
|
DstPort
|
||||||
Process
|
Process
|
||||||
|
@ -41,6 +43,10 @@ func (rt RuleType) String() string {
|
||||||
return "IPCIDR"
|
return "IPCIDR"
|
||||||
case SrcIPCIDR:
|
case SrcIPCIDR:
|
||||||
return "SrcIPCIDR"
|
return "SrcIPCIDR"
|
||||||
|
case IPSuffix:
|
||||||
|
return "IPSuffix"
|
||||||
|
case SrcIPSuffix:
|
||||||
|
return "SrcIPSuffix"
|
||||||
case SrcPort:
|
case SrcPort:
|
||||||
return "SrcPort"
|
return "SrcPort"
|
||||||
case DstPort:
|
case DstPort:
|
||||||
|
|
79
rule/common/ipsuffix.go
Normal file
79
rule/common/ipsuffix.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPSuffix struct {
|
||||||
|
*Base
|
||||||
|
ipBytes []byte
|
||||||
|
bits int
|
||||||
|
payload string
|
||||||
|
adapter string
|
||||||
|
isSourceIP bool
|
||||||
|
noResolveIP bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *IPSuffix) RuleType() C.RuleType {
|
||||||
|
if is.isSourceIP {
|
||||||
|
return C.SrcIPSuffix
|
||||||
|
}
|
||||||
|
return C.IPSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *IPSuffix) Match(metadata *C.Metadata) bool {
|
||||||
|
ip := metadata.DstIP
|
||||||
|
if is.isSourceIP {
|
||||||
|
ip = metadata.SrcIP
|
||||||
|
}
|
||||||
|
|
||||||
|
mIPBytes := ip.AsSlice()
|
||||||
|
if len(is.ipBytes) != len(mIPBytes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
size := len(mIPBytes)
|
||||||
|
bits := is.bits
|
||||||
|
|
||||||
|
for i := bits / 8; i > 0; i-- {
|
||||||
|
if is.ipBytes[size-i] != mIPBytes[size-i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is.ipBytes[size-bits/8-1] << (8 - bits%8)) != (mIPBytes[size-bits/8-1] << (8 - bits%8)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *IPSuffix) Adapter() string {
|
||||||
|
return is.adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *IPSuffix) Payload() string {
|
||||||
|
return is.payload
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *IPSuffix) ShouldResolveIP() bool {
|
||||||
|
return !is.noResolveIP
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIPSuffix(payload, adapter string, isSrc, noResolveIP bool) (*IPSuffix, error) {
|
||||||
|
ipnet, err := netip.ParsePrefix(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errPayload
|
||||||
|
}
|
||||||
|
|
||||||
|
return &IPSuffix{
|
||||||
|
Base: &Base{},
|
||||||
|
payload: payload,
|
||||||
|
ipBytes: ipnet.Addr().AsSlice(),
|
||||||
|
bits: ipnet.Bits(),
|
||||||
|
adapter: adapter,
|
||||||
|
isSourceIP: isSrc,
|
||||||
|
noResolveIP: noResolveIP,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -83,6 +83,11 @@ func parseRule(tp, payload string, params []string) (C.Rule, error) {
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, "", RC.WithIPCIDRNoResolve(noResolve))
|
parsed, parseErr = RC.NewIPCIDR(payload, "", RC.WithIPCIDRNoResolve(noResolve))
|
||||||
case "SRC-IP-CIDR":
|
case "SRC-IP-CIDR":
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, "", RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
parsed, parseErr = RC.NewIPCIDR(payload, "", RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
||||||
|
case "IP-SUFFIX":
|
||||||
|
noResolve := RC.HasNoResolve(params)
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, "", false, noResolve)
|
||||||
|
case "SRC-IP-SUFFIX":
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, "", true, true)
|
||||||
case "SRC-PORT":
|
case "SRC-PORT":
|
||||||
parsed, parseErr = RC.NewPort(payload, "", true)
|
parsed, parseErr = RC.NewPort(payload, "", true)
|
||||||
case "DST-PORT":
|
case "DST-PORT":
|
||||||
|
|
|
@ -31,6 +31,11 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
|
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
|
||||||
case "SRC-IP-CIDR":
|
case "SRC-IP-CIDR":
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
||||||
|
case "IP-SUFFIX":
|
||||||
|
noResolve := RC.HasNoResolve(params)
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, target, false, noResolve)
|
||||||
|
case "SRC-IP-SUFFIX":
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, target, true, true)
|
||||||
case "SRC-PORT":
|
case "SRC-PORT":
|
||||||
parsed, parseErr = RC.NewPort(payload, target, true)
|
parsed, parseErr = RC.NewPort(payload, target, true)
|
||||||
case "DST-PORT":
|
case "DST-PORT":
|
||||||
|
|
|
@ -74,6 +74,11 @@ func parseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
|
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
|
||||||
case "SRC-IP-CIDR":
|
case "SRC-IP-CIDR":
|
||||||
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true))
|
||||||
|
case "IP-SUFFIX":
|
||||||
|
noResolve := RC.HasNoResolve(params)
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, target, false, noResolve)
|
||||||
|
case "SRC-IP-SUFFIX":
|
||||||
|
parsed, parseErr = RC.NewIPSuffix(payload, target, true, true)
|
||||||
case "SRC-PORT":
|
case "SRC-PORT":
|
||||||
parsed, parseErr = RC.NewPort(payload, target, true)
|
parsed, parseErr = RC.NewPort(payload, target, true)
|
||||||
case "DST-PORT":
|
case "DST-PORT":
|
||||||
|
|
Loading…
Reference in a new issue