Skip to content

Commit

Permalink
feat: IP-SUFFIX
Browse files Browse the repository at this point in the history
eg. IP-SUFFIX,0.0.0.124/6,匹配ip二进制后四位(IP-CIDR的倒序),支持ipv6
  • Loading branch information
adlyq committed Jun 2, 2022
1 parent 1af39cb commit 04e5d02
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
6 changes: 6 additions & 0 deletions constant/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const (
GEOIP
IPCIDR
SrcIPCIDR
IPSuffix
SrcIPSuffix
SrcPort
DstPort
Process
Expand Down Expand Up @@ -41,6 +43,10 @@ func (rt RuleType) String() string {
return "IPCIDR"
case SrcIPCIDR:
return "SrcIPCIDR"
case IPSuffix:
return "IPSuffix"
case SrcIPSuffix:
return "SrcIPSuffix"
case SrcPort:
return "SrcPort"
case DstPort:
Expand Down
79 changes: 79 additions & 0 deletions rule/common/ipsuffix.go
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 5 additions & 0 deletions rule/logic/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ func parseRule(tp, payload string, params []string) (C.Rule, error) {
parsed, parseErr = RC.NewIPCIDR(payload, "", RC.WithIPCIDRNoResolve(noResolve))
case "SRC-IP-CIDR":
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":
parsed, parseErr = RC.NewPort(payload, "", true)
case "DST-PORT":
Expand Down
5 changes: 5 additions & 0 deletions rule/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
case "SRC-IP-CIDR":
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":
parsed, parseErr = RC.NewPort(payload, target, true)
case "DST-PORT":
Expand Down
5 changes: 5 additions & 0 deletions rule/provider/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func parseRule(tp, payload, target string, params []string) (C.Rule, error) {
parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve))
case "SRC-IP-CIDR":
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":
parsed, parseErr = RC.NewPort(payload, target, true)
case "DST-PORT":
Expand Down

0 comments on commit 04e5d02

Please sign in to comment.