2025-08-17 12:09:41 +00:00
|
|
|
namespace ServiceLib.Services.CoreConfig;
|
|
|
|
|
|
|
|
|
|
public partial class CoreConfigSingboxService
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenDns()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var item = context.RawDnsItem;
|
|
|
|
|
if (item is { Enabled: true })
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
GenDnsCustom();
|
|
|
|
|
return;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
GenDnsServers();
|
|
|
|
|
GenDnsRules();
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns ??= new Dns4Sbox();
|
|
|
|
|
_coreConfig.dns.independent_cache = true;
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2025-08-19 01:10:54 +00:00
|
|
|
// final dns
|
2026-02-06 04:55:55 +00:00
|
|
|
var routing = context.RoutingItem;
|
2025-08-17 12:09:41 +00:00
|
|
|
var useDirectDns = false;
|
|
|
|
|
if (routing != null)
|
|
|
|
|
{
|
|
|
|
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
|
|
|
|
|
|
|
|
|
|
useDirectDns = rules?.LastOrDefault() is { } lastRule &&
|
|
|
|
|
lastRule.OutboundTag == Global.DirectTag &&
|
|
|
|
|
(lastRule.Port == "0-65535" ||
|
|
|
|
|
lastRule.Network == "tcp,udp" ||
|
|
|
|
|
lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
|
|
|
|
}
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;
|
|
|
|
|
var simpleDnsItem = context.SimpleDnsItem;
|
|
|
|
|
if ((!useDirectDns) && simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)
|
2025-09-13 06:55:30 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(new()
|
2025-09-13 06:55:30 +00:00
|
|
|
{
|
|
|
|
|
server = Global.SingboxFakeDNSTag,
|
|
|
|
|
query_type = new List<int> { 1, 28 }, // A and AAAA
|
|
|
|
|
rewrite_ttl = 1,
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logging.SaveLog(_tag, ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenDnsServers()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var simpleDnsItem = context.SimpleDnsItem;
|
|
|
|
|
var finalDns = GenBootstrapDns();
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
var directDns = ParseDnsAddress(simpleDnsItem.DirectDNS ?? Global.DomainDirectDNSAddress.First());
|
2025-08-17 12:09:41 +00:00
|
|
|
directDns.tag = Global.SingboxDirectDNSTag;
|
2025-10-11 11:22:26 +00:00
|
|
|
directDns.domain_resolver = Global.SingboxLocalDNSTag;
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
var remoteDns = ParseDnsAddress(simpleDnsItem.RemoteDNS ?? Global.DomainRemoteDNSAddress.First());
|
2025-08-17 12:09:41 +00:00
|
|
|
remoteDns.tag = Global.SingboxRemoteDNSTag;
|
|
|
|
|
remoteDns.detour = Global.ProxyTag;
|
2025-10-11 11:22:26 +00:00
|
|
|
remoteDns.domain_resolver = Global.SingboxLocalDNSTag;
|
2025-08-17 12:09:41 +00:00
|
|
|
|
|
|
|
|
var hostsDns = new Server4Sbox
|
|
|
|
|
{
|
|
|
|
|
tag = Global.SingboxHostsDNSTag,
|
|
|
|
|
type = "hosts",
|
|
|
|
|
predefined = new(),
|
|
|
|
|
};
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.AddCommonHosts == true)
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
hostsDns.predefined = Global.PredefinedHosts;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.UseSystemHosts == true)
|
2025-08-26 09:34:12 +00:00
|
|
|
{
|
|
|
|
|
var systemHosts = Utils.GetSystemHosts();
|
|
|
|
|
if (systemHosts != null && systemHosts.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var host in systemHosts)
|
|
|
|
|
{
|
|
|
|
|
hostsDns.predefined.TryAdd(host.Key, new List<string> { host.Value });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
hostsDns.predefined[kvp.Key] = kvp.Value.Where(Utils.IsIpAddress).ToList();
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var host in hostsDns.predefined)
|
|
|
|
|
{
|
|
|
|
|
if (finalDns.server == host.Key)
|
|
|
|
|
{
|
|
|
|
|
finalDns.domain_resolver = Global.SingboxHostsDNSTag;
|
|
|
|
|
}
|
|
|
|
|
if (remoteDns.server == host.Key)
|
|
|
|
|
{
|
|
|
|
|
remoteDns.domain_resolver = Global.SingboxHostsDNSTag;
|
|
|
|
|
}
|
|
|
|
|
if (directDns.server == host.Key)
|
|
|
|
|
{
|
|
|
|
|
directDns.domain_resolver = Global.SingboxHostsDNSTag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns ??= new Dns4Sbox();
|
|
|
|
|
_coreConfig.dns.servers ??= [];
|
|
|
|
|
_coreConfig.dns.servers.Add(remoteDns);
|
|
|
|
|
_coreConfig.dns.servers.Add(directDns);
|
|
|
|
|
_coreConfig.dns.servers.Add(hostsDns);
|
2025-08-17 12:09:41 +00:00
|
|
|
|
|
|
|
|
// fake ip
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.FakeIP == true)
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
var fakeip = new Server4Sbox
|
|
|
|
|
{
|
|
|
|
|
tag = Global.SingboxFakeDNSTag,
|
|
|
|
|
type = "fakeip",
|
|
|
|
|
inet4_range = "198.18.0.0/15",
|
|
|
|
|
inet6_range = "fc00::/18",
|
|
|
|
|
};
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.servers.Add(fakeip);
|
2026-01-08 05:56:45 +00:00
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private Server4Sbox GenBootstrapDns()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var finalDns = ParseDnsAddress(context.SimpleDnsItem?.BootstrapDNS ?? Global.DomainPureIPDNSAddress.First());
|
2025-10-11 11:22:26 +00:00
|
|
|
finalDns.tag = Global.SingboxLocalDNSTag;
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns ??= new Dns4Sbox();
|
|
|
|
|
_coreConfig.dns.servers ??= [];
|
|
|
|
|
_coreConfig.dns.servers.Add(finalDns);
|
|
|
|
|
return finalDns;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenDnsRules()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var simpleDnsItem = context.SimpleDnsItem;
|
|
|
|
|
_coreConfig.dns ??= new Dns4Sbox();
|
|
|
|
|
_coreConfig.dns.rules ??= [];
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.AddRange(new[]
|
2026-02-04 06:35:26 +00:00
|
|
|
{
|
2025-08-17 12:09:41 +00:00
|
|
|
new Rule4Sbox { ip_accept_any = true, server = Global.SingboxHostsDNSTag },
|
|
|
|
|
new Rule4Sbox
|
2026-02-06 04:55:55 +00:00
|
|
|
{
|
|
|
|
|
server = Global.SingboxDirectDNSTag,
|
|
|
|
|
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),
|
|
|
|
|
domain = context.ProtectDomainList.ToList(),
|
|
|
|
|
},
|
|
|
|
|
new Rule4Sbox
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
server = Global.SingboxRemoteDNSTag,
|
2026-02-06 04:55:55 +00:00
|
|
|
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy),
|
2025-08-17 12:09:41 +00:00
|
|
|
clash_mode = ERuleMode.Global.ToString()
|
|
|
|
|
},
|
|
|
|
|
new Rule4Sbox
|
|
|
|
|
{
|
|
|
|
|
server = Global.SingboxDirectDNSTag,
|
2026-02-06 04:55:55 +00:00
|
|
|
strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),
|
2025-08-17 12:09:41 +00:00
|
|
|
clash_mode = ERuleMode.Direct.ToString()
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
2026-02-05 09:05:27 +00:00
|
|
|
{
|
|
|
|
|
var predefined = kvp.Value.First();
|
|
|
|
|
if (predefined.IsNullOrEmpty() || Utils.IsIpAddress(predefined))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (predefined.StartsWith('#') && int.TryParse(predefined.AsSpan(1), out var rcode))
|
|
|
|
|
{
|
|
|
|
|
// xray syntactic sugar for predefined
|
|
|
|
|
// etc. #0 -> NOERROR
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(new()
|
2026-02-05 09:05:27 +00:00
|
|
|
{
|
|
|
|
|
query_type = [1, 28],
|
|
|
|
|
domain = [kvp.Key],
|
|
|
|
|
action = "predefined",
|
|
|
|
|
rcode = rcode switch
|
|
|
|
|
{
|
|
|
|
|
0 => "NOERROR",
|
|
|
|
|
1 => "FORMERR",
|
|
|
|
|
2 => "SERVFAIL",
|
|
|
|
|
3 => "NXDOMAIN",
|
|
|
|
|
4 => "NOTIMP",
|
|
|
|
|
5 => "REFUSED",
|
|
|
|
|
_ => "NOERROR",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// CNAME record
|
|
|
|
|
Rule4Sbox rule = new()
|
|
|
|
|
{
|
|
|
|
|
query_type = [1, 28],
|
|
|
|
|
action = "predefined",
|
|
|
|
|
rcode = "NOERROR",
|
|
|
|
|
answer = [$"*. IN CNAME {predefined}."],
|
|
|
|
|
};
|
|
|
|
|
if (ParseV2Domain(kvp.Key, rule))
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(rule);
|
2026-02-05 09:05:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.BlockBindingQuery == true)
|
2026-01-08 05:56:45 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(new()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-05 09:05:27 +00:00
|
|
|
query_type = [64, 65],
|
2025-08-17 12:09:41 +00:00
|
|
|
action = "predefined",
|
2026-02-05 09:05:27 +00:00
|
|
|
rcode = "NOERROR"
|
2025-08-17 12:09:41 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == true)
|
2025-09-13 06:55:30 +00:00
|
|
|
{
|
|
|
|
|
var fakeipFilterRule = JsonUtils.Deserialize<Rule4Sbox>(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName));
|
|
|
|
|
fakeipFilterRule.invert = true;
|
|
|
|
|
var rule4Fake = new Rule4Sbox
|
|
|
|
|
{
|
|
|
|
|
server = Global.SingboxFakeDNSTag,
|
|
|
|
|
type = "logical",
|
|
|
|
|
mode = "and",
|
|
|
|
|
rewrite_ttl = 1,
|
2026-02-05 09:05:27 +00:00
|
|
|
rules =
|
|
|
|
|
[
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
query_type = [1, 28], // A and AAAA
|
2025-09-13 06:55:30 +00:00
|
|
|
},
|
2026-02-05 09:05:27 +00:00
|
|
|
fakeipFilterRule
|
|
|
|
|
]
|
2025-09-13 06:55:30 +00:00
|
|
|
};
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(rule4Fake);
|
2025-09-13 06:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
var routing = context.RoutingItem;
|
2025-08-17 12:09:41 +00:00
|
|
|
if (routing == null)
|
2025-11-02 07:25:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
return;
|
2025-11-02 07:25:41 +00:00
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
|
|
|
|
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
|
|
|
|
|
var expectedIPCidr = new List<string>();
|
|
|
|
|
var expectedIPsRegions = new List<string>();
|
|
|
|
|
var regionNames = new HashSet<string>();
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
if (!string.IsNullOrEmpty(simpleDnsItem?.DirectExpectedIPs))
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var ipItems = simpleDnsItem.DirectExpectedIPs
|
2026-02-07 11:31:35 +00:00
|
|
|
.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
|
2025-08-17 12:09:41 +00:00
|
|
|
.Select(s => s.Trim())
|
|
|
|
|
.Where(s => !string.IsNullOrEmpty(s))
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
foreach (var ip in ipItems)
|
|
|
|
|
{
|
|
|
|
|
if (ip.StartsWith("geoip:", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
var region = ip["geoip:".Length..];
|
|
|
|
|
if (!string.IsNullOrEmpty(region))
|
|
|
|
|
{
|
|
|
|
|
expectedIPsRegions.Add(region);
|
|
|
|
|
regionNames.Add(region);
|
|
|
|
|
regionNames.Add($"geolocation-{region}");
|
|
|
|
|
regionNames.Add($"tld-{region}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
expectedIPCidr.Add(ip);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var item in rules)
|
|
|
|
|
{
|
|
|
|
|
if (!item.Enabled || item.Domain is null || item.Domain.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 02:40:26 +00:00
|
|
|
if (item.RuleType == ERuleType.Routing)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-17 12:09:41 +00:00
|
|
|
var rule = new Rule4Sbox();
|
|
|
|
|
var validDomains = item.Domain.Count(it => ParseV2Domain(it, rule));
|
|
|
|
|
if (validDomains <= 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.OutboundTag == Global.DirectTag)
|
|
|
|
|
{
|
|
|
|
|
rule.server = Global.SingboxDirectDNSTag;
|
2026-02-06 04:55:55 +00:00
|
|
|
rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);
|
2025-08-17 12:09:41 +00:00
|
|
|
|
|
|
|
|
if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var geositeSet = new HashSet<string>(rule.geosite);
|
|
|
|
|
if (regionNames.Intersect(geositeSet).Any())
|
|
|
|
|
{
|
|
|
|
|
if (expectedIPsRegions.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
rule.geoip = expectedIPsRegions;
|
|
|
|
|
}
|
|
|
|
|
if (expectedIPCidr.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
rule.ip_cidr = expectedIPCidr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (item.OutboundTag == Global.BlockTag)
|
|
|
|
|
{
|
|
|
|
|
rule.action = "predefined";
|
|
|
|
|
rule.rcode = "NXDOMAIN";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
var rule4Fake = JsonUtils.DeepCopy(rule);
|
|
|
|
|
rule4Fake.server = Global.SingboxFakeDNSTag;
|
2025-09-13 06:55:30 +00:00
|
|
|
rule4Fake.query_type = new List<int> { 1, 28 }; // A and AAAA
|
|
|
|
|
rule4Fake.rewrite_ttl = 1;
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(rule4Fake);
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
rule.server = Global.SingboxRemoteDNSTag;
|
2026-02-06 04:55:55 +00:00
|
|
|
rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy);
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Add(rule);
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
2026-02-06 04:55:55 +00:00
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenMinimizedDns()
|
|
|
|
|
{
|
|
|
|
|
GenDnsServers();
|
2026-02-08 06:26:39 +00:00
|
|
|
foreach (var server in _coreConfig.dns!.servers.Where(s => !string.IsNullOrEmpty(s.detour)).ToList())
|
|
|
|
|
{
|
|
|
|
|
_coreConfig.dns.servers.Remove(server);
|
|
|
|
|
}
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns ??= new();
|
2026-02-06 07:24:14 +00:00
|
|
|
_coreConfig.dns.rules ??= [];
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns.rules.Clear();
|
|
|
|
|
_coreConfig.dns.final = Global.SingboxDirectDNSTag;
|
|
|
|
|
_coreConfig.route.default_domain_resolver = new()
|
|
|
|
|
{
|
|
|
|
|
server = Global.SingboxDirectDNSTag,
|
|
|
|
|
};
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenDnsCustom()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var item = context.RawDnsItem;
|
2025-08-17 12:09:41 +00:00
|
|
|
var strDNS = string.Empty;
|
2026-02-06 04:55:55 +00:00
|
|
|
if (context.IsTunEnabled)
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
strDNS = string.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strDNS = string.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);
|
|
|
|
|
if (dns4Sbox is null)
|
|
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
return;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns = dns4Sbox;
|
2026-02-06 07:20:18 +00:00
|
|
|
if (dns4Sbox.servers?.Count > 0 &&
|
|
|
|
|
dns4Sbox.servers.First().address.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
GenDnsProtectCustom();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GenDnsProtectCustomLegacy();
|
|
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logging.SaveLog(_tag, ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private void GenDnsProtectCustom()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
var dnsItem = context.RawDnsItem;
|
|
|
|
|
var dns4Sbox = _coreConfig.dns ?? new();
|
2025-08-17 12:09:41 +00:00
|
|
|
dns4Sbox.servers ??= [];
|
|
|
|
|
dns4Sbox.rules ??= [];
|
|
|
|
|
|
2025-10-11 11:22:26 +00:00
|
|
|
var tag = Global.SingboxLocalDNSTag;
|
2026-02-06 07:20:18 +00:00
|
|
|
dns4Sbox.rules.Insert(0, new()
|
|
|
|
|
{
|
|
|
|
|
server = tag,
|
|
|
|
|
clash_mode = ERuleMode.Direct.ToString()
|
|
|
|
|
});
|
|
|
|
|
dns4Sbox.rules.Insert(0, new()
|
|
|
|
|
{
|
|
|
|
|
server = dns4Sbox.servers.Where(t => t.detour == Global.ProxyTag).Select(t => t.tag).FirstOrDefault() ?? "remote",
|
|
|
|
|
clash_mode = ERuleMode.Global.ToString()
|
|
|
|
|
});
|
2025-10-11 11:22:26 +00:00
|
|
|
|
|
|
|
|
var finalDnsAddress = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress;
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2025-10-11 11:22:26 +00:00
|
|
|
var localDnsServer = ParseDnsAddress(finalDnsAddress);
|
2025-08-17 12:09:41 +00:00
|
|
|
localDnsServer.tag = tag;
|
|
|
|
|
|
|
|
|
|
dns4Sbox.servers.Add(localDnsServer);
|
2026-02-06 04:55:55 +00:00
|
|
|
dns4Sbox.rules.Insert(0, BuildProtectDomainRule());
|
2025-08-17 12:09:41 +00:00
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
_coreConfig.dns = dns4Sbox;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 07:20:18 +00:00
|
|
|
private void GenDnsProtectCustomLegacy()
|
|
|
|
|
{
|
|
|
|
|
GenDnsProtectCustom();
|
|
|
|
|
|
|
|
|
|
var localDnsServer = _coreConfig.dns?.servers?.FirstOrDefault(s => s.tag == Global.SingboxLocalDNSTag);
|
|
|
|
|
if (localDnsServer == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
localDnsServer.type = null;
|
|
|
|
|
localDnsServer.server = null;
|
|
|
|
|
var dnsItem = context.RawDnsItem;
|
|
|
|
|
localDnsServer.address = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 04:55:55 +00:00
|
|
|
private Rule4Sbox BuildProtectDomainRule()
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2026-02-06 04:55:55 +00:00
|
|
|
return new()
|
2025-09-21 04:05:06 +00:00
|
|
|
{
|
2025-10-11 11:22:26 +00:00
|
|
|
server = Global.SingboxLocalDNSTag,
|
2026-02-06 04:55:55 +00:00
|
|
|
domain = context.ProtectDomainList.ToList(),
|
|
|
|
|
};
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Server4Sbox? ParseDnsAddress(string address)
|
|
|
|
|
{
|
|
|
|
|
var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(addressFirst))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var server = new Server4Sbox();
|
|
|
|
|
|
|
|
|
|
if (addressFirst is "local" or "localhost")
|
|
|
|
|
{
|
|
|
|
|
server.type = "local";
|
|
|
|
|
return server;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-21 09:28:48 +00:00
|
|
|
var (domain, scheme, port, path) = Utils.ParseUrl(addressFirst);
|
|
|
|
|
|
|
|
|
|
if (scheme.Equals("dhcp", StringComparison.OrdinalIgnoreCase))
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
server.type = "dhcp";
|
2025-10-21 09:28:48 +00:00
|
|
|
if ((!domain.IsNullOrEmpty()) && domain != "auto")
|
|
|
|
|
{
|
|
|
|
|
server.server = domain;
|
|
|
|
|
}
|
2025-08-17 12:09:41 +00:00
|
|
|
return server;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-21 09:28:48 +00:00
|
|
|
if (scheme.IsNullOrEmpty())
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
|
|
|
|
// udp dns
|
|
|
|
|
server.type = "udp";
|
2025-10-22 01:07:53 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// server.type = scheme.ToLower();
|
|
|
|
|
|
|
|
|
|
// remove "+local" suffix
|
|
|
|
|
// TODO: "+local" suffix decide server.detour = "direct" ?
|
|
|
|
|
server.type = scheme.Replace("+local", "", StringComparison.OrdinalIgnoreCase).ToLower();
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-21 09:28:48 +00:00
|
|
|
server.server = domain;
|
|
|
|
|
if (port != 0)
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2025-10-21 09:28:48 +00:00
|
|
|
server.server_port = port;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
2025-10-21 09:28:48 +00:00
|
|
|
if ((server.type == "https" || server.type == "h3") && !string.IsNullOrEmpty(path) && path != "/")
|
2025-08-17 12:09:41 +00:00
|
|
|
{
|
2025-10-21 09:28:48 +00:00
|
|
|
server.path = path;
|
2025-08-17 12:09:41 +00:00
|
|
|
}
|
|
|
|
|
return server;
|
|
|
|
|
}
|
|
|
|
|
}
|