Skip to content

Commit

Permalink
feat: Add sing-geoip database support
Browse files Browse the repository at this point in the history
  • Loading branch information
H1JK committed Jul 14, 2023
1 parent 5dd57ba commit 081e94c
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 19 deletions.
37 changes: 27 additions & 10 deletions component/mmdb/mmdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,59 @@ import (
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"

"github.com/oschwald/geoip2-golang"
"github.com/oschwald/maxminddb-golang"
)

type databaseType = uint8

const (
typeMaxmind databaseType = iota
typeSing
)

var (
mmdb *geoip2.Reader
once sync.Once
reader Reader
once sync.Once
)

func LoadFromBytes(buffer []byte) {
once.Do(func() {
var err error
mmdb, err = geoip2.FromBytes(buffer)
mmdb, err := maxminddb.FromBytes(buffer)
if err != nil {
log.Fatalln("Can't load mmdb: %s", err.Error())
}
reader = Reader{Reader: mmdb}
if mmdb.Metadata.DatabaseType == "sing-geoip" {
reader.databaseType = typeSing
} else {
reader.databaseType = typeMaxmind
}
})
}

func Verify() bool {
instance, err := geoip2.Open(C.Path.MMDB())
instance, err := maxminddb.Open(C.Path.MMDB())
if err == nil {
instance.Close()
}
return err == nil
}

func Instance() *geoip2.Reader {
func Instance() Reader {
once.Do(func() {
var err error
mmdb, err = geoip2.Open(C.Path.MMDB())
mmdb, err := maxminddb.Open(C.Path.MMDB())
if err != nil {
log.Fatalln("Can't load mmdb: %s", err.Error())
}
reader = Reader{Reader: mmdb}
if mmdb.Metadata.DatabaseType == "sing-geoip" {
reader.databaseType = typeSing
} else {
reader.databaseType = typeMaxmind
}
})

return mmdb
return reader
}

func DownloadMMDB(path string) (err error) {
Expand Down
36 changes: 36 additions & 0 deletions component/mmdb/reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package mmdb

import (
"fmt"
"net"

"github.com/oschwald/maxminddb-golang"
)

type geoip2Country struct {
Country struct {
IsoCode string `maxminddb:"iso_code"`
} `maxminddb:"country"`
}

type Reader struct {
*maxminddb.Reader
databaseType
}

func (r Reader) LookupCode(ipAddress net.IP) string {
switch r.databaseType {
case typeMaxmind:
var country geoip2Country
_ = r.Lookup(ipAddress, &country)
return country.Country.IsoCode

case typeSing:
var code string
_ = r.Lookup(ipAddress, &code)
return code

default:
panic(fmt.Sprint("unknown geoip database type:", r.databaseType))
}
}
4 changes: 2 additions & 2 deletions config/updateGeo.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
clashHttp "github.com/Dreamacro/clash/component/http"
C "github.com/Dreamacro/clash/constant"

"github.com/oschwald/geoip2-golang"
"github.com/oschwald/maxminddb-golang"
)

func UpdateGeoDatabases() error {
Expand Down Expand Up @@ -44,7 +44,7 @@ func UpdateGeoDatabases() error {
return fmt.Errorf("can't download MMDB database file: %w", err)
}

instance, err := geoip2.FromBytes(data)
instance, err := maxminddb.FromBytes(data)
if err != nil {
return fmt.Errorf("invalid MMDB database file: %s", err)
}
Expand Down
3 changes: 2 additions & 1 deletion constant/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ func (p *path) MMDB() string {
// 目录则直接跳过
continue
} else {
if strings.EqualFold(fi.Name(), "Country.mmdb") {
if strings.EqualFold(fi.Name(), "Country.mmdb") ||
strings.EqualFold(fi.Name(), "geoip.db") {
GeoipName = fi.Name()
return P.Join(p.homeDir, fi.Name())
}
Expand Down
6 changes: 3 additions & 3 deletions dns/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package dns

import (
"net/netip"
"strings"

"github.com/Dreamacro/clash/component/geodata"
"github.com/Dreamacro/clash/component/geodata/router"
"github.com/Dreamacro/clash/component/mmdb"
"github.com/Dreamacro/clash/component/trie"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"
"strings"
)

type fallbackIPFilter interface {
Expand All @@ -24,8 +24,8 @@ var geoIPMatcher *router.GeoIPMatcher

func (gf *geoipFilter) Match(ip netip.Addr) bool {
if !C.GeodataMode {
record, _ := mmdb.Instance().Country(ip.AsSlice())
return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate()
code := mmdb.Instance().LookupCode(ip.AsSlice())
return !strings.EqualFold(code, gf.code) && !ip.IsPrivate()
}

if geoIPMatcher == nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
github.com/mroth/weightedrand/v2 v2.0.1
github.com/openacid/low v0.1.21
github.com/oschwald/geoip2-golang v1.9.0
github.com/oschwald/maxminddb-golang v1.11.0
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/sing v0.2.8-0.20230703002104-c68251b6d059
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90
Expand Down Expand Up @@ -80,7 +81,6 @@ require (
github.com/metacubex/gvisor v0.0.0-20230611153922-78842f086475 // indirect
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
Expand Down
4 changes: 2 additions & 2 deletions rules/common/geoip.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func (g *GEOIP) Match(metadata *C.Metadata) (bool, string) {
resolver.IsFakeBroadcastIP(ip), g.adapter
}
if !C.GeodataMode {
record, _ := mmdb.Instance().Country(ip.AsSlice())
return strings.EqualFold(record.Country.IsoCode, g.country), g.adapter
code := mmdb.Instance().LookupCode(ip.AsSlice())
return strings.EqualFold(code, g.country), g.adapter
}
return g.geoIPMatcher.Match(ip.AsSlice()), g.adapter
}
Expand Down

0 comments on commit 081e94c

Please sign in to comment.