mirror of https://github.com/v2ray/v2ray-core
cachable domain matcher, step 1
parent
482793d28a
commit
6b77e14bf6
|
@ -64,13 +64,35 @@ func (v *AnyCondition) Len() int {
|
||||||
return len(*v)
|
return len(*v)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainDomainMatcher string
|
type CachableDomainMatcher struct {
|
||||||
|
matchers []domainMatcher
|
||||||
func NewPlainDomainMatcher(pattern string) Condition {
|
|
||||||
return PlainDomainMatcher(pattern)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PlainDomainMatcher) Apply(ctx context.Context) bool {
|
func NewCachableDomainMatcher() *CachableDomainMatcher {
|
||||||
|
return &CachableDomainMatcher{
|
||||||
|
matchers: make([]domainMatcher, 0, 64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CachableDomainMatcher) Add(domain *Domain) error {
|
||||||
|
switch domain.Type {
|
||||||
|
case Domain_Plain:
|
||||||
|
m.matchers = append(m.matchers, NewPlainDomainMatcher(domain.Value))
|
||||||
|
case Domain_Regex:
|
||||||
|
rm, err := NewRegexpDomainMatcher(domain.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.matchers = append(m.matchers, rm)
|
||||||
|
case Domain_Domain:
|
||||||
|
m.matchers = append(m.matchers, NewSubDomainMatcher(domain.Value))
|
||||||
|
default:
|
||||||
|
return newError("unknown domain type: ", domain.Type).AtError()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CachableDomainMatcher) Apply(ctx context.Context) bool {
|
||||||
dest, ok := proxy.TargetFromContext(ctx)
|
dest, ok := proxy.TargetFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
|
@ -80,6 +102,27 @@ func (v PlainDomainMatcher) Apply(ctx context.Context) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
domain := dest.Address.Domain()
|
domain := dest.Address.Domain()
|
||||||
|
|
||||||
|
for _, matcher := range m.matchers {
|
||||||
|
if matcher.Apply(domain) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type domainMatcher interface {
|
||||||
|
Apply(domain string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlainDomainMatcher string
|
||||||
|
|
||||||
|
func NewPlainDomainMatcher(pattern string) PlainDomainMatcher {
|
||||||
|
return PlainDomainMatcher(pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v PlainDomainMatcher) Apply(domain string) bool {
|
||||||
return strings.Contains(domain, string(v))
|
return strings.Contains(domain, string(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,33 +140,17 @@ func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *RegexpDomainMatcher) Apply(ctx context.Context) bool {
|
func (v *RegexpDomainMatcher) Apply(domain string) bool {
|
||||||
dest, ok := proxy.TargetFromContext(ctx)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !dest.Address.Family().IsDomain() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
domain := dest.Address.Domain()
|
|
||||||
return v.pattern.MatchString(strings.ToLower(domain))
|
return v.pattern.MatchString(strings.ToLower(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubDomainMatcher string
|
type SubDomainMatcher string
|
||||||
|
|
||||||
func NewSubDomainMatcher(p string) Condition {
|
func NewSubDomainMatcher(p string) SubDomainMatcher {
|
||||||
return SubDomainMatcher(p)
|
return SubDomainMatcher(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m SubDomainMatcher) Apply(ctx context.Context) bool {
|
func (m SubDomainMatcher) Apply(domain string) bool {
|
||||||
dest, ok := proxy.TargetFromContext(ctx)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !dest.Address.Family().IsDomain() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
domain := dest.Address.Domain()
|
|
||||||
pattern := string(m)
|
pattern := string(m)
|
||||||
if !strings.HasSuffix(domain, pattern) {
|
if !strings.HasSuffix(domain, pattern) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -16,32 +16,32 @@ func TestSubDomainMatcher(t *testing.T) {
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
pattern string
|
pattern string
|
||||||
input context.Context
|
input string
|
||||||
output bool
|
output bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
pattern: "v2ray.com",
|
pattern: "v2ray.com",
|
||||||
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com"), 80)),
|
input: "www.v2ray.com",
|
||||||
output: true,
|
output: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "v2ray.com",
|
pattern: "v2ray.com",
|
||||||
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)),
|
input: "v2ray.com",
|
||||||
output: true,
|
output: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "v2ray.com",
|
pattern: "v2ray.com",
|
||||||
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v3ray.com"), 80)),
|
input: "www.v3ray.com",
|
||||||
output: false,
|
output: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "v2ray.com",
|
pattern: "v2ray.com",
|
||||||
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("2ray.com"), 80)),
|
input: "2ray.com",
|
||||||
output: false,
|
output: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "v2ray.com",
|
pattern: "v2ray.com",
|
||||||
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("xv2ray.com"), 80)),
|
input: "xv2ray.com",
|
||||||
output: false,
|
output: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,24 +52,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||||
conds := NewConditionChan()
|
conds := NewConditionChan()
|
||||||
|
|
||||||
if len(rr.Domain) > 0 {
|
if len(rr.Domain) > 0 {
|
||||||
anyCond := NewAnyCondition()
|
matcher := NewCachableDomainMatcher()
|
||||||
for _, domain := range rr.Domain {
|
for _, domain := range rr.Domain {
|
||||||
switch domain.Type {
|
matcher.Add(domain)
|
||||||
case Domain_Plain:
|
|
||||||
anyCond.Add(NewPlainDomainMatcher(domain.Value))
|
|
||||||
case Domain_Regex:
|
|
||||||
matcher, err := NewRegexpDomainMatcher(domain.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
anyCond.Add(matcher)
|
conds.Add(matcher)
|
||||||
case Domain_Domain:
|
|
||||||
anyCond.Add(NewSubDomainMatcher(domain.Value))
|
|
||||||
default:
|
|
||||||
panic("Unknown domain type.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conds.Add(anyCond)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Cidr) > 0 {
|
if len(rr.Cidr) > 0 {
|
||||||
|
|
Loading…
Reference in New Issue