From 088fdb2dddbda83bb7f07dd4e81f2fce3f67a331 Mon Sep 17 00:00:00 2001 From: hamjin Date: Sun, 25 Feb 2024 22:11:04 +0800 Subject: [PATCH 1/3] Make private ip the same as geoip:private Currently ip.IsPrivate and netip.Addr.IsPrivate only matches a part of private IPs. --- common/nnip/netip.go | 37 +++++++++++++++++++++++++++++++++++++ dns/filters.go | 3 ++- rules/common/geoip.go | 3 ++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/common/nnip/netip.go b/common/nnip/netip.go index e4566138..93fb49b4 100644 --- a/common/nnip/netip.go +++ b/common/nnip/netip.go @@ -6,6 +6,28 @@ import ( "net/netip" ) +// Private IP CIDRs +var privateIPCIDRs = []string{ + "0.0.0.0/8", + "10.0.0.0/8", + "100.64.0.0/10", + "127.0.0.0/8", + "169.254.0.0/16", + "172.16.0.0/12", + "192.0.0.0/24", + "192.0.2.0/24", + "192.88.99.0/24", + "192.168.0.0/16", + "198.18.0.0/15", + "198.51.100.0/24", + "203.0.113.0/24", + "224.0.0.0/3", + "::/127", + "fc00::/7", + "fe80::/10", + "ff00::/8", +} + // IpToAddr converts the net.IP to netip.Addr. // If slice's length is not 4 or 16, IpToAddr returns netip.Addr{} func IpToAddr(slice net.IP) netip.Addr { @@ -51,3 +73,18 @@ func UnMasked(p netip.Prefix) netip.Addr { } return addr } + +// IsPrivateIP returns whether IP is private +// If IP is private, return true, else return false +func IsPrivateIP(ip netip.Addr) bool { + for _, network := range privateIPCIDRs { + _, subnet, err := net.ParseCIDR(network) + if err != nil { + continue + } + if subnet.Contains(ip.AsSlice()) { + return true + } + } + return false +} diff --git a/dns/filters.go b/dns/filters.go index d8633e8b..2751346e 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -4,6 +4,7 @@ import ( "net/netip" "strings" + "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/component/geodata" "github.com/metacubex/mihomo/component/geodata/router" "github.com/metacubex/mihomo/component/mmdb" @@ -26,7 +27,7 @@ func (gf *geoipFilter) Match(ip netip.Addr) bool { if !C.GeodataMode { codes := mmdb.Instance().LookupCode(ip.AsSlice()) for _, code := range codes { - if !strings.EqualFold(code, gf.code) && !ip.IsPrivate() { + if !strings.EqualFold(code, gf.code) && !nnip.IsPrivateIP(ip) { return true } } diff --git a/rules/common/geoip.go b/rules/common/geoip.go index ebca1d16..fe9a1b91 100644 --- a/rules/common/geoip.go +++ b/rules/common/geoip.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/component/geodata" "github.com/metacubex/mihomo/component/geodata/router" "github.com/metacubex/mihomo/component/mmdb" @@ -32,7 +33,7 @@ func (g *GEOIP) Match(metadata *C.Metadata) (bool, string) { } if strings.EqualFold(g.country, "LAN") { - return ip.IsPrivate() || + return nnip.IsPrivateIP(ip) || ip.IsUnspecified() || ip.IsLoopback() || ip.IsMulticast() || From c49cede02b7002a4ec64b26f327c4c8fbe8b81f8 Mon Sep 17 00:00:00 2001 From: hamjin Date: Mon, 26 Feb 2024 14:29:05 +0800 Subject: [PATCH 2/3] Fix for GeodataMode --- dns/filters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns/filters.go b/dns/filters.go index 2751346e..580d5da1 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -42,7 +42,7 @@ func (gf *geoipFilter) Match(ip netip.Addr) bool { return false } } - return !geoIPMatcher.Match(ip) + return !geoIPMatcher.Match(ip) && !nnip.IsPrivateIP(ip) } type ipnetFilter struct { From 9b4857649da4f3ab3c9320a31ac538765903be8e Mon Sep 17 00:00:00 2001 From: hamjin Date: Mon, 26 Feb 2024 14:38:54 +0800 Subject: [PATCH 3/3] fix: GeoIPMatcher doesn't obey the config when using GeoData --- dns/filters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns/filters.go b/dns/filters.go index 580d5da1..f183f11f 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -36,7 +36,7 @@ func (gf *geoipFilter) Match(ip netip.Addr) bool { if geoIPMatcher == nil { var err error - geoIPMatcher, _, err = geodata.LoadGeoIPMatcher("CN") + geoIPMatcher, _, err = geodata.LoadGeoIPMatcher(gf.code) if err != nil { log.Errorln("[GeoIPFilter] LoadGeoIPMatcher error: %s", err.Error()) return false