feat: Add Meta-geoip V0 database support
This commit is contained in:
parent
a82745f544
commit
b0e76ec791
5 changed files with 54 additions and 14 deletions
|
@ -20,6 +20,7 @@ type databaseType = uint8
|
|||
const (
|
||||
typeMaxmind databaseType = iota
|
||||
typeSing
|
||||
typeMetaV0
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -34,9 +35,12 @@ func LoadFromBytes(buffer []byte) {
|
|||
log.Fatalln("Can't load mmdb: %s", err.Error())
|
||||
}
|
||||
reader = Reader{Reader: mmdb}
|
||||
if mmdb.Metadata.DatabaseType == "sing-geoip" {
|
||||
switch mmdb.Metadata.DatabaseType {
|
||||
case "sing-geoip":
|
||||
reader.databaseType = typeSing
|
||||
} else {
|
||||
case "Meta-geoip0":
|
||||
reader.databaseType = typeMetaV0
|
||||
default:
|
||||
reader.databaseType = typeMaxmind
|
||||
}
|
||||
})
|
||||
|
@ -52,14 +56,19 @@ func Verify() bool {
|
|||
|
||||
func Instance() Reader {
|
||||
once.Do(func() {
|
||||
mmdb, err := maxminddb.Open(C.Path.MMDB())
|
||||
mmdbPath := C.Path.MMDB()
|
||||
log.Debugln("Load MMDB file: %s", mmdbPath)
|
||||
mmdb, err := maxminddb.Open(mmdbPath)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't load mmdb: %s", err.Error())
|
||||
log.Fatalln("Can't load MMDB: %s", err.Error())
|
||||
}
|
||||
reader = Reader{Reader: mmdb}
|
||||
if mmdb.Metadata.DatabaseType == "sing-geoip" {
|
||||
switch mmdb.Metadata.DatabaseType {
|
||||
case "sing-geoip":
|
||||
reader.databaseType = typeSing
|
||||
} else {
|
||||
case "Meta-geoip0":
|
||||
reader.databaseType = typeMetaV0
|
||||
default:
|
||||
reader.databaseType = typeMaxmind
|
||||
}
|
||||
})
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/oschwald/maxminddb-golang"
|
||||
"github.com/sagernet/sing/common"
|
||||
)
|
||||
|
||||
type geoip2Country struct {
|
||||
|
@ -18,17 +19,36 @@ type Reader struct {
|
|||
databaseType
|
||||
}
|
||||
|
||||
func (r Reader) LookupCode(ipAddress net.IP) string {
|
||||
func (r Reader) LookupCode(ipAddress net.IP) []string {
|
||||
switch r.databaseType {
|
||||
case typeMaxmind:
|
||||
var country geoip2Country
|
||||
_ = r.Lookup(ipAddress, &country)
|
||||
return country.Country.IsoCode
|
||||
if country.Country.IsoCode == "" {
|
||||
return []string{}
|
||||
}
|
||||
return []string{country.Country.IsoCode}
|
||||
|
||||
case typeSing:
|
||||
var code string
|
||||
_ = r.Lookup(ipAddress, &code)
|
||||
return code
|
||||
if code == "" {
|
||||
return []string{}
|
||||
}
|
||||
return []string{code}
|
||||
|
||||
case typeMetaV0:
|
||||
var record any
|
||||
_ = r.Lookup(ipAddress, &record)
|
||||
switch record := record.(type) {
|
||||
case string:
|
||||
return []string{record}
|
||||
case []any: // lookup returned type of slice is []any
|
||||
return common.Map(record, func(it any) string {
|
||||
return it.(string)
|
||||
})
|
||||
}
|
||||
return []string{}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprint("unknown geoip database type:", r.databaseType))
|
||||
|
|
|
@ -92,7 +92,8 @@ func (p *path) MMDB() string {
|
|||
continue
|
||||
} else {
|
||||
if strings.EqualFold(fi.Name(), "Country.mmdb") ||
|
||||
strings.EqualFold(fi.Name(), "geoip.db") {
|
||||
strings.EqualFold(fi.Name(), "geoip.db") ||
|
||||
strings.EqualFold(fi.Name(), "geoip.metadb") {
|
||||
GeoipName = fi.Name()
|
||||
return P.Join(p.homeDir, fi.Name())
|
||||
}
|
||||
|
|
|
@ -24,8 +24,13 @@ var geoIPMatcher *router.GeoIPMatcher
|
|||
|
||||
func (gf *geoipFilter) Match(ip netip.Addr) bool {
|
||||
if !C.GeodataMode {
|
||||
code := mmdb.Instance().LookupCode(ip.AsSlice())
|
||||
return !strings.EqualFold(code, gf.code) && !ip.IsPrivate()
|
||||
codes := mmdb.Instance().LookupCode(ip.AsSlice())
|
||||
for _, code := range codes {
|
||||
if !strings.EqualFold(code, gf.code) && !ip.IsPrivate() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if geoIPMatcher == nil {
|
||||
|
|
|
@ -40,8 +40,13 @@ func (g *GEOIP) Match(metadata *C.Metadata) (bool, string) {
|
|||
resolver.IsFakeBroadcastIP(ip), g.adapter
|
||||
}
|
||||
if !C.GeodataMode {
|
||||
code := mmdb.Instance().LookupCode(ip.AsSlice())
|
||||
return strings.EqualFold(code, g.country), g.adapter
|
||||
codes := mmdb.Instance().LookupCode(ip.AsSlice())
|
||||
for _, code := range codes {
|
||||
if strings.EqualFold(code, g.country) {
|
||||
return true, g.adapter
|
||||
}
|
||||
}
|
||||
return false, g.adapter
|
||||
}
|
||||
return g.geoIPMatcher.Match(ip.AsSlice()), g.adapter
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue