mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00: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"`
|
Domain Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
||||||
|
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
||||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
||||||
GeoIP Listable[string] `json:"geoip,omitempty"`
|
GeoIP Listable[string] `json:"geoip,omitempty"`
|
||||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,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.Domain, other.Domain) &&
|
||||||
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
||||||
common.ComparableSliceEquals(r.DomainKeyword, other.DomainKeyword) &&
|
common.ComparableSliceEquals(r.DomainKeyword, other.DomainKeyword) &&
|
||||||
|
common.ComparableSliceEquals(r.DomainRegex, other.DomainRegex) &&
|
||||||
common.ComparableSliceEquals(r.SourceGeoIP, other.SourceGeoIP) &&
|
common.ComparableSliceEquals(r.SourceGeoIP, other.SourceGeoIP) &&
|
||||||
common.ComparableSliceEquals(r.GeoIP, other.GeoIP) &&
|
common.ComparableSliceEquals(r.GeoIP, other.GeoIP) &&
|
||||||
common.ComparableSliceEquals(r.SourceIPCIDR, other.SourceIPCIDR) &&
|
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 {
|
if len(options.DomainKeyword) > 0 {
|
||||||
rule.items = append(rule.items, NewDomainKeywordItem(options.DomainKeyword))
|
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 {
|
if len(options.SourceGeoIP) > 0 {
|
||||||
rule.items = append(rule.items, NewGeoIPItem(router, logger, true, options.SourceGeoIP))
|
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 {
|
if len(options.SourceIPCIDR) > 0 {
|
||||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, E.Cause(err, "source_ipcidr")
|
||||||
}
|
}
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
}
|
}
|
||||||
if len(options.IPCIDR) > 0 {
|
if len(options.IPCIDR) > 0 {
|
||||||
item, err := NewIPCIDRItem(false, options.IPCIDR)
|
item, err := NewIPCIDRItem(false, options.IPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, E.Cause(err, "ipcidr")
|
||||||
}
|
}
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,10 +19,10 @@ type IPCIDRItem struct {
|
||||||
|
|
||||||
func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
|
func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
|
||||||
prefixes := make([]netip.Prefix, 0, len(prefixStrings))
|
prefixes := make([]netip.Prefix, 0, len(prefixStrings))
|
||||||
for _, prefixString := range prefixStrings {
|
for i, prefixString := range prefixStrings {
|
||||||
prefix, err := netip.ParsePrefix(prefixString)
|
prefix, err := netip.ParsePrefix(prefixString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, E.Cause(err, "parse prefix [", i, "]")
|
||||||
}
|
}
|
||||||
prefixes = append(prefixes, prefix)
|
prefixes = append(prefixes, prefix)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
var _ RuleItem = (*DomainItem)(nil)
|
var _ RuleItem = (*DomainItem)(nil)
|
||||||
|
|
||||||
type DomainItem struct {
|
type DomainItem struct {
|
||||||
description string
|
|
||||||
matcher *domain.Matcher
|
matcher *domain.Matcher
|
||||||
|
description string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
||||||
|
@ -41,8 +41,8 @@ func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &DomainItem{
|
return &DomainItem{
|
||||||
description,
|
|
||||||
domain.NewMatcher(domains, domainSuffixes),
|
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 a new issue