Refactor core config gen (#8768)

* Refactor core config gen

* Update tag naming

* Support sing-box 1.11 DNS

* Fix

* Optimize ProfileItem acquisition speed

* Fix

* Fix
This commit is contained in:
DHR60
2026-02-24 11:48:59 +00:00
committed by GitHub
parent b5800f7dfc
commit 9c82df5b49
29 changed files with 1284 additions and 2207 deletions
@@ -1,43 +1,34 @@
namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService(Config config)
public partial class CoreConfigSingboxService(CoreConfigContext context)
{
private readonly Config _config = config;
private static readonly string _tag = "CoreConfigSingboxService";
private readonly Config _config = context.AppConfig;
private readonly ProfileItem _node = context.Node;
private SingboxConfig _coreConfig = new();
#region public gen function
public async Task<RetResult> GenerateClientConfigContent(ProfileItem node)
public RetResult GenerateClientConfigContent()
{
var ret = new RetResult();
try
{
if (node == null
|| !node.IsValid())
if (_node == null
|| !_node.IsValid())
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
if (_node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
{
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
ret.Msg = ResUI.Incorrectconfiguration + $" - {_node.GetNetwork()}";
return ret;
}
ret.Msg = ResUI.InitialConfiguration;
if (node.ConfigType.IsGroupType())
{
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(node);
case EConfigType.ProxyChain:
return await GenerateClientChainConfig(node);
}
}
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
if (result.IsNullOrEmpty())
{
@@ -45,44 +36,31 @@ public partial class CoreConfigSingboxService(Config config)
return ret;
}
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (singboxConfig == null)
_coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (_coreConfig == null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
await GenLog(singboxConfig);
GenLog();
await GenInbounds(singboxConfig);
GenInbounds();
if (node.ConfigType == EConfigType.WireGuard)
{
singboxConfig.outbounds.RemoveAt(0);
var endpoints = new Endpoints4Sbox();
await GenEndpoint(node, endpoints);
endpoints.tag = Global.ProxyTag;
singboxConfig.endpoints = new() { endpoints };
}
else
{
await GenOutbound(node, singboxConfig.outbounds.First());
}
GenOutbounds();
await GenMoreOutbounds(node, singboxConfig);
GenRouting();
await GenRouting(singboxConfig);
GenDns();
await GenDns(node, singboxConfig);
GenExperimental();
await GenExperimental(singboxConfig);
await ConvertGeo2Ruleset(singboxConfig);
ConvertGeo2Ruleset();
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
ret.Data = await ApplyFullConfigTemplate(singboxConfig);
ret.Data = ApplyFullConfigTemplate();
return ret;
}
catch (Exception ex)
@@ -93,17 +71,11 @@ public partial class CoreConfigSingboxService(Config config)
}
}
public async Task<RetResult> GenerateClientSpeedtestConfig(List<ServerTestItem> selecteds)
public RetResult GenerateClientSpeedtestConfig(List<ServerTestItem> selecteds)
{
var ret = new RetResult();
try
{
if (_config == null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
ret.Msg = ResUI.InitialConfiguration;
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
@@ -114,8 +86,8 @@ public partial class CoreConfigSingboxService(Config config)
return ret;
}
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (singboxConfig == null)
_coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (_coreConfig == null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
@@ -133,10 +105,10 @@ public partial class CoreConfigSingboxService(Config config)
Logging.SaveLog(_tag, ex);
}
await GenLog(singboxConfig);
//GenDns(new(), singboxConfig);
singboxConfig.inbounds.Clear();
singboxConfig.outbounds.RemoveAt(0);
GenLog();
GenMinimizedDns();
_coreConfig.inbounds.Clear();
_coreConfig.outbounds.RemoveAt(0);
var initPort = AppManager.Instance.GetLocalPort(EInboundProtocol.speedtest);
@@ -150,7 +122,7 @@ public partial class CoreConfigSingboxService(Config config)
{
continue;
}
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
var item = context.AllProxiesMap.GetValueOrDefault(it.IndexId);
if (item is null || item.IsComplex() || !item.IsValid())
{
continue;
@@ -190,26 +162,11 @@ public partial class CoreConfigSingboxService(Config config)
type = EInboundProtocol.mixed.ToString(),
};
inbound.tag = inbound.type + inbound.listen_port.ToString();
singboxConfig.inbounds.Add(inbound);
_coreConfig.inbounds.Add(inbound);
//outbound
var server = await GenServer(item);
if (server is null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
var tag = Global.ProxyTag + inbound.listen_port.ToString();
server.tag = tag;
if (server is Endpoints4Sbox endpoint)
{
singboxConfig.endpoints ??= new();
singboxConfig.endpoints.Add(endpoint);
}
else if (server is Outbound4Sbox outbound)
{
singboxConfig.outbounds.Add(outbound);
}
var serverList = new CoreConfigSingboxService(context with { Node = item }).BuildAllProxyOutbounds(tag);
FillRangeProxy(serverList, _coreConfig, false);
//rule
Rule4Sbox rule = new()
@@ -217,25 +174,11 @@ public partial class CoreConfigSingboxService(Config config)
inbound = new List<string> { inbound.tag },
outbound = tag
};
singboxConfig.route.rules.Add(rule);
_coreConfig.route.rules.Add(rule);
}
var rawDNSItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (rawDNSItem != null && rawDNSItem.Enabled == true)
{
await GenDnsDomainsCompatible(singboxConfig, rawDNSItem);
}
else
{
await GenDnsDomains(singboxConfig, _config.SimpleDNSItem);
}
singboxConfig.route.default_domain_resolver = new()
{
server = Global.SingboxLocalDNSTag,
};
ret.Success = true;
ret.Data = JsonUtils.Serialize(singboxConfig);
ret.Data = JsonUtils.Serialize(_coreConfig);
return ret;
}
catch (Exception ex)
@@ -246,20 +189,20 @@ public partial class CoreConfigSingboxService(Config config)
}
}
public async Task<RetResult> GenerateClientSpeedtestConfig(ProfileItem node, int port)
public RetResult GenerateClientSpeedtestConfig(int port)
{
var ret = new RetResult();
try
{
if (node == null
|| !node.IsValid())
if (_node == null
|| !_node.IsValid())
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
if (_node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
{
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
ret.Msg = ResUI.Incorrectconfiguration + $" - {_node.GetNetwork()}";
return ret;
}
@@ -272,44 +215,20 @@ public partial class CoreConfigSingboxService(Config config)
return ret;
}
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (singboxConfig == null)
_coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (_coreConfig == null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
await GenLog(singboxConfig);
if (node.ConfigType == EConfigType.WireGuard)
{
singboxConfig.outbounds.RemoveAt(0);
var endpoints = new Endpoints4Sbox();
await GenEndpoint(node, endpoints);
endpoints.tag = Global.ProxyTag;
singboxConfig.endpoints = new() { endpoints };
}
else
{
await GenOutbound(node, singboxConfig.outbounds.First());
}
await GenMoreOutbounds(node, singboxConfig);
var item = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (item != null && item.Enabled == true)
{
await GenDnsDomainsCompatible(singboxConfig, item);
}
else
{
await GenDnsDomains(singboxConfig, _config.SimpleDNSItem);
}
singboxConfig.route.default_domain_resolver = new()
{
server = Global.SingboxLocalDNSTag,
};
GenLog();
GenOutbounds();
GenMinimizedDns();
singboxConfig.route.rules.Clear();
singboxConfig.inbounds.Clear();
singboxConfig.inbounds.Add(new()
_coreConfig.route.rules.Clear();
_coreConfig.inbounds.Clear();
_coreConfig.inbounds.Add(new()
{
tag = $"{EInboundProtocol.mixed}{port}",
listen = Global.Loopback,
@@ -319,202 +238,7 @@ public partial class CoreConfigSingboxService(Config config)
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
ret.Data = JsonUtils.Serialize(singboxConfig);
return ret;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
}
public async Task<RetResult> GenerateClientMultipleLoadConfig(ProfileItem parentNode)
{
var ret = new RetResult();
try
{
if (_config == null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
ret.Msg = ResUI.InitialConfiguration;
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
return ret;
}
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (singboxConfig == null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
singboxConfig.outbounds.RemoveAt(0);
await GenLog(singboxConfig);
await GenInbounds(singboxConfig);
var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
if (groupRet != 0)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
await GenRouting(singboxConfig);
await GenExperimental(singboxConfig);
await GenDns(parentNode, singboxConfig);
await ConvertGeo2Ruleset(singboxConfig);
ret.Success = true;
ret.Data = await ApplyFullConfigTemplate(singboxConfig);
return ret;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
}
public async Task<RetResult> GenerateClientChainConfig(ProfileItem parentNode)
{
var ret = new RetResult();
try
{
if (_config == null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
ret.Msg = ResUI.InitialConfiguration;
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
return ret;
}
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
if (singboxConfig == null)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
singboxConfig.outbounds.RemoveAt(0);
await GenLog(singboxConfig);
await GenInbounds(singboxConfig);
var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
if (groupRet != 0)
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
await GenRouting(singboxConfig);
await GenExperimental(singboxConfig);
await GenDns(parentNode, singboxConfig);
await ConvertGeo2Ruleset(singboxConfig);
ret.Success = true;
ret.Data = await ApplyFullConfigTemplate(singboxConfig);
return ret;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
}
public async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)
{
var ret = new RetResult();
if (node == null || fileName is null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
ret.Msg = ResUI.InitialConfiguration;
try
{
if (node == null)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
if (File.Exists(fileName))
{
File.Delete(fileName);
}
var addressFileName = node.Address;
if (addressFileName.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
return ret;
}
if (!File.Exists(addressFileName))
{
addressFileName = Path.Combine(Utils.GetConfigPath(), addressFileName);
}
if (!File.Exists(addressFileName))
{
ret.Msg = ResUI.FailedReadConfiguration + "1";
return ret;
}
if (node.Address == Global.CoreMultipleLoadConfigFileName)
{
var txtFile = File.ReadAllText(addressFileName);
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(txtFile);
if (singboxConfig == null)
{
File.Copy(addressFileName, fileName);
}
else
{
await GenInbounds(singboxConfig);
await GenExperimental(singboxConfig);
var content = JsonUtils.Serialize(singboxConfig, true);
await File.WriteAllTextAsync(fileName, content);
}
}
else
{
File.Copy(addressFileName, fileName);
}
//check again
if (!File.Exists(fileName))
{
ret.Msg = ResUI.FailedReadConfiguration + "2";
return ret;
}
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
ret.Data = JsonUtils.Serialize(_coreConfig);
return ret;
}
catch (Exception ex)
@@ -2,29 +2,29 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<string> ApplyFullConfigTemplate(SingboxConfig singboxConfig)
private string ApplyFullConfigTemplate()
{
var fullConfigTemplate = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
if (fullConfigTemplate == null || !fullConfigTemplate.Enabled)
var fullConfigTemplate = context.FullConfigTemplate;
if (fullConfigTemplate is not { Enabled: true })
{
return JsonUtils.Serialize(singboxConfig);
return JsonUtils.Serialize(_coreConfig);
}
var fullConfigTemplateItem = _config.TunModeItem.EnableTun ? fullConfigTemplate.TunConfig : fullConfigTemplate.Config;
var fullConfigTemplateItem = context.IsTunEnabled ? fullConfigTemplate.TunConfig : fullConfigTemplate.Config;
if (fullConfigTemplateItem.IsNullOrEmpty())
{
return JsonUtils.Serialize(singboxConfig);
return JsonUtils.Serialize(_coreConfig);
}
var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplateItem);
if (fullConfigTemplateNode == null)
{
return JsonUtils.Serialize(singboxConfig);
return JsonUtils.Serialize(_coreConfig);
}
// Process outbounds
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray();
foreach (var outbound in singboxConfig.outbounds)
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : [];
foreach (var outbound in _coreConfig.outbounds)
{
if (outbound.type.ToLower() is "direct" or "block")
{
@@ -42,10 +42,10 @@ public partial class CoreConfigSingboxService
fullConfigTemplateNode["outbounds"] = customOutboundsNode;
// Process endpoints
if (singboxConfig.endpoints != null && singboxConfig.endpoints.Count > 0)
if (_coreConfig.endpoints != null && _coreConfig.endpoints.Count > 0)
{
var customEndpointsNode = fullConfigTemplateNode["endpoints"] is JsonArray endpoints ? endpoints : new JsonArray();
foreach (var endpoint in singboxConfig.endpoints)
var customEndpointsNode = fullConfigTemplateNode["endpoints"] is JsonArray endpoints ? endpoints : [];
foreach (var endpoint in _coreConfig.endpoints)
{
if (endpoint.detour.IsNullOrEmpty() && !fullConfigTemplate.ProxyDetour.IsNullOrEmpty())
{
@@ -56,6 +56,6 @@ public partial class CoreConfigSingboxService
fullConfigTemplateNode["endpoints"] = customEndpointsNode;
}
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
return JsonUtils.Serialize(fullConfigTemplateNode);
}
}
@@ -2,25 +2,25 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
private void GenDns()
{
try
{
var item = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (item != null && item.Enabled == true)
var item = context.RawDnsItem;
if (item is { Enabled: true })
{
return await GenDnsCompatible(node, singboxConfig);
GenDnsCustom();
return;
}
var simpleDNSItem = _config.SimpleDNSItem;
await GenDnsServers(node, singboxConfig, simpleDNSItem);
await GenDnsRules(node, singboxConfig, simpleDNSItem);
GenDnsServers();
GenDnsRules();
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.independent_cache = true;
_coreConfig.dns ??= new Dns4Sbox();
_coreConfig.dns.independent_cache = true;
// final dns
var routing = await ConfigHandler.GetDefaultRouting(_config);
var routing = context.RoutingItem;
var useDirectDns = false;
if (routing != null)
{
@@ -32,35 +32,34 @@ public partial class CoreConfigSingboxService
lastRule.Network == "tcp,udp" ||
lastRule.Ip?.Contains("0.0.0.0/0") == true);
}
singboxConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;
if ((!useDirectDns) && simpleDNSItem.FakeIP == true && simpleDNSItem.GlobalFakeIp == false)
_coreConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;
var simpleDnsItem = context.SimpleDnsItem;
if ((!useDirectDns) && simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)
{
singboxConfig.dns.rules.Add(new()
_coreConfig.dns.rules.Add(new()
{
server = Global.SingboxFakeDNSTag,
query_type = new List<int> { 1, 28 }, // A and AAAA
rewrite_ttl = 1,
});
}
await GenOutboundDnsRule(node, singboxConfig);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return 0;
}
private async Task<int> GenDnsServers(ProfileItem? node, SingboxConfig singboxConfig, SimpleDNSItem simpleDNSItem)
private void GenDnsServers()
{
var finalDns = await GenDnsDomains(singboxConfig, simpleDNSItem);
var simpleDnsItem = context.SimpleDnsItem;
var finalDns = GenBootstrapDns();
var directDns = ParseDnsAddress(simpleDNSItem.DirectDNS);
var directDns = ParseDnsAddress(simpleDnsItem.DirectDNS ?? Global.DomainDirectDNSAddress.First());
directDns.tag = Global.SingboxDirectDNSTag;
directDns.domain_resolver = Global.SingboxLocalDNSTag;
var remoteDns = ParseDnsAddress(simpleDNSItem.RemoteDNS);
var remoteDns = ParseDnsAddress(simpleDnsItem.RemoteDNS ?? Global.DomainRemoteDNSAddress.First());
remoteDns.tag = Global.SingboxRemoteDNSTag;
remoteDns.detour = Global.ProxyTag;
remoteDns.domain_resolver = Global.SingboxLocalDNSTag;
@@ -71,12 +70,12 @@ public partial class CoreConfigSingboxService
type = "hosts",
predefined = new(),
};
if (simpleDNSItem.AddCommonHosts == true)
if (simpleDnsItem.AddCommonHosts == true)
{
hostsDns.predefined = Global.PredefinedHosts;
}
if (simpleDNSItem.UseSystemHosts == true)
if (simpleDnsItem.UseSystemHosts == true)
{
var systemHosts = Utils.GetSystemHosts();
if (systemHosts != null && systemHosts.Count > 0)
@@ -88,9 +87,9 @@ public partial class CoreConfigSingboxService
}
}
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
{
hostsDns.predefined[kvp.Key] = kvp.Value.Where(s => Utils.IsIpAddress(s)).ToList();
hostsDns.predefined[kvp.Key] = kvp.Value.Where(Utils.IsIpAddress).ToList();
}
foreach (var host in hostsDns.predefined)
@@ -109,14 +108,14 @@ public partial class CoreConfigSingboxService
}
}
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.servers ??= [];
singboxConfig.dns.servers.Add(remoteDns);
singboxConfig.dns.servers.Add(directDns);
singboxConfig.dns.servers.Add(hostsDns);
_coreConfig.dns ??= new Dns4Sbox();
_coreConfig.dns.servers ??= [];
_coreConfig.dns.servers.Add(remoteDns);
_coreConfig.dns.servers.Add(directDns);
_coreConfig.dns.servers.Add(hostsDns);
// fake ip
if (simpleDNSItem.FakeIP == true)
if (simpleDnsItem.FakeIP == true)
{
var fakeip = new Server4Sbox
{
@@ -125,68 +124,50 @@ public partial class CoreConfigSingboxService
inet4_range = "198.18.0.0/15",
inet6_range = "fc00::/18",
};
singboxConfig.dns.servers.Add(fakeip);
_coreConfig.dns.servers.Add(fakeip);
}
// ech
var (_, dnsServer) = ParseEchParam(node?.EchConfigList);
if (dnsServer is not null)
{
dnsServer.tag = Global.SingboxEchDNSTag;
if (dnsServer.server is not null
&& hostsDns.predefined.ContainsKey(dnsServer.server))
{
dnsServer.domain_resolver = Global.SingboxHostsDNSTag;
}
else
{
dnsServer.domain_resolver = Global.SingboxLocalDNSTag;
}
singboxConfig.dns.servers.Add(dnsServer);
}
else if (node?.ConfigType.IsGroupType() == true)
{
var echDnsObject = JsonUtils.DeepCopy(directDns);
echDnsObject.tag = Global.SingboxEchDNSTag;
singboxConfig.dns.servers.Add(echDnsObject);
}
return await Task.FromResult(0);
}
private async Task<Server4Sbox> GenDnsDomains(SingboxConfig singboxConfig, SimpleDNSItem? simpleDNSItem)
private Server4Sbox GenBootstrapDns()
{
var finalDns = ParseDnsAddress(simpleDNSItem.BootstrapDNS);
var finalDns = ParseDnsAddress(context.SimpleDnsItem?.BootstrapDNS ?? Global.DomainPureIPDNSAddress.First());
finalDns.tag = Global.SingboxLocalDNSTag;
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.servers ??= new List<Server4Sbox>();
singboxConfig.dns.servers.Add(finalDns);
return await Task.FromResult(finalDns);
_coreConfig.dns ??= new Dns4Sbox();
_coreConfig.dns.servers ??= [];
_coreConfig.dns.servers.Add(finalDns);
return finalDns;
}
private async Task<int> GenDnsRules(ProfileItem? node, SingboxConfig singboxConfig, SimpleDNSItem simpleDNSItem)
private void GenDnsRules()
{
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
var simpleDnsItem = context.SimpleDnsItem;
_coreConfig.dns ??= new Dns4Sbox();
_coreConfig.dns.rules ??= [];
singboxConfig.dns.rules.AddRange(new[]
_coreConfig.dns.rules.AddRange(new[]
{
new Rule4Sbox { ip_accept_any = true, server = Global.SingboxHostsDNSTag },
new Rule4Sbox
{
server = Global.SingboxDirectDNSTag,
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),
domain = context.ProtectDomainList.ToList(),
},
new Rule4Sbox
{
server = Global.SingboxRemoteDNSTag,
strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Proxy),
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy),
clash_mode = ERuleMode.Global.ToString()
},
new Rule4Sbox
{
server = Global.SingboxDirectDNSTag,
strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Freedom),
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),
clash_mode = ERuleMode.Direct.ToString()
}
});
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
{
var predefined = kvp.Value.First();
if (predefined.IsNullOrEmpty() || Utils.IsIpAddress(predefined))
@@ -197,7 +178,7 @@ public partial class CoreConfigSingboxService
{
// xray syntactic sugar for predefined
// etc. #0 -> NOERROR
singboxConfig.dns.rules.Add(new()
_coreConfig.dns.rules.Add(new()
{
query_type = [1, 28],
domain = [kvp.Key],
@@ -225,38 +206,13 @@ public partial class CoreConfigSingboxService
};
if (ParseV2Domain(kvp.Key, rule))
{
singboxConfig.dns.rules.Add(rule);
_coreConfig.dns.rules.Add(rule);
}
}
var (ech, _) = ParseEchParam(node?.EchConfigList);
if (ech is not null)
if (simpleDnsItem.BlockBindingQuery == true)
{
var echDomain = ech.query_server_name ?? node?.Sni;
singboxConfig.dns.rules.Add(new()
{
query_type = [64, 65],
server = Global.SingboxEchDNSTag,
domain = echDomain is not null ? new List<string> { echDomain } : null,
});
}
else if (node?.ConfigType.IsGroupType() == true)
{
var queryServerNames = (await GroupProfileManager.GetAllChildEchQuerySni(node)).ToList();
if (queryServerNames.Count > 0)
{
singboxConfig.dns.rules.Add(new()
{
query_type = [64, 65],
server = Global.SingboxEchDNSTag,
domain = queryServerNames,
});
}
}
if (simpleDNSItem.BlockBindingQuery == true)
{
singboxConfig.dns.rules.Add(new()
_coreConfig.dns.rules.Add(new()
{
query_type = [64, 65],
action = "predefined",
@@ -264,7 +220,7 @@ public partial class CoreConfigSingboxService
});
}
if (simpleDNSItem.FakeIP == true && simpleDNSItem.GlobalFakeIp == true)
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == true)
{
var fakeipFilterRule = JsonUtils.Deserialize<Rule4Sbox>(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName));
fakeipFilterRule.invert = true;
@@ -284,13 +240,13 @@ public partial class CoreConfigSingboxService
]
};
singboxConfig.dns.rules.Add(rule4Fake);
_coreConfig.dns.rules.Add(rule4Fake);
}
var routing = await ConfigHandler.GetDefaultRouting(_config);
var routing = context.RoutingItem;
if (routing == null)
{
return 0;
return;
}
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
@@ -298,9 +254,9 @@ public partial class CoreConfigSingboxService
var expectedIPsRegions = new List<string>();
var regionNames = new HashSet<string>();
if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs))
if (!string.IsNullOrEmpty(simpleDnsItem?.DirectExpectedIPs))
{
var ipItems = simpleDNSItem.DirectExpectedIPs
var ipItems = simpleDnsItem.DirectExpectedIPs
.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Trim())
.Where(s => !string.IsNullOrEmpty(s))
@@ -348,7 +304,7 @@ public partial class CoreConfigSingboxService
if (item.OutboundTag == Global.DirectTag)
{
rule.server = Global.SingboxDirectDNSTag;
rule.strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Freedom);
rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);
if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0)
{
@@ -373,31 +329,46 @@ public partial class CoreConfigSingboxService
}
else
{
if (simpleDNSItem.FakeIP == true && simpleDNSItem.GlobalFakeIp == false)
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)
{
var rule4Fake = JsonUtils.DeepCopy(rule);
rule4Fake.server = Global.SingboxFakeDNSTag;
rule4Fake.query_type = new List<int> { 1, 28 }; // A and AAAA
rule4Fake.rewrite_ttl = 1;
singboxConfig.dns.rules.Add(rule4Fake);
_coreConfig.dns.rules.Add(rule4Fake);
}
rule.server = Global.SingboxRemoteDNSTag;
rule.strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Proxy);
rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy);
}
singboxConfig.dns.rules.Add(rule);
_coreConfig.dns.rules.Add(rule);
}
return 0;
}
private async Task<int> GenDnsCompatible(ProfileItem? node, SingboxConfig singboxConfig)
private void GenMinimizedDns()
{
GenDnsServers();
foreach (var server in _coreConfig.dns!.servers.Where(s => !string.IsNullOrEmpty(s.detour)).ToList())
{
_coreConfig.dns.servers.Remove(server);
}
_coreConfig.dns ??= new();
_coreConfig.dns.rules ??= [];
_coreConfig.dns.rules.Clear();
_coreConfig.dns.final = Global.SingboxDirectDNSTag;
_coreConfig.route.default_domain_resolver = new()
{
server = Global.SingboxDirectDNSTag,
};
}
private void GenDnsCustom()
{
try
{
var item = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
var item = context.RawDnsItem;
var strDNS = string.Empty;
if (_config.TunModeItem.EnableTun)
if (context.IsTunEnabled)
{
strDNS = string.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;
}
@@ -409,61 +380,33 @@ public partial class CoreConfigSingboxService
var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);
if (dns4Sbox is null)
{
return 0;
return;
}
singboxConfig.dns = dns4Sbox;
if (dns4Sbox.servers != null && dns4Sbox.servers.Count > 0 && dns4Sbox.servers.First().address.IsNullOrEmpty())
_coreConfig.dns = dns4Sbox;
if (dns4Sbox.servers?.Count > 0 &&
dns4Sbox.servers.First().address.IsNullOrEmpty())
{
await GenDnsDomainsCompatible(singboxConfig, item);
GenDnsProtectCustom();
}
else
{
await GenDnsDomainsLegacyCompatible(singboxConfig, item);
GenDnsProtectCustomLegacy();
}
await GenOutboundDnsRule(node, singboxConfig);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return 0;
}
private async Task<int> GenDnsDomainsCompatible(SingboxConfig singboxConfig, DNSItem? dnsItem)
private void GenDnsProtectCustom()
{
var dns4Sbox = singboxConfig.dns ?? new();
var dnsItem = context.RawDnsItem;
var dns4Sbox = _coreConfig.dns ?? new();
dns4Sbox.servers ??= [];
dns4Sbox.rules ??= [];
var tag = Global.SingboxLocalDNSTag;
var finalDnsAddress = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress;
var localDnsServer = ParseDnsAddress(finalDnsAddress);
localDnsServer.tag = tag;
dns4Sbox.servers.Add(localDnsServer);
singboxConfig.dns = dns4Sbox;
return await Task.FromResult(0);
}
private async Task<int> GenDnsDomainsLegacyCompatible(SingboxConfig singboxConfig, DNSItem? dnsItem)
{
var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= [];
dns4Sbox.rules ??= [];
var tag = Global.SingboxLocalDNSTag;
dns4Sbox.servers.Add(new()
{
tag = tag,
address = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress,
detour = Global.DirectTag,
strategy = string.IsNullOrEmpty(dnsItem?.DomainStrategy4Freedom) ? null : dnsItem?.DomainStrategy4Freedom,
});
dns4Sbox.rules.Insert(0, new()
{
server = tag,
@@ -475,56 +418,41 @@ public partial class CoreConfigSingboxService
clash_mode = ERuleMode.Global.ToString()
});
var lstDomain = singboxConfig.outbounds
.Where(t => t.server.IsNotEmpty() && Utils.IsDomain(t.server))
.Select(t => t.server)
.Distinct()
.ToList();
if (lstDomain != null && lstDomain.Count > 0)
{
dns4Sbox.rules.Insert(0, new()
{
server = tag,
domain = lstDomain
});
}
var finalDnsAddress = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress;
singboxConfig.dns = dns4Sbox;
return await Task.FromResult(0);
var localDnsServer = ParseDnsAddress(finalDnsAddress);
localDnsServer.tag = tag;
dns4Sbox.servers.Add(localDnsServer);
dns4Sbox.rules.Insert(0, BuildProtectDomainRule());
_coreConfig.dns = dns4Sbox;
}
private async Task<int> GenOutboundDnsRule(ProfileItem? node, SingboxConfig singboxConfig)
private void GenDnsProtectCustomLegacy()
{
if (node == null)
{
return 0;
}
GenDnsProtectCustom();
List<string> domain = new();
if (Utils.IsDomain(node.Address)) // normal outbound
_coreConfig.dns?.servers?.RemoveAll(s => s.tag == Global.SingboxLocalDNSTag);
var dnsItem = context.RawDnsItem;
var localDnsServer = new Server4Sbox()
{
domain.Add(node.Address);
}
if (node.Address == Global.Loopback && node.SpiderX.IsNotEmpty()) // Tun2SocksAddress
{
domain.AddRange(Utils.String2List(node.SpiderX)
.Where(Utils.IsDomain)
.Distinct()
.ToList());
}
if (domain.Count == 0)
{
return 0;
}
address = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress)
? Global.DomainPureIPDNSAddress.FirstOrDefault()
: dnsItem?.DomainDNSAddress,
tag = Global.SingboxLocalDNSTag,
detour = Global.DirectTag,
};
_coreConfig.dns?.servers?.Add(localDnsServer);
}
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
singboxConfig.dns.rules.Insert(0, new Rule4Sbox
private Rule4Sbox BuildProtectDomainRule()
{
return new()
{
server = Global.SingboxLocalDNSTag,
domain = domain,
});
return await Task.FromResult(0);
domain = context.ProtectDomainList.ToList(),
};
}
private static Server4Sbox? ParseDnsAddress(string address)
@@ -2,12 +2,12 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> GenInbounds(SingboxConfig singboxConfig)
private void GenInbounds()
{
try
{
var listen = "0.0.0.0";
singboxConfig.inbounds = [];
_coreConfig.inbounds = [];
if (!_config.TunModeItem.EnableTun
|| (_config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && AppManager.Instance.RunningCoreType == ECoreType.sing_box))
@@ -18,23 +18,23 @@ public partial class CoreConfigSingboxService
tag = EInboundProtocol.socks.ToString(),
listen = Global.Loopback,
};
singboxConfig.inbounds.Add(inbound);
_coreConfig.inbounds.Add(inbound);
inbound.listen_port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
if (_config.Inbound.First().SecondLocalPortEnabled)
{
var inbound2 = GetInbound(inbound, EInboundProtocol.socks2, true);
singboxConfig.inbounds.Add(inbound2);
var inbound2 = BuildInbound(inbound, EInboundProtocol.socks2, true);
_coreConfig.inbounds.Add(inbound2);
}
if (_config.Inbound.First().AllowLANConn)
{
if (_config.Inbound.First().NewPort4LAN)
{
var inbound3 = GetInbound(inbound, EInboundProtocol.socks3, true);
var inbound3 = BuildInbound(inbound, EInboundProtocol.socks3, true);
inbound3.listen = listen;
singboxConfig.inbounds.Add(inbound3);
_coreConfig.inbounds.Add(inbound3);
//auth
if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty())
@@ -71,17 +71,16 @@ public partial class CoreConfigSingboxService
tunInbound.address = ["172.18.0.1/30"];
}
singboxConfig.inbounds.Add(tunInbound);
_coreConfig.inbounds.Add(tunInbound);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return await Task.FromResult(0);
}
private Inbound4Sbox GetInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks)
private Inbound4Sbox BuildInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks)
{
var inbound = JsonUtils.DeepCopy(inItem);
inbound.tag = protocol.ToString();
@@ -2,7 +2,7 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> GenLog(SingboxConfig singboxConfig)
private void GenLog()
{
try
{
@@ -11,11 +11,11 @@ public partial class CoreConfigSingboxService
case "debug":
case "info":
case "error":
singboxConfig.log.level = _config.CoreBasicItem.Loglevel;
_coreConfig.log.level = _config.CoreBasicItem.Loglevel;
break;
case "warning":
singboxConfig.log.level = "warn";
_coreConfig.log.level = "warn";
break;
default:
@@ -23,18 +23,17 @@ public partial class CoreConfigSingboxService
}
if (_config.CoreBasicItem.Loglevel == Global.None)
{
singboxConfig.log.disabled = true;
_coreConfig.log.disabled = true;
}
if (_config.CoreBasicItem.LogEnabled)
{
var dtNow = DateTime.Now;
singboxConfig.log.output = Utils.GetLogPath($"sbox_{dtNow:yyyy-MM-dd}.txt");
_coreConfig.log.output = Utils.GetLogPath($"sbox_{dtNow:yyyy-MM-dd}.txt");
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return await Task.FromResult(0);
}
}
File diff suppressed because it is too large Load Diff
@@ -2,23 +2,23 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> GenRouting(SingboxConfig singboxConfig)
private void GenRouting()
{
try
{
singboxConfig.route.final = Global.ProxyTag;
var simpleDnsItem = _config.SimpleDNSItem;
_coreConfig.route.final = Global.ProxyTag;
var simpleDnsItem = context.SimpleDnsItem;
var defaultDomainResolverTag = Global.SingboxDirectDNSTag;
var directDnsStrategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);
var rawDNSItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
var rawDNSItem = context.RawDnsItem;
if (rawDNSItem is { Enabled: true })
{
defaultDomainResolverTag = Global.SingboxLocalDNSTag;
directDnsStrategy = rawDNSItem.DomainStrategy4Freedom.IsNullOrEmpty() ? null : rawDNSItem.DomainStrategy4Freedom;
}
singboxConfig.route.default_domain_resolver = new()
_coreConfig.route.default_domain_resolver = new()
{
server = defaultDomainResolverTag,
strategy = directDnsStrategy
@@ -26,23 +26,23 @@ public partial class CoreConfigSingboxService
if (_config.TunModeItem.EnableTun)
{
singboxConfig.route.auto_detect_interface = true;
_coreConfig.route.auto_detect_interface = true;
var tunRules = JsonUtils.Deserialize<List<Rule4Sbox>>(EmbedUtils.GetEmbedText(Global.TunSingboxRulesFileName));
if (tunRules != null)
{
singboxConfig.route.rules.AddRange(tunRules);
_coreConfig.route.rules.AddRange(tunRules);
}
GenRoutingDirectExe(out var lstDnsExe, out var lstDirectExe);
singboxConfig.route.rules.Add(new()
var (lstDnsExe, lstDirectExe) = BuildRoutingDirectExe();
_coreConfig.route.rules.Add(new()
{
port = new() { 53 },
port = [53],
action = "hijack-dns",
process_name = lstDnsExe
});
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
outbound = Global.DirectTag,
process_name = lstDirectExe
@@ -51,66 +51,62 @@ public partial class CoreConfigSingboxService
if (_config.Inbound.First().SniffingEnabled)
{
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
action = "sniff"
});
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
protocol = new() { "dns" },
protocol = ["dns"],
action = "hijack-dns"
});
}
else
{
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
port = new() { 53 },
network = new() { "udp" },
port = [53],
network = ["udp"],
action = "hijack-dns"
});
}
var hostsDomains = new List<string>();
var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (dnsItem == null || !dnsItem.Enabled)
if (rawDNSItem is not { Enabled: true })
{
var userHostsMap = Utils.ParseHostsToDictionary(simpleDnsItem.Hosts);
hostsDomains.AddRange(userHostsMap.Select(kvp => kvp.Key));
if (simpleDnsItem.UseSystemHosts == true)
{
var systemHostsMap = Utils.GetSystemHosts();
foreach (var kvp in systemHostsMap)
{
hostsDomains.Add(kvp.Key);
}
hostsDomains.AddRange(systemHostsMap.Select(kvp => kvp.Key));
}
}
if (hostsDomains.Count > 0)
{
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
action = "resolve",
domain = hostsDomains,
});
}
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
outbound = Global.DirectTag,
clash_mode = ERuleMode.Direct.ToString()
});
singboxConfig.route.rules.Add(new()
_coreConfig.route.rules.Add(new()
{
outbound = Global.ProxyTag,
clash_mode = ERuleMode.Global.ToString()
});
var domainStrategy = _config.RoutingBasicItem.DomainStrategy4Singbox.NullIfEmpty();
var defaultRouting = await ConfigHandler.GetDefaultRouting(_config);
if (defaultRouting.DomainStrategy4Singbox.IsNotEmpty())
var routing = context.RoutingItem;
if (routing.DomainStrategy4Singbox.IsNotEmpty())
{
domainStrategy = defaultRouting.DomainStrategy4Singbox;
domainStrategy = routing.DomainStrategy4Singbox;
}
var resolveRule = new Rule4Sbox
{
@@ -119,10 +115,9 @@ public partial class CoreConfigSingboxService
};
if (_config.RoutingBasicItem.DomainStrategy == Global.IPOnDemand)
{
singboxConfig.route.rules.Add(resolveRule);
_coreConfig.route.rules.Add(resolveRule);
}
var routing = await ConfigHandler.GetDefaultRouting(_config);
var ipRules = new List<RulesItem>();
if (routing != null)
{
@@ -139,7 +134,7 @@ public partial class CoreConfigSingboxService
continue;
}
await GenRoutingUserRule(item1, singboxConfig);
GenRoutingUserRule(item1);
if (item1.Ip?.Count > 0)
{
@@ -149,10 +144,10 @@ public partial class CoreConfigSingboxService
}
if (_config.RoutingBasicItem.DomainStrategy == Global.IPIfNonMatch)
{
singboxConfig.route.rules.Add(resolveRule);
_coreConfig.route.rules.Add(resolveRule);
foreach (var item2 in ipRules)
{
await GenRoutingUserRule(item2, singboxConfig);
GenRoutingUserRule(item2);
}
}
}
@@ -160,10 +155,9 @@ public partial class CoreConfigSingboxService
{
Logging.SaveLog(_tag, ex);
}
return 0;
}
private void GenRoutingDirectExe(out List<string> lstDnsExe, out List<string> lstDirectExe)
private static (List<string> lstDnsExe, List<string> lstDirectExe) BuildRoutingDirectExe()
{
var dnsExeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var directExeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
@@ -187,20 +181,22 @@ public partial class CoreConfigSingboxService
}
}
lstDnsExe = new List<string>(dnsExeSet);
lstDirectExe = new List<string>(directExeSet);
var lstDnsExe = new List<string>(dnsExeSet);
var lstDirectExe = new List<string>(directExeSet);
return (lstDnsExe, lstDirectExe);
}
private async Task<int> GenRoutingUserRule(RulesItem item, SingboxConfig singboxConfig)
private void GenRoutingUserRule(RulesItem? item)
{
try
{
if (item == null)
{
return 0;
return;
}
item.OutboundTag = await GenRoutingUserRuleOutbound(item.OutboundTag, singboxConfig);
var rules = singboxConfig.route.rules;
item.OutboundTag = GenRoutingUserRuleOutbound(item.OutboundTag ?? Global.ProxyTag);
var rules = _coreConfig.route.rules;
var rule = new Rule4Sbox();
if (item.OutboundTag == "block")
@@ -326,10 +322,9 @@ public partial class CoreConfigSingboxService
{
Logging.SaveLog(_tag, ex);
}
return await Task.FromResult(0);
}
private bool ParseV2Domain(string domain, Rule4Sbox rule)
private static bool ParseV2Domain(string domain, Rule4Sbox rule)
{
if (domain.StartsWith('#') || domain.StartsWith("ext:") || domain.StartsWith("ext-domain:"))
{
@@ -368,7 +363,7 @@ public partial class CoreConfigSingboxService
return true;
}
private bool ParseV2Address(string address, Rule4Sbox rule)
private static bool ParseV2Address(string address, Rule4Sbox rule)
{
if (address.StartsWith("ext:") || address.StartsWith("ext-ip:"))
{
@@ -401,14 +396,14 @@ public partial class CoreConfigSingboxService
return true;
}
private async Task<string?> GenRoutingUserRuleOutbound(string outboundTag, SingboxConfig singboxConfig)
private string GenRoutingUserRuleOutbound(string outboundTag)
{
if (Global.OutboundTags.Contains(outboundTag))
{
return outboundTag;
}
var node = await AppManager.Instance.GetProfileItemViaRemarks(outboundTag);
var node = context.AllProxiesMap.GetValueOrDefault($"remark:{outboundTag}");
if (node == null
|| (!Global.SingboxSupportConfigType.Contains(node.ConfigType)
@@ -418,39 +413,15 @@ public partial class CoreConfigSingboxService
}
var tag = $"{node.IndexId}-{Global.ProxyTag}";
if (singboxConfig.outbounds.Any(o => o.tag == tag)
|| (singboxConfig.endpoints != null && singboxConfig.endpoints.Any(e => e.tag == tag)))
if (_coreConfig.outbounds.Any(o => o.tag.StartsWith(tag))
|| (_coreConfig.endpoints != null && _coreConfig.endpoints.Any(e => e.tag.StartsWith(tag))))
{
return tag;
}
if (node.ConfigType.IsGroupType())
{
var ret = await GenGroupOutbound(node, singboxConfig, tag);
if (ret == 0)
{
return tag;
}
return Global.ProxyTag;
}
var proxyOutbounds = new CoreConfigSingboxService(context with { Node = node, }).BuildAllProxyOutbounds(tag);
FillRangeProxy(proxyOutbounds, _coreConfig, false);
var server = await GenServer(node);
if (server is null)
{
return Global.ProxyTag;
}
server.tag = tag;
if (server is Endpoints4Sbox endpoint)
{
singboxConfig.endpoints ??= new();
singboxConfig.endpoints.Add(endpoint);
}
else if (server is Outbound4Sbox outbound)
{
singboxConfig.outbounds.Add(outbound);
}
return server.tag;
return tag;
}
}
@@ -2,7 +2,7 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> ConvertGeo2Ruleset(SingboxConfig singboxConfig)
private void ConvertGeo2Ruleset()
{
static void AddRuleSets(List<string> ruleSets, List<string>? rule_set)
{
@@ -16,14 +16,14 @@ public partial class CoreConfigSingboxService
var ruleSets = new List<string>();
//convert route geosite & geoip to ruleset
foreach (var rule in singboxConfig.route.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])
foreach (var rule in _coreConfig.route.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])
{
rule.rule_set ??= new List<string>();
rule.rule_set.AddRange(rule?.geosite?.Select(t => $"{geosite}-{t}").ToList());
rule.geosite = null;
AddRuleSets(ruleSets, rule.rule_set);
}
foreach (var rule in singboxConfig.route.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])
foreach (var rule in _coreConfig.route.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])
{
rule.rule_set ??= new List<string>();
rule.rule_set.AddRange(rule?.geoip?.Select(t => $"{geoip}-{t}").ToList());
@@ -32,24 +32,24 @@ public partial class CoreConfigSingboxService
}
//convert dns geosite & geoip to ruleset
foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])
foreach (var rule in _coreConfig.dns?.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])
{
rule.rule_set ??= new List<string>();
rule.rule_set.AddRange(rule?.geosite?.Select(t => $"{geosite}-{t}").ToList());
rule.geosite = null;
}
foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])
foreach (var rule in _coreConfig.dns?.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])
{
rule.rule_set ??= new List<string>();
rule.rule_set.AddRange(rule?.geoip?.Select(t => $"{geoip}-{t}").ToList());
rule.geoip = null;
}
foreach (var dnsRule in singboxConfig.dns?.rules.Where(t => t.rule_set?.Count > 0).ToList() ?? [])
foreach (var dnsRule in _coreConfig.dns?.rules.Where(t => t.rule_set?.Count > 0).ToList() ?? [])
{
AddRuleSets(ruleSets, dnsRule.rule_set);
}
//rules in rules
foreach (var item in singboxConfig.dns?.rules.Where(t => t.rules?.Count > 0).Select(t => t.rules).ToList() ?? [])
foreach (var item in _coreConfig.dns?.rules.Where(t => t.rules?.Count > 0).Select(t => t.rules).ToList() ?? [])
{
foreach (var item2 in item ?? [])
{
@@ -60,7 +60,7 @@ public partial class CoreConfigSingboxService
//load custom ruleset file
List<Ruleset4Sbox> customRulesets = [];
var routing = await ConfigHandler.GetDefaultRouting(_config);
var routing = context.RoutingItem;
if (routing.CustomRulesetPath4Singbox.IsNotEmpty())
{
var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox);
@@ -78,7 +78,7 @@ public partial class CoreConfigSingboxService
var localSrss = Utils.GetBinPath("srss");
//Add ruleset srs
singboxConfig.route.rule_set = [];
_coreConfig.route.rule_set = [];
foreach (var item in new HashSet<string>(ruleSets))
{
if (item.IsNullOrEmpty())
@@ -113,9 +113,7 @@ public partial class CoreConfigSingboxService
};
}
}
singboxConfig.route.rule_set.Add(customRuleset);
_coreConfig.route.rule_set.Add(customRuleset);
}
return 0;
}
}
@@ -2,12 +2,12 @@ namespace ServiceLib.Services.CoreConfig;
public partial class CoreConfigSingboxService
{
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
private void GenExperimental()
{
//if (_config.guiItem.enableStatistics)
{
singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.clash_api = new Clash_Api4Sbox()
_coreConfig.experimental ??= new Experimental4Sbox();
_coreConfig.experimental.clash_api = new Clash_Api4Sbox()
{
external_controller = $"{Global.Loopback}:{AppManager.Instance.StatePort2}",
};
@@ -15,15 +15,13 @@ public partial class CoreConfigSingboxService
if (_config.CoreBasicItem.EnableCacheFile4Sbox)
{
singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
_coreConfig.experimental ??= new Experimental4Sbox();
_coreConfig.experimental.cache_file = new CacheFile4Sbox()
{
enabled = true,
path = Utils.GetBinPath("cache.db"),
store_fakeip = _config.SimpleDNSItem.FakeIP == true
store_fakeip = context.SimpleDnsItem.FakeIP == true
};
}
return await Task.FromResult(0);
}
}