cachable domain matcher, step 1

pull/692/merge
Darien Raymond 7 years ago
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 { func NewCachableDomainMatcher() *CachableDomainMatcher {
return PlainDomainMatcher(pattern) 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 (v PlainDomainMatcher) Apply(ctx context.Context) bool { 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)
case Domain_Domain:
anyCond.Add(NewSubDomainMatcher(domain.Value))
default:
panic("Unknown domain type.")
}
} }
conds.Add(anyCond) conds.Add(matcher)
} }
if len(rr.Cidr) > 0 { if len(rr.Cidr) > 0 {

Loading…
Cancel
Save