mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-02-27 01:07:10 +00:00
feat: add IP-ASN rule
This commit is contained in:
@@ -14,8 +14,11 @@ import (
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
var initGeoSite bool
|
||||
var initGeoIP int
|
||||
var (
|
||||
initGeoSite bool
|
||||
initGeoIP int
|
||||
initASN bool
|
||||
)
|
||||
|
||||
func InitGeoSite() error {
|
||||
if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) {
|
||||
@@ -113,7 +116,7 @@ func InitGeoIP() error {
|
||||
}
|
||||
|
||||
if initGeoIP != 2 {
|
||||
if !mmdb.Verify() {
|
||||
if !mmdb.Verify(C.Path.MMDB()) {
|
||||
log.Warnln("MMDB invalid, remove and download")
|
||||
if err := os.Remove(C.Path.MMDB()); err != nil {
|
||||
return fmt.Errorf("can't remove invalid MMDB: %s", err.Error())
|
||||
@@ -126,3 +129,27 @@ func InitGeoIP() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InitASN() error {
|
||||
if _, err := os.Stat(C.Path.ASN()); os.IsNotExist(err) {
|
||||
log.Infoln("Can't find ASN.mmdb, start download")
|
||||
if err := mmdb.DownloadASN(C.Path.ASN()); err != nil {
|
||||
return fmt.Errorf("can't download ASN.mmdb: %s", err.Error())
|
||||
}
|
||||
log.Infoln("Download ASN.mmdb finish")
|
||||
initASN = false
|
||||
}
|
||||
if !initASN {
|
||||
if !mmdb.Verify(C.Path.ASN()) {
|
||||
log.Warnln("ASN invalid, remove and download")
|
||||
if err := os.Remove(C.Path.ASN()); err != nil {
|
||||
return fmt.Errorf("can't remove invalid ASN: %s", err.Error())
|
||||
}
|
||||
if err := mmdb.DownloadASN(C.Path.ASN()); err != nil {
|
||||
return fmt.Errorf("can't download ASN: %s", err.Error())
|
||||
}
|
||||
}
|
||||
initASN = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -25,56 +25,58 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
reader Reader
|
||||
once sync.Once
|
||||
IPreader IPReader
|
||||
ASNreader ASNReader
|
||||
IPonce sync.Once
|
||||
ASNonce sync.Once
|
||||
)
|
||||
|
||||
func LoadFromBytes(buffer []byte) {
|
||||
once.Do(func() {
|
||||
IPonce.Do(func() {
|
||||
mmdb, err := maxminddb.FromBytes(buffer)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't load mmdb: %s", err.Error())
|
||||
}
|
||||
reader = Reader{Reader: mmdb}
|
||||
IPreader = IPReader{Reader: mmdb}
|
||||
switch mmdb.Metadata.DatabaseType {
|
||||
case "sing-geoip":
|
||||
reader.databaseType = typeSing
|
||||
IPreader.databaseType = typeSing
|
||||
case "Meta-geoip0":
|
||||
reader.databaseType = typeMetaV0
|
||||
IPreader.databaseType = typeMetaV0
|
||||
default:
|
||||
reader.databaseType = typeMaxmind
|
||||
IPreader.databaseType = typeMaxmind
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Verify() bool {
|
||||
instance, err := maxminddb.Open(C.Path.MMDB())
|
||||
func Verify(path string) bool {
|
||||
instance, err := maxminddb.Open(path)
|
||||
if err == nil {
|
||||
instance.Close()
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func Instance() Reader {
|
||||
once.Do(func() {
|
||||
func IPInstance() IPReader {
|
||||
IPonce.Do(func() {
|
||||
mmdbPath := C.Path.MMDB()
|
||||
log.Infoln("Load MMDB file: %s", mmdbPath)
|
||||
mmdb, err := maxminddb.Open(mmdbPath)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't load MMDB: %s", err.Error())
|
||||
}
|
||||
reader = Reader{Reader: mmdb}
|
||||
IPreader = IPReader{Reader: mmdb}
|
||||
switch mmdb.Metadata.DatabaseType {
|
||||
case "sing-geoip":
|
||||
reader.databaseType = typeSing
|
||||
IPreader.databaseType = typeSing
|
||||
case "Meta-geoip0":
|
||||
reader.databaseType = typeMetaV0
|
||||
IPreader.databaseType = typeMetaV0
|
||||
default:
|
||||
reader.databaseType = typeMaxmind
|
||||
IPreader.databaseType = typeMaxmind
|
||||
}
|
||||
})
|
||||
|
||||
return reader
|
||||
return IPreader
|
||||
}
|
||||
|
||||
func DownloadMMDB(path string) (err error) {
|
||||
@@ -96,6 +98,43 @@ func DownloadMMDB(path string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func Reload() {
|
||||
mihomoOnce.Reset(&once)
|
||||
func ASNInstance() ASNReader {
|
||||
ASNonce.Do(func() {
|
||||
ASNPath := C.Path.ASN()
|
||||
log.Infoln("Load ASN file: %s", ASNPath)
|
||||
asn, err := maxminddb.Open(ASNPath)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't load ASN: %s", err.Error())
|
||||
}
|
||||
ASNreader = ASNReader{Reader: asn}
|
||||
})
|
||||
|
||||
return ASNreader
|
||||
}
|
||||
|
||||
func DownloadASN(path string) (err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
|
||||
defer cancel()
|
||||
resp, err := mihomoHttp.HttpRequest(ctx, C.ASNUrl, http.MethodGet, http.Header{"User-Agent": {C.UA}}, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func ReloadIP() {
|
||||
mihomoOnce.Reset(&IPonce)
|
||||
}
|
||||
|
||||
func ReloadASN() {
|
||||
mihomoOnce.Reset(&ASNonce)
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ package mmdb
|
||||
import "github.com/oschwald/maxminddb-golang"
|
||||
|
||||
func InstallOverride(override *maxminddb.Reader) {
|
||||
newReader := Reader{Reader: override}
|
||||
newReader := IPReader{Reader: override}
|
||||
switch override.Metadata.DatabaseType {
|
||||
case "sing-geoip":
|
||||
reader.databaseType = typeSing
|
||||
IPreader.databaseType = typeSing
|
||||
case "Meta-geoip0":
|
||||
reader.databaseType = typeMetaV0
|
||||
IPreader.databaseType = typeMetaV0
|
||||
default:
|
||||
reader.databaseType = typeMaxmind
|
||||
IPreader.databaseType = typeMaxmind
|
||||
}
|
||||
reader = newReader
|
||||
IPreader = newReader
|
||||
}
|
||||
|
||||
@@ -14,12 +14,21 @@ type geoip2Country struct {
|
||||
} `maxminddb:"country"`
|
||||
}
|
||||
|
||||
type Reader struct {
|
||||
type IPReader struct {
|
||||
*maxminddb.Reader
|
||||
databaseType
|
||||
}
|
||||
|
||||
func (r Reader) LookupCode(ipAddress net.IP) []string {
|
||||
type ASNReader struct {
|
||||
*maxminddb.Reader
|
||||
}
|
||||
|
||||
type ASNResult struct {
|
||||
AutonomousSystemNumber uint32 `maxminddb:"autonomous_system_number"`
|
||||
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
||||
}
|
||||
|
||||
func (r IPReader) LookupCode(ipAddress net.IP) []string {
|
||||
switch r.databaseType {
|
||||
case typeMaxmind:
|
||||
var country geoip2Country
|
||||
@@ -56,3 +65,9 @@ func (r Reader) LookupCode(ipAddress net.IP) []string {
|
||||
panic(fmt.Sprint("unknown geoip database type:", r.databaseType))
|
||||
}
|
||||
}
|
||||
|
||||
func (r ASNReader) LookupASN(ip net.IP) ASNResult {
|
||||
var result ASNResult
|
||||
r.Lookup(ip, &result)
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user