diff --git a/component/geodata/utils.go b/component/geodata/utils.go index 1cf7c63c..e919ce56 100644 --- a/component/geodata/utils.go +++ b/component/geodata/utils.go @@ -2,6 +2,7 @@ package geodata import ( "github.com/Dreamacro/clash/component/geodata/router" + C "github.com/Dreamacro/clash/constant" "strings" ) @@ -17,6 +18,19 @@ func SetLoader(newLoader string) { geoLoaderName = newLoader } +func Verify(name string) bool { + switch name { + case C.GeositeName: + _, _, err := LoadGeoSiteMatcher("CN") + return err == nil + case C.GeoipName: + _, _, err := LoadGeoIPMatcher("CN") + return err == nil + default: + return false + } +} + func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error) { geoLoader, err := GetGeoDataLoader(geoLoaderName) if err != nil { diff --git a/config/config.go b/config/config.go index 8d9465ec..9cc0b3bf 100644 --- a/config/config.go +++ b/config/config.go @@ -41,6 +41,7 @@ type General struct { LogLevel log.LogLevel `json:"log-level"` IPv6 bool `json:"ipv6"` Interface string `json:"-"` + GeodataMode string `json:"geodata-mode"` GeodataLoader string `json:"geodata-loader"` AutoIptables bool `json:"auto-iptables"` } @@ -172,6 +173,7 @@ type RawConfig struct { ExternalUI string `yaml:"external-ui"` Secret string `yaml:"secret"` Interface string `yaml:"interface-name"` + GeodataMode string `yaml:"geodata-mode"` GeodataLoader string `yaml:"geodata-loader"` AutoIptables bool `yaml:"auto-iptables"` @@ -204,6 +206,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { AllowLan: false, BindAddress: "*", Mode: T.Rule, + GeodataMode: "dat", GeodataLoader: "memconservative", AutoIptables: false, UnifiedDelay: false, diff --git a/config/initial.go b/config/initial.go index b2acaa2a..d3c2ce35 100644 --- a/config/initial.go +++ b/config/initial.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "github.com/Dreamacro/clash/component/geodata" "github.com/Dreamacro/clash/component/mmdb" "io" "net/http" @@ -11,6 +12,8 @@ import ( "github.com/Dreamacro/clash/log" ) +var GeodataMode bool + func downloadMMDB(path string) (err error) { resp, err := http.Get("https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/Country.mmdb") if err != nil { @@ -71,16 +74,38 @@ func initGeoSite() error { log.Infoln("Download GeoSite.dat finish") } + if !geodata.Verify(C.GeositeName) { + log.Warnln("GeoSite.dat invalid, remove and download") + if err := os.Remove(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't remove invalid GeoSite.dat: %s", err.Error()) + } + if err := downloadGeoSite(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) + } + } return nil } func initGeoIP() error { - if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) { - log.Infoln("Need GeoIP but can't find GeoIP.dat, start download") - if err := downloadGeoIP(C.Path.GeoIP()); err != nil { - return fmt.Errorf("can't download GeoIP.dat: %s", err.Error()) + if GeodataMode { + if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) { + log.Infoln("Need GeoIP but can't find GeoIP.dat, start download") + if err := downloadGeoIP(C.Path.GeoIP()); err != nil { + return fmt.Errorf("can't download GeoIP.dat: %s", err.Error()) + } + log.Infoln("Download GeoIP.dat finish") } - log.Infoln("Download GeoIP.dat finish") + + if !geodata.Verify(C.GeoipName) { + log.Warnln("GeoIP.dat invalid, remove and download") + if err := os.Remove(C.Path.GeoIP()); err != nil { + return fmt.Errorf("can't remove invalid GeoIP.dat: %s", err.Error()) + } + if err := downloadGeoIP(C.Path.GeoIP()); err != nil { + return fmt.Errorf("can't download GeoIP.dat: %s", err.Error()) + } + } + return nil } if _, err := os.Stat(C.Path.MMDB()); os.IsNotExist(err) { diff --git a/main.go b/main.go index 8d9daff7..cd98a89b 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ var ( flagset map[string]bool version bool testConfig bool + geodataMode bool homeDir string configFile string externalUI string @@ -35,6 +36,7 @@ func init() { flag.StringVar(&externalUI, "ext-ui", "", "override external ui directory") flag.StringVar(&externalController, "ext-ctl", "", "override external controller address") flag.StringVar(&secret, "secret", "", "override secret for RESTful API") + flag.BoolVar(&geodataMode, "m", false, "set geodata mode") flag.BoolVar(&version, "v", false, "show current version of clash") flag.BoolVar(&testConfig, "t", false, "test configuration and exit") flag.Parse() @@ -75,6 +77,10 @@ func main() { log.Fatalln("Initial configuration directory error: %s", err.Error()) } + if geodataMode { + config.GeodataMode = true + } + if testConfig { if _, err := executor.Parse(); err != nil { log.Errorln(err.Error())