Feature: support IPSET rule (#2693)
This commit is contained in:
parent
765982e86a
commit
6eee226965
22
component/ipset/ipset_linux.go
Normal file
22
component/ipset/ipset_linux.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package ipset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test whether the ip is in the set or not
|
||||||
|
func Test(setName string, ip net.IP) (bool, error) {
|
||||||
|
return netlink.IpsetTest(setName, &netlink.IPSetEntry{
|
||||||
|
IP: ip,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify dumps a specific ipset to check if we can use the set normally
|
||||||
|
func Verify(setName string) error {
|
||||||
|
_, err := netlink.IpsetList(setName)
|
||||||
|
return err
|
||||||
|
}
|
17
component/ipset/ipset_others.go
Normal file
17
component/ipset/ipset_others.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package ipset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Always return false in non-linux
|
||||||
|
func Test(setName string, ip net.IP) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always pass in non-linux
|
||||||
|
func Verify(setName string) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -12,6 +12,7 @@ const (
|
|||||||
DstPort
|
DstPort
|
||||||
Process
|
Process
|
||||||
ProcessPath
|
ProcessPath
|
||||||
|
IPSet
|
||||||
MATCH
|
MATCH
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +40,8 @@ func (rt RuleType) String() string {
|
|||||||
return "Process"
|
return "Process"
|
||||||
case ProcessPath:
|
case ProcessPath:
|
||||||
return "ProcessPath"
|
return "ProcessPath"
|
||||||
|
case IPSet:
|
||||||
|
return "IPSet"
|
||||||
case MATCH:
|
case MATCH:
|
||||||
return "Match"
|
return "Match"
|
||||||
default:
|
default:
|
||||||
|
2
go.mod
2
go.mod
@ -16,6 +16,7 @@ require (
|
|||||||
github.com/samber/lo v1.38.1
|
github.com/samber/lo v1.38.1
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230420174744-55c8b9515a01
|
||||||
go.etcd.io/bbolt v1.3.7
|
go.etcd.io/bbolt v1.3.7
|
||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
go.uber.org/automaxprocs v1.5.2
|
go.uber.org/automaxprocs v1.5.2
|
||||||
@ -37,6 +38,7 @@ require (
|
|||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
|
||||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -55,6 +55,10 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ
|
|||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230420174744-55c8b9515a01 h1:F9xjJm4IH8VjcqG4ujciOF+GIM4mjPkHhWLLzOghPtM=
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230420174744-55c8b9515a01/go.mod h1:cAAsePK2e15YDAMJNyOpGYEWNe4sIghTY7gpz4cX/Ik=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
@ -71,8 +75,10 @@ golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
|||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
54
rule/ipset.go
Normal file
54
rule/ipset.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package rules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Dreamacro/clash/component/ipset"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPSet struct {
|
||||||
|
name string
|
||||||
|
adapter string
|
||||||
|
noResolveIP bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) RuleType() C.RuleType {
|
||||||
|
return C.IPSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) Match(metadata *C.Metadata) bool {
|
||||||
|
exist, err := ipset.Test(f.name, metadata.DstIP)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("check ipset '%s' failed: %s", f.name, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return exist
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) Adapter() string {
|
||||||
|
return f.adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) Payload() string {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) ShouldResolveIP() bool {
|
||||||
|
return !f.noResolveIP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSet) ShouldFindProcess() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIPSet(name string, adapter string, noResolveIP bool) (*IPSet, error) {
|
||||||
|
if err := ipset.Verify(name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &IPSet{
|
||||||
|
name: name,
|
||||||
|
adapter: adapter,
|
||||||
|
noResolveIP: noResolveIP,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -35,6 +35,9 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
|||||||
parsed, parseErr = NewProcess(payload, target, true)
|
parsed, parseErr = NewProcess(payload, target, true)
|
||||||
case "PROCESS-PATH":
|
case "PROCESS-PATH":
|
||||||
parsed, parseErr = NewProcess(payload, target, false)
|
parsed, parseErr = NewProcess(payload, target, false)
|
||||||
|
case "IPSET":
|
||||||
|
noResolve := HasNoResolve(params)
|
||||||
|
parsed, parseErr = NewIPSet(payload, target, noResolve)
|
||||||
case "MATCH":
|
case "MATCH":
|
||||||
parsed = NewMatch(target)
|
parsed = NewMatch(target)
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user