mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-16 02:42:23 +08:00
Add domain_regex rule
This commit is contained in:
parent
8e7f215514
commit
ca5b782106
|
@ -83,6 +83,7 @@ type DefaultRule struct {
|
|||
Domain Listable[string] `json:"domain,omitempty"`
|
||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
||||
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
||||
GeoIP Listable[string] `json:"geoip,omitempty"`
|
||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||
|
@ -108,6 +109,7 @@ func (r DefaultRule) Equals(other DefaultRule) bool {
|
|||
common.ComparableSliceEquals(r.Domain, other.Domain) &&
|
||||
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
||||
common.ComparableSliceEquals(r.DomainKeyword, other.DomainKeyword) &&
|
||||
common.ComparableSliceEquals(r.DomainRegex, other.DomainRegex) &&
|
||||
common.ComparableSliceEquals(r.SourceGeoIP, other.SourceGeoIP) &&
|
||||
common.ComparableSliceEquals(r.GeoIP, other.GeoIP) &&
|
||||
common.ComparableSliceEquals(r.SourceIPCIDR, other.SourceIPCIDR) &&
|
||||
|
|
|
@ -83,6 +83,13 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
if len(options.DomainKeyword) > 0 {
|
||||
rule.items = append(rule.items, NewDomainKeywordItem(options.DomainKeyword))
|
||||
}
|
||||
if len(options.DomainRegex) > 0 {
|
||||
item, err := NewDomainRegexItem(options.DomainRegex)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "domain_regex")
|
||||
}
|
||||
rule.items = append(rule.items, item)
|
||||
}
|
||||
if len(options.SourceGeoIP) > 0 {
|
||||
rule.items = append(rule.items, NewGeoIPItem(router, logger, true, options.SourceGeoIP))
|
||||
}
|
||||
|
@ -92,14 +99,14 @@ func NewDefaultRule(router adapter.Router, logger log.Logger, options option.Def
|
|||
if len(options.SourceIPCIDR) > 0 {
|
||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, E.Cause(err, "source_ipcidr")
|
||||
}
|
||||
rule.items = append(rule.items, item)
|
||||
}
|
||||
if len(options.IPCIDR) > 0 {
|
||||
item, err := NewIPCIDRItem(false, options.IPCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, E.Cause(err, "ipcidr")
|
||||
}
|
||||
rule.items = append(rule.items, item)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
|
@ -18,10 +19,10 @@ type IPCIDRItem struct {
|
|||
|
||||
func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
|
||||
prefixes := make([]netip.Prefix, 0, len(prefixStrings))
|
||||
for _, prefixString := range prefixStrings {
|
||||
for i, prefixString := range prefixStrings {
|
||||
prefix, err := netip.ParsePrefix(prefixString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, E.Cause(err, "parse prefix [", i, "]")
|
||||
}
|
||||
prefixes = append(prefixes, prefix)
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
var _ RuleItem = (*DomainItem)(nil)
|
||||
|
||||
type DomainItem struct {
|
||||
description string
|
||||
matcher *domain.Matcher
|
||||
description string
|
||||
}
|
||||
|
||||
func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
||||
|
@ -41,8 +41,8 @@ func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
|||
}
|
||||
}
|
||||
return &DomainItem{
|
||||
description,
|
||||
domain.NewMatcher(domains, domainSuffixes),
|
||||
description,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
60
route/rule_domain_regex.go
Normal file
60
route/rule_domain_regex.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package route
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*DomainRegexItem)(nil)
|
||||
|
||||
type DomainRegexItem struct {
|
||||
matchers []*regexp.Regexp
|
||||
description string
|
||||
}
|
||||
|
||||
func NewDomainRegexItem(expressions []string) (*DomainRegexItem, error) {
|
||||
matchers := make([]*regexp.Regexp, 0, len(expressions))
|
||||
for i, regex := range expressions {
|
||||
matcher, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse expression ", i)
|
||||
}
|
||||
matchers = append(matchers, matcher)
|
||||
}
|
||||
description := "domain_regex="
|
||||
eLen := len(expressions)
|
||||
if eLen == 1 {
|
||||
description = expressions[0]
|
||||
} else if eLen > 3 {
|
||||
description = F.ToString("[", strings.Join(expressions[:3], " "), "]")
|
||||
} else {
|
||||
description = F.ToString("[", strings.Join(expressions, " "), "]")
|
||||
}
|
||||
return &DomainRegexItem{matchers, description}, nil
|
||||
}
|
||||
|
||||
func (r *DomainRegexItem) Match(metadata *adapter.InboundContext) bool {
|
||||
var domainHost string
|
||||
if metadata.Domain != "" {
|
||||
domainHost = metadata.Domain
|
||||
} else {
|
||||
domainHost = metadata.Destination.Fqdn
|
||||
}
|
||||
if domainHost == "" {
|
||||
return false
|
||||
}
|
||||
for _, matcher := range r.matchers {
|
||||
if matcher.MatchString(domainHost) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *DomainRegexItem) String() string {
|
||||
return r.description
|
||||
}
|
Loading…
Reference in New Issue
Block a user