From 88df3f75d55c2b36673c90e2df0fd5549c7cebba Mon Sep 17 00:00:00 2001 From: eternal Date: Sat, 18 Jun 2022 21:08:18 +0800 Subject: [PATCH 1/2] optimize geoip match behavior --- app/dns/nameserver.go | 12 +++++++++++- app/router/condition.go | 13 ++++++++++++- app/router/condition_geoip.go | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index d6f9b2726fa5..fc21289dfb90 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -205,12 +205,22 @@ func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) } newIps := []net.IP{} for _, ip := range ips { + result := false for _, matcher := range c.expectIPs { if matcher.Match(ip) { - newIps = append(newIps, ip) + result = true + if !matcher.IsReverseMatch() { + break + } + } else if matcher.IsReverseMatch() { + result = false break } } + + if result { + newIps = append(newIps, ip) + } } if len(newIps) == 0 { return nil, errExpectedIPNonMatch diff --git a/app/router/condition.go b/app/router/condition.go index cdcb6747504f..11a125aec9e1 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -143,11 +143,22 @@ func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool { ips = ctx.GetTargetIPs() } for _, ip := range ips { + result := false for _, matcher := range m.matchers { if matcher.Match(ip) { - return true + result = true + if !matcher.IsReverseMatch() { + break + } + } else if matcher.IsReverseMatch() { + result = false + break } } + + if result { + return true + } } return false } diff --git a/app/router/condition_geoip.go b/app/router/condition_geoip.go index eb47be833c29..0dd19cd0502f 100644 --- a/app/router/condition_geoip.go +++ b/app/router/condition_geoip.go @@ -85,6 +85,10 @@ func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) { m.reverseMatch = isReverseMatch } +func (m *GeoIPMatcher) IsReverseMatch() bool { + return m.reverseMatch +} + func (m *GeoIPMatcher) match4(ip uint32) bool { if len(m.ip4) == 0 { return false From 326d70b791ea1763fd4653c922eb9b7e0060f283 Mon Sep 17 00:00:00 2001 From: eternal Date: Sat, 18 Jun 2022 23:12:28 +0800 Subject: [PATCH 2/2] add full geoip reverse match --- infra/conf/router.go | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/infra/conf/router.go b/infra/conf/router.go index e10317bd31a4..8d59c85b6496 100644 --- a/infra/conf/router.go +++ b/infra/conf/router.go @@ -416,17 +416,35 @@ func parseDomainRule(domain string) ([]*router.Domain, error) { return []*router.Domain{domainRule}, nil } +func appendCidrsToList(list *[]*router.GeoIP, cidrs *[]*router.CIDR, isReverseMatch bool) { + if len(*cidrs) > 0 { + (*list) = append(*list, &router.GeoIP{ + Cidr: *cidrs, + ReverseMatch: isReverseMatch, + }) + (*cidrs) = []*router.CIDR{} + } +} + func ToCidrList(ips StringList) ([]*router.GeoIP, error) { var geoipList []*router.GeoIP var customCidrs []*router.CIDR + lastIpReverseMatch := false for _, ip := range ips { + isReverseMatch := false + if strings.HasPrefix(ip, "!") { + isReverseMatch = true + ip = ip[1:] + } + if strings.HasPrefix(ip, "geoip:") { + appendCidrsToList(&geoipList, &customCidrs, lastIpReverseMatch) + country := ip[6:] - isReverseMatch := false if strings.HasPrefix(ip, "geoip:!") { country = ip[7:] - isReverseMatch = true + isReverseMatch = !isReverseMatch } if len(country) == 0 { return nil, newError("empty country name in rule") @@ -455,6 +473,8 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) { } } if isExtDatFile != 0 { + appendCidrsToList(&geoipList, &customCidrs, lastIpReverseMatch) + kv := strings.Split(ip[isExtDatFile:], ":") if len(kv) != 2 { return nil, newError("invalid external resource: ", ip) @@ -466,10 +486,9 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) { return nil, newError("empty filename or empty country in rule") } - isReverseMatch := false if strings.HasPrefix(country, "!") { country = country[1:] - isReverseMatch = true + isReverseMatch = !isReverseMatch } geoip, err := loadIP(filename, strings.ToUpper(country)) if err != nil { @@ -485,19 +504,19 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) { continue } + // last ip reverse match state changed, appends customCidrs to geoipList + if lastIpReverseMatch != isReverseMatch { + appendCidrsToList(&geoipList, &customCidrs, lastIpReverseMatch) + } + lastIpReverseMatch = isReverseMatch + ipRule, err := ParseIP(ip) if err != nil { return nil, newError("invalid IP: ", ip).Base(err) } customCidrs = append(customCidrs, ipRule) } - - if len(customCidrs) > 0 { - geoipList = append(geoipList, &router.GeoIP{ - Cidr: customCidrs, - }) - } - + appendCidrsToList(&geoipList, &customCidrs, lastIpReverseMatch) return geoipList, nil }