Fix geosite:ru rule (Normalization to RU vs lowercase ru) (#3971)
* Fix geosite:ru rule (Normalization to RU vs lowercase ru) * fix
This commit is contained in:
@@ -34,6 +34,8 @@ import (
|
||||
"github.com/shirou/gopsutil/v4/load"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
"github.com/shirou/gopsutil/v4/net"
|
||||
"github.com/xtls/xray-core/app/router"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// ProcessState represents the current state of a system process.
|
||||
@@ -1055,6 +1057,48 @@ func (s *ServerService) IsValidGeofileName(filename string) bool {
|
||||
return matched
|
||||
}
|
||||
|
||||
// NormalizeGeositeCountryCodes reads a geosite .dat file, uppercases all
|
||||
// country_code fields, and writes it back. This works around a case-sensitivity
|
||||
// mismatch in Xray-core: the router normalizes codes to uppercase before lookup,
|
||||
// but the find() function compares bytes case-sensitively. Some geosite.dat
|
||||
// providers (e.g. Loyalsoldier) store codes in lowercase, causing lookup failures.
|
||||
func NormalizeGeositeCountryCodes(path string) error {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read geosite file %s: %w", path, err)
|
||||
}
|
||||
|
||||
var list router.GeoSiteList
|
||||
if err := proto.Unmarshal(data, &list); err != nil {
|
||||
return fmt.Errorf("failed to parse geosite file %s: %w", path, err)
|
||||
}
|
||||
|
||||
changed := false
|
||||
for _, entry := range list.Entry {
|
||||
upper := strings.ToUpper(entry.CountryCode)
|
||||
if entry.CountryCode != upper {
|
||||
entry.CountryCode = upper
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
normalized, err := proto.Marshal(&list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize normalized geosite file %s: %w", path, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(path, normalized, 0o644); err != nil {
|
||||
return fmt.Errorf("failed to write normalized geosite file %s: %w", path, err)
|
||||
}
|
||||
|
||||
logger.Infof("Normalized country codes to uppercase in %s (%d entries)", path, len(list.Entry))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServerService) UpdateGeofile(fileName string) error {
|
||||
type geofileEntry struct {
|
||||
URL string
|
||||
@@ -1146,12 +1190,22 @@ func (s *ServerService) UpdateGeofile(fileName string) error {
|
||||
|
||||
var errorMessages []string
|
||||
|
||||
normalizeIfGeosite := func(destPath, name string) {
|
||||
if strings.Contains(name, "geosite") {
|
||||
if err := NormalizeGeositeCountryCodes(destPath); err != nil {
|
||||
logger.Warningf("Failed to normalize geosite country codes in %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if fileName == "" {
|
||||
// Download all geofiles
|
||||
for _, entry := range geofileAllowlist {
|
||||
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
||||
if err := downloadFile(entry.URL, destPath); err != nil {
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
||||
} else {
|
||||
normalizeIfGeosite(destPath, entry.FileName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1159,6 +1213,8 @@ func (s *ServerService) UpdateGeofile(fileName string) error {
|
||||
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
||||
if err := downloadFile(entry.URL, destPath); err != nil {
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
||||
} else {
|
||||
normalizeIfGeosite(destPath, entry.FileName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user