diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs index c050c863..2b6bdf2b 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs @@ -329,11 +329,52 @@ public partial class CoreConfigSingboxService if (item.Ip?.Count > 0) { var countIp = 0; - foreach (var it in item.Ip) + var negativeIpList = item.Ip.Where(it => it.StartsWith('!')).ToList(); + if (negativeIpList.Count > 0) { - if (ParseV2Address(it, rule2)) + 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) { - countIp++; + 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) + { + if (ParseV2Address(it, rule2)) + { + countIp++; + } } } if (countIp > 0) @@ -459,16 +500,6 @@ public partial class CoreConfigSingboxService rule.geoip ??= []; rule.geoip?.Add(address[Global.GeoIPPrefix.Length..]); } - else if (address.Equals($"{Global.GeoIPPrefix}!private")) - { - rule.ip_is_private = false; - } - else if (address.StartsWith($"{Global.GeoIPPrefix}!")) - { - rule.geoip ??= []; - rule.geoip?.Add(address.Substring($"{Global.GeoIPPrefix}!".Length)); - rule.invert = true; - } else { rule.ip_cidr ??= [];