1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-22 01:57:12 -05:00

Amend domain matcher with returning values of all matched subdomains

This commit is contained in:
Vigilans 2020-08-13 15:26:30 +08:00
parent 8b4ba03e6f
commit 1e222425b6
3 changed files with 60 additions and 12 deletions

View File

@ -53,6 +53,9 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
} else if q.Name == "api.google.com." && q.Qtype == dns.TypeA { } else if q.Name == "api.google.com." && q.Qtype == dns.TypeA {
rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7") rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7")
ans.Answer = append(ans.Answer, rr) ans.Answer = append(ans.Answer, rr)
} else if q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA {
rr, _ := dns.NewRR("v2.api.google.com. IN A 8.8.7.8")
ans.Answer = append(ans.Answer, rr)
} else if q.Name == "facebook.com." && q.Qtype == dns.TypeA { } else if q.Name == "facebook.com." && q.Qtype == dns.TypeA {
rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9") rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
ans.Answer = append(ans.Answer, rr) ans.Answer = append(ans.Answer, rr)
@ -847,14 +850,38 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
PrioritizedDomain: []*NameServer_PriorityDomain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: DomainMatchingType_Full, Type: DomainMatchingType_Subdomain,
Domain: "api.google.com", Domain: "api.google.com",
}, },
}, },
Geoip: []*router.GeoIP{ Geoip: []*router.GeoIP{
{ // Will only match 8.8.7.7 (api.google.com) { // Will only match 8.8.7.7 (api.google.com)
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 7}, Prefix: 0}, {Ip: []byte{8, 8, 7, 7}, Prefix: 32},
},
},
},
},
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
PrioritizedDomain: []*NameServer_PriorityDomain{
{
Type: DomainMatchingType_Full,
Domain: "v2.api.google.com",
},
},
Geoip: []*router.GeoIP{
{ // Will only match 8.8.7.8 (v2.api.google.com)
Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
}, },
}, },
}, },
@ -902,7 +929,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
} }
{ // Will match server 1,2,3 and server 1,2 returns unexpected ip, then server 3 returns expected one { // Will match server 3,1,2 and server 3 returns expected one
ips, err := client.LookupIP("api.google.com") ips, err := client.LookupIP("api.google.com")
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
@ -913,6 +940,17 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
} }
{ // Will match server 4,3,1,2 and server 4 returns expected one
ips, err := client.LookupIP("v2.api.google.com")
if err != nil {
t.Fatal("unexpected error: ", err)
}
if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 8}}); r != "" {
t.Fatal(r)
}
}
endTime := time.Now() endTime := time.Now()
if startTime.After(endTime.Add(time.Second * 2)) { if startTime.After(endTime.Add(time.Second * 2)) {
t.Error("DNS query doesn't finish in 2 seconds.") t.Error("DNS query doesn't finish in 2 seconds.")

View File

@ -25,11 +25,6 @@ func (g *DomainMatcherGroup) Add(domain string, value uint32) {
current := g.root current := g.root
parts := breakDomain(domain) parts := breakDomain(domain)
for i := len(parts) - 1; i >= 0; i-- { for i := len(parts) - 1; i >= 0; i-- {
if len(current.values) > 0 {
// if current node is already a match, it is not necessary to match further.
return
}
part := parts[i] part := parts[i]
if current.sub == nil { if current.sub == nil {
current.sub = make(map[string]*node) current.sub = make(map[string]*node)
@ -43,7 +38,6 @@ func (g *DomainMatcherGroup) Add(domain string, value uint32) {
} }
current.values = append(current.values, value) current.values = append(current.values, value)
current.sub = nil // shortcut sub nodes as current node is a match.
} }
func (g *DomainMatcherGroup) addMatcher(m domainMatcher, value uint32) { func (g *DomainMatcherGroup) addMatcher(m domainMatcher, value uint32) {
@ -69,6 +63,7 @@ func (g *DomainMatcherGroup) Match(domain string) []uint32 {
return -1 return -1
} }
matches := [][]uint32{}
idx := len(domain) idx := len(domain)
for { for {
if idx == -1 || current.sub == nil { if idx == -1 || current.sub == nil {
@ -83,6 +78,21 @@ func (g *DomainMatcherGroup) Match(domain string) []uint32 {
} }
current = next current = next
idx = nidx idx = nidx
if len(current.values) > 0 {
matches = append(matches, current.values)
}
}
switch len(matches) {
case 0:
return nil
case 1:
return matches[0]
default:
result := []uint32{}
for idx := range matches {
// Insert reversely, the subdomain that matches further ranks higher
result = append(result, matches[len(matches)-1-idx]...)
}
return result
} }
return current.values
} }

View File

@ -33,9 +33,9 @@ func TestDomainMatcherGroup(t *testing.T) {
Domain: "a.b.com", Domain: "a.b.com",
Result: []uint32{4}, Result: []uint32{4},
}, },
{ { // Matches [c.a.b.com, a.b.com]
Domain: "c.a.b.com", Domain: "c.a.b.com",
Result: []uint32{4}, Result: []uint32{5, 4},
}, },
{ {
Domain: "c.a..b.com", Domain: "c.a..b.com",