Fix (#9235)
Some checks are pending
release Linux / build (push) Waiting to run
release Linux / release-zip (push) Blocked by required conditions
release Linux / build and release deb x64 & arm64 (push) Waiting to run
release Linux / build and release rpm x64 & arm64 (push) Waiting to run
release Linux / build and release rpm riscv64 (push) Waiting to run
release macOS / build (push) Waiting to run
release macOS / release-zip (push) Blocked by required conditions
release macOS / package and release macOS dmg (push) Blocked by required conditions
release Windows desktop (Avalonia UI) / build (push) Waiting to run
release Windows desktop (Avalonia UI) / release-zip (push) Blocked by required conditions
release Windows / build (push) Waiting to run
release Windows / release-zip (push) Blocked by required conditions

* Perf routing

* GeoPrefix move to Global

* Fix negative rules

* Fix
This commit is contained in:
DHR60 2026-05-03 08:09:47 +00:00 committed by GitHub
parent 0fac18ba95
commit 37ef25cbfe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 90 additions and 50 deletions

View file

@ -67,6 +67,8 @@ public class Global
public const string AsIs = "AsIs"; public const string AsIs = "AsIs";
public const string IPIfNonMatch = "IPIfNonMatch"; public const string IPIfNonMatch = "IPIfNonMatch";
public const string IPOnDemand = "IPOnDemand"; public const string IPOnDemand = "IPOnDemand";
public const string GeoSitePrefix = "geosite:";
public const string GeoIPPrefix = "geoip:";
public const string UserEMail = "t@t.tt"; public const string UserEMail = "t@t.tt";
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run"; public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";

View file

@ -298,7 +298,7 @@ public partial class CoreConfigSingboxService
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? []; var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
var expectedIPCidr = new List<string>(); var expectedIPCidr = new List<string>();
var expectedIPsRegions = new List<string>(); var expectedIPsRegions = new List<string>();
var regionNames = new HashSet<string>(); var regionName = string.Empty;
if (!string.IsNullOrEmpty(simpleDnsItem?.DirectExpectedIPs)) if (!string.IsNullOrEmpty(simpleDnsItem?.DirectExpectedIPs))
{ {
@ -310,16 +310,16 @@ public partial class CoreConfigSingboxService
foreach (var ip in ipItems) foreach (var ip in ipItems)
{ {
if (ip.StartsWith("geoip:", StringComparison.OrdinalIgnoreCase)) if (ip.StartsWith(Global.GeoIPPrefix, StringComparison.OrdinalIgnoreCase))
{ {
var region = ip["geoip:".Length..]; var region = ip[Global.GeoIPPrefix.Length..];
if (!string.IsNullOrEmpty(region)) if (string.IsNullOrEmpty(region))
{ {
expectedIPsRegions.Add(region); continue;
regionNames.Add(region);
regionNames.Add($"geolocation-{region}");
regionNames.Add($"tld-{region}");
} }
expectedIPsRegions.Add(region);
regionName = region;
} }
else else
{ {
@ -352,19 +352,25 @@ public partial class CoreConfigSingboxService
rule.server = Global.SingboxDirectDNSTag; rule.server = Global.SingboxDirectDNSTag;
rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom); rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);
if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0) if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0 && !regionName.IsNullOrEmpty())
{ {
var geositeSet = new HashSet<string>(rule.geosite); var regionGeosite = rule.geosite.Where(g => g.EndsWith($"-{regionName}", StringComparison.OrdinalIgnoreCase)
if (regionNames.Intersect(geositeSet).Any()) || g.EndsWith($"@{regionName}", StringComparison.OrdinalIgnoreCase)
|| g == regionName).ToList();
if (regionGeosite.Count > 0)
{ {
rule.geosite.RemoveAll(regionGeosite.Contains);
var rule4ExpectedIPs = JsonUtils.DeepCopy(rule);
rule4ExpectedIPs.geosite = regionGeosite;
if (expectedIPsRegions.Count > 0) if (expectedIPsRegions.Count > 0)
{ {
rule.geoip = expectedIPsRegions; rule4ExpectedIPs.geoip = expectedIPsRegions;
} }
if (expectedIPCidr.Count > 0) if (expectedIPCidr.Count > 0)
{ {
rule.ip_cidr = expectedIPCidr; rule4ExpectedIPs.ip_cidr = expectedIPCidr;
} }
_coreConfig.dns.rules.Add(rule4ExpectedIPs);
} }
} }
} }

View file

@ -329,6 +329,46 @@ public partial class CoreConfigSingboxService
if (item.Ip?.Count > 0) if (item.Ip?.Count > 0)
{ {
var countIp = 0; var countIp = 0;
var negativeIpList = item.Ip.Where(it => it.StartsWith('!')).ToList();
if (negativeIpList.Count > 0)
{
var positiveIpList = item.Ip.Except(negativeIpList).ToList();
var positiveRule = rule2;
positiveRule = JsonUtils.DeepCopy(rule2);
positiveRule.outbound = null;
positiveRule.action = null;
foreach (var it in positiveIpList)
{
if (ParseV2Address(it, positiveRule))
{
countIp++;
}
}
var negativeRule = new Rule4Sbox();
foreach (var it in negativeIpList)
{
// Remove first '!' and trim spaces
var ip = it[1..].Trim();
if (ParseV2Address(ip, negativeRule))
{
countIp++;
}
}
negativeRule.invert = true;
rule2 = new Rule4Sbox()
{
outbound = rule2.outbound,
action = rule2.action,
type = "logical",
mode = "or",
rules = [
positiveRule,
negativeRule
]
};
}
else
{
foreach (var it in item.Ip) foreach (var it in item.Ip)
{ {
if (ParseV2Address(it, rule2)) if (ParseV2Address(it, rule2))
@ -336,6 +376,7 @@ public partial class CoreConfigSingboxService
countIp++; countIp++;
} }
} }
}
if (countIp > 0) if (countIp > 0)
{ {
rules.Add(rule2); rules.Add(rule2);
@ -406,10 +447,10 @@ public partial class CoreConfigSingboxService
{ {
return false; return false;
} }
else if (domain.StartsWith("geosite:")) else if (domain.StartsWith(Global.GeoSitePrefix))
{ {
rule.geosite ??= []; rule.geosite ??= [];
rule.geosite?.Add(domain.Substring(8)); rule.geosite?.Add(domain[Global.GeoSitePrefix.Length..]);
} }
else if (domain.StartsWith("regexp:")) else if (domain.StartsWith("regexp:"))
{ {
@ -450,28 +491,18 @@ public partial class CoreConfigSingboxService
{ {
return false; return false;
} }
else if (address.Equals("geoip:private")) else if (address.Equals($"{Global.GeoIPPrefix}private"))
{ {
rule.ip_is_private = true; rule.ip_is_private = true;
} }
else if (address.StartsWith("geoip:")) else if (address.StartsWith(Global.GeoIPPrefix))
{ {
rule.geoip ??= new(); rule.geoip ??= [];
rule.geoip?.Add(address.Substring(6)); rule.geoip?.Add(address[Global.GeoIPPrefix.Length..]);
}
else if (address.Equals("geoip:!private"))
{
rule.ip_is_private = false;
}
else if (address.StartsWith("geoip:!"))
{
rule.geoip ??= new();
rule.geoip?.Add(address.Substring(6));
rule.invert = true;
} }
else else
{ {
rule.ip_cidr ??= new(); rule.ip_cidr ??= [];
rule.ip_cidr?.Add(address); rule.ip_cidr?.Add(address);
} }
return true; return true;

View file

@ -121,7 +121,7 @@ public partial class CoreConfigV2rayService
var proxyGeositeList = new List<string>(); var proxyGeositeList = new List<string>();
var expectedDomainList = new List<string>(); var expectedDomainList = new List<string>();
var expectedIPs = new List<string>(); var expectedIPs = new List<string>();
var regionNames = new HashSet<string>(); var regionName = string.Empty;
var bootstrapDNSAddress = ParseDnsAddresses(simpleDNSItem?.BootstrapDNS, Global.DomainPureIPDNSAddress.First()); var bootstrapDNSAddress = ParseDnsAddresses(simpleDNSItem?.BootstrapDNS, Global.DomainPureIPDNSAddress.First());
var dnsServerDomains = new List<string>(); var dnsServerDomains = new List<string>();
@ -160,18 +160,14 @@ public partial class CoreConfigV2rayService
.Where(s => !string.IsNullOrEmpty(s)) .Where(s => !string.IsNullOrEmpty(s))
.ToList(); .ToList();
foreach (var ip in expectedIPs) foreach (var region in from ip in expectedIPs
where ip.StartsWith(Global.GeoIPPrefix, StringComparison.OrdinalIgnoreCase)
select ip[Global.GeoIPPrefix.Length..]
into region
where !string.IsNullOrEmpty(region)
select region)
{ {
if (ip.StartsWith("geoip:", StringComparison.OrdinalIgnoreCase)) regionName = region;
{
var region = ip["geoip:".Length..];
if (!string.IsNullOrEmpty(region))
{
regionNames.Add($"geosite:{region}");
regionNames.Add($"geosite:geolocation-{region}");
regionNames.Add($"geosite:tld-{region}");
}
}
} }
} }
@ -201,9 +197,14 @@ public partial class CoreConfigV2rayService
if (item.OutboundTag == Global.DirectTag) if (item.OutboundTag == Global.DirectTag)
{ {
if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) if (normalizedDomain.StartsWith(Global.GeoSitePrefix) || normalizedDomain.StartsWith("ext:"))
{ {
(regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain); var isExpectedDomain = !regionName.IsNullOrEmpty()
|| normalizedDomain.EndsWith($"-{regionName}")
|| normalizedDomain.EndsWith($"@{regionName}")
|| normalizedDomain == Global.GeoSitePrefix + regionName;
var targetList = isExpectedDomain ? expectedDomainList : directGeositeList;
targetList.Add(normalizedDomain);
} }
else else
{ {
@ -212,7 +213,7 @@ public partial class CoreConfigV2rayService
} }
else if (item.OutboundTag != Global.BlockTag) else if (item.OutboundTag != Global.BlockTag)
{ {
if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) if (normalizedDomain.StartsWith(Global.GeoSitePrefix) || normalizedDomain.StartsWith("ext:"))
{ {
proxyGeositeList.Add(normalizedDomain); proxyGeositeList.Add(normalizedDomain);
} }

View file

@ -375,8 +375,8 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet); var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules ?? []) foreach (var item in rules ?? [])
{ {
AddPrefixedItems(item.Ip, "geoip:", geoipFiles); AddPrefixedItems(item.Ip, Global.GeoIPPrefix, geoipFiles);
AddPrefixedItems(item.Domain, "geosite:", geoSiteFiles); AddPrefixedItems(item.Domain, Global.GeoSitePrefix, geoSiteFiles);
} }
} }