Simplify DNS Settings

DHR60 2025-07-10 21:42:53 +08:00
parent 2b32f37057
commit dff67e9d78
23 changed files with 1532 additions and 812 deletions

View File

@ -349,25 +349,42 @@ public class Global
public static readonly List<string> SingboxDomainStrategy4Out =
[
"",
"ipv4_only",
"prefer_ipv4",
"prefer_ipv6",
"ipv6_only",
""
"ipv6_only"
];
public static readonly List<string> DomainDNSAddress =
public static readonly List<string> DomainDirectDNSAddress =
[
"https://dns.alidns.com/dns-query",
"https://doh.pub/dns-query",
"223.5.5.5",
"223.6.6.6",
"119.29.29.29",
"localhost"
];
public static readonly List<string> SingboxDomainDNSAddress =
public static readonly List<string> DomainRemoteDNSAddress =
[
"https://cloudflare-dns.com/dns-query",
"https://dns.cloudflare.com/dns-query",
"https://dns.google/dns-query",
"https://doh.dns.sb/dns-query",
"https://doh.opendns.com/dns-query",
"https://common.dot.dns.yandex.net",
"8.8.8.8",
"1.1.1.1",
"185.222.222.222",
"208.67.222.222",
"77.88.8.8"
];
public static readonly List<string> DomainPureIPDNSAddress =
[
"223.5.5.5",
"223.6.6.6",
"dhcp://auto"
"119.29.29.29",
"localhost"
];
public static readonly List<string> Languages =
@ -537,5 +554,22 @@ public class Global
BlockTag
];
public static readonly Dictionary<string, List<string>> PredefinedHosts = new()
{
{ "dns.google", new List<string> { "8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844" } },
{ "dns.alidns.com", new List<string> { "223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1" } },
{ "one.one.one.one", new List<string> { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } },
{ "1dot1dot1dot1.cloudflare-dns.com", new List<string> { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } },
{ "cloudflare-dns.com", new List<string> { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } },
{ "dns.cloudflare.com", new List<string> { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } },
{ "dot.pub", new List<string> { "1.12.12.12", "120.53.53.53" } },
{ "dns.quad9.net", new List<string> { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } },
{ "dns.yandex.net", new List<string> { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } },
{ "dns.sb", new List<string> { "185.222.222.222", "2a09::" } },
{ "dns.umbrella.com", new List<string> { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } },
{ "dns.sse.cisco.com", new List<string> { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } },
{ "engage.cloudflareclient.com", new List<string> { "162.159.192.1", "2606:4700:d0::a29f:c001" } }
};
#endregion const
}

View File

@ -193,16 +193,6 @@ public sealed class AppHandler
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Id == id);
}
public async Task<List<DNSItem>?> DNSItems()
{
return await SQLiteHelper.Instance.TableAsync<DNSItem>().ToListAsync();
}
public async Task<DNSItem?> GetDNSItem(ECoreType eCoreType)
{
return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
}
#endregion SqliteHelper
#region Core Type

View File

@ -112,6 +112,18 @@ public class ConfigHandler
config.ConstItem ??= new ConstItem();
config.DNSItem ??= new DNSItem()
{
UseSystemHosts = false,
AddCommonHosts = true,
FakeIP = false,
BlockBindingQuery = true,
DirectDNS = Global.DomainDirectDNSAddress.FirstOrDefault(),
RemoteDNS = Global.DomainRemoteDNSAddress.FirstOrDefault(),
SingboxOutboundsResolveDNS = Global.DomainDirectDNSAddress.FirstOrDefault(),
SingboxFinalResolveDNS = Global.DomainPureIPDNSAddress.FirstOrDefault()
};
config.SpeedTestItem ??= new();
if (config.SpeedTestItem.SpeedTestTimeout < 10)
{
@ -2088,101 +2100,6 @@ public class ConfigHandler
#endregion Routing
#region DNS
/// <summary>
/// Initialize built-in DNS configurations
/// Creates default DNS items for V2Ray and sing-box
/// </summary>
/// <param name="config">Current configuration</param>
/// <returns>0 if successful</returns>
public static async Task<int> InitBuiltinDNS(Config config)
{
var items = await AppHandler.Instance.DNSItems();
if (items.Count <= 0)
{
var item = new DNSItem()
{
Remarks = "V2ray",
CoreType = ECoreType.Xray,
};
await SaveDNSItems(config, item);
var item2 = new DNSItem()
{
Remarks = "sing-box",
CoreType = ECoreType.sing_box,
};
await SaveDNSItems(config, item2);
}
return 0;
}
/// <summary>
/// Save a DNS item to the database
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="item">DNS item to save</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SaveDNSItems(Config config, DNSItem item)
{
if (item == null)
{
return -1;
}
if (item.Id.IsNullOrEmpty())
{
item.Id = Utils.GetGuid(false);
}
if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)
{
return 0;
}
else
{
return -1;
}
}
/// <summary>
/// Get an external DNS configuration from URL
/// Downloads and processes DNS templates
/// </summary>
/// <param name="type">Core type (Xray or sing-box)</param>
/// <param name="url">URL of the DNS template</param>
/// <returns>DNS item with configuration from the URL</returns>
public static async Task<DNSItem> GetExternalDNSItem(ECoreType type, string url)
{
var currentItem = await AppHandler.Instance.GetDNSItem(type);
var downloadHandle = new DownloadService();
var templateContent = await downloadHandle.TryDownloadString(url, true, "");
if (templateContent.IsNullOrEmpty())
return currentItem;
var template = JsonUtils.Deserialize<DNSItem>(templateContent);
if (template == null)
return currentItem;
if (!template.NormalDNS.IsNullOrEmpty())
template.NormalDNS = await downloadHandle.TryDownloadString(template.NormalDNS, true, "");
if (!template.TunDNS.IsNullOrEmpty())
template.TunDNS = await downloadHandle.TryDownloadString(template.TunDNS, true, "");
template.Id = currentItem.Id;
template.Enabled = currentItem.Enabled;
template.Remarks = currentItem.Remarks;
template.CoreType = type;
return template;
}
#endregion DNS
#region Regional Presets
/// <summary>
@ -2202,7 +2119,6 @@ public class ConfigHandler
config.ConstItem.RouteRulesTemplateSourceUrl = "";
await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>();
await InitBuiltinDNS(config);
return true;
@ -2211,8 +2127,8 @@ public class ConfigHandler
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[1];
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[1];
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
//await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
//await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
return true;
@ -2221,8 +2137,8 @@ public class ConfigHandler
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
//await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
//await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
return true;
}

View File

@ -48,6 +48,7 @@ public class Config
public List<InItem> Inbound { get; set; }
public List<KeyEventItem> GlobalHotkeys { get; set; }
public List<CoreTypeItem> CoreTypeItem { get; set; }
public DNSItem DNSItem { get; set; }
#endregion other entities
}

View File

@ -253,3 +253,20 @@ public class WindowSizeItem
public int Width { get; set; }
public int Height { get; set; }
}
[Serializable]
public class DNSItem
{
public bool? UseSystemHosts { get; set; }
public bool? AddCommonHosts { get; set; }
public bool? FakeIP { get; set; }
public bool? BlockBindingQuery { get; set; }
public string? DirectDNS { get; set; }
public string? RemoteDNS { get; set; }
public string? SingboxOutboundsResolveDNS { get; set; }
public string? SingboxFinalResolveDNS { get; set; }
public string? RayStrategy4Freedom { get; set; }
public string? SingboxStrategy4Direct { get; set; }
public string? SingboxStrategy4Proxy { get; set; }
public string? Hosts { get; set; }
}

View File

@ -1,19 +0,0 @@
using SQLite;
namespace ServiceLib.Models;
[Serializable]
public class DNSItem
{
[PrimaryKey]
public string Id { get; set; }
public string Remarks { get; set; }
public bool Enabled { get; set; } = true;
public ECoreType CoreType { get; set; }
public bool UseSystemHosts { get; set; }
public string? NormalDNS { get; set; }
public string? TunDNS { get; set; }
public string? DomainStrategy4Freedom { get; set; }
public string? DomainDNSAddress { get; set; }
}

View File

@ -36,6 +36,7 @@ public class Dns4Sbox
public class Route4Sbox
{
public Rule4Sbox? default_domain_resolver { get; set; } // or string
public bool? auto_detect_interface { get; set; }
public List<Rule4Sbox> rules { get; set; }
public List<Ruleset4Sbox>? rule_set { get; set; }
@ -75,7 +76,7 @@ public class Rule4Sbox
public string? strategy { get; set; }
public List<string>? sniffer { get; set; }
public string? rcode { get; set; }
public List<object>? query_type { get; set; }
public List<int>? query_type { get; set; }
public List<string>? answer { get; set; }
public List<string>? ns { get; set; }
public List<string>? extra { get; set; }
@ -237,13 +238,7 @@ public class Server4Sbox : BaseServer4Sbox
public string? path { get; set; }
public Headers4Sbox? headers { get; set; }
// public List<string>? path { get; set; } // hosts
public Dictionary<string, object>? predefined { get; set; }
// Deprecated
public string? address { get; set; }
public string? address_resolver { get; set; }
public string? address_strategy { get; set; }
public string? strategy { get; set; }
// Deprecated End
public Dictionary<string, List<string>>? predefined { get; set; }
}
public class Experimental4Sbox

View File

@ -5,7 +5,7 @@ namespace ServiceLib.Models;
public class V2rayConfig
{
public Log4Ray log { get; set; }
public object dns { get; set; }
public Dns4Ray dns { get; set; }
public List<Inbounds4Ray> inbounds { get; set; }
public List<Outbounds4Ray> outbounds { get; set; }
public Routing4Ray routing { get; set; }
@ -203,7 +203,8 @@ public class Response4Ray
public class Dns4Ray
{
public List<string> servers { get; set; }
public Dictionary<string, List<string>>? hosts { get; set; }
public List<object> servers { get; set; }
}
public class DnsServer4Ray

View File

@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
@ -2211,6 +2211,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Add Common DNS Hosts 的本地化字符串。
/// </summary>
public static string TbAddCommonDNSHosts {
get {
return ResourceManager.GetString("TbAddCommonDNSHosts", resourceCulture);
}
}
/// <summary>
/// 查找类似 Address 的本地化字符串。
/// </summary>
@ -2247,6 +2256,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Apply to Proxy Domains Only 的本地化字符串。
/// </summary>
public static string TbApplyProxyDomainsOnly {
get {
return ResourceManager.GetString("TbApplyProxyDomainsOnly", resourceCulture);
}
}
/// <summary>
/// 查找类似 Auto refresh 的本地化字符串。
/// </summary>
@ -2274,6 +2292,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Block SVCB and HTTPS Queries 的本地化字符串。
/// </summary>
public static string TbBlockSVCBHTTPSQueries {
get {
return ResourceManager.GetString("TbBlockSVCBHTTPSQueries", resourceCulture);
}
}
/// <summary>
/// 查找类似 Browse 的本地化字符串。
/// </summary>
@ -2346,6 +2373,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 DNS Hosts: (&quot;domain1 ip1 ip2&quot; per line) 的本地化字符串。
/// </summary>
public static string TbDNSHostsConfig {
get {
return ResourceManager.GetString("TbDNSHostsConfig", resourceCulture);
}
}
/// <summary>
/// 查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。
/// </summary>
@ -2391,6 +2427,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Domestic DNS 的本地化字符串。
/// </summary>
public static string TbDomesticDNS {
get {
return ResourceManager.GetString("TbDomesticDNS", resourceCulture);
}
}
/// <summary>
/// 查找类似 Edit 的本地化字符串。
/// </summary>
@ -2409,6 +2454,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 FakeIP 的本地化字符串。
/// </summary>
public static string TbFakeIP {
get {
return ResourceManager.GetString("TbFakeIP", resourceCulture);
}
}
/// <summary>
/// 查找类似 Fingerprint 的本地化字符串。
/// </summary>
@ -2598,6 +2652,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Prevent DNS Leaks 的本地化字符串。
/// </summary>
public static string TbPreventDNSLeaks {
get {
return ResourceManager.GetString("TbPreventDNSLeaks", resourceCulture);
}
}
/// <summary>
/// 查找类似 Private Key 的本地化字符串。
/// </summary>
@ -2634,6 +2697,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Remote DNS 的本地化字符串。
/// </summary>
public static string TbRemoteDNS {
get {
return ResourceManager.GetString("TbRemoteDNS", resourceCulture);
}
}
/// <summary>
/// 查找类似 Camouflage domain(host) 的本地化字符串。
/// </summary>
@ -2742,6 +2814,69 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 sing-box Direct Resolution Strategy 的本地化字符串。
/// </summary>
public static string TbSBDirectResolveStrategy {
get {
return ResourceManager.GetString("TbSBDirectResolveStrategy", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable to Override sing-box DoH Resolver 的本地化字符串。
/// </summary>
public static string TbSBDoHOverride {
get {
return ResourceManager.GetString("TbSBDoHOverride", resourceCulture);
}
}
/// <summary>
/// 查找类似 sing-box DoH Resolver Server 的本地化字符串。
/// </summary>
public static string TbSBDoHResolverServer {
get {
return ResourceManager.GetString("TbSBDoHResolverServer", resourceCulture);
}
}
/// <summary>
/// 查找类似 Fallback DNS Resolution, Suggest IP 的本地化字符串。
/// </summary>
public static string TbSBFallbackDNSResolve {
get {
return ResourceManager.GetString("TbSBFallbackDNSResolve", resourceCulture);
}
}
/// <summary>
/// 查找类似 Resolve Outbound Domains 的本地化字符串。
/// </summary>
public static string TbSBOutboundDomainResolve {
get {
return ResourceManager.GetString("TbSBOutboundDomainResolve", resourceCulture);
}
}
/// <summary>
/// 查找类似 Outbound DNS Resolution (sing-box) 的本地化字符串。
/// </summary>
public static string TbSBOutboundsResolverDNS {
get {
return ResourceManager.GetString("TbSBOutboundsResolverDNS", resourceCulture);
}
}
/// <summary>
/// 查找类似 sing-box Remote Resolution Strategy 的本地化字符串。
/// </summary>
public static string TbSBRemoteResolveStrategy {
get {
return ResourceManager.GetString("TbSBRemoteResolveStrategy", resourceCulture);
}
}
/// <summary>
/// 查找类似 Encryption method (security) 的本地化字符串。
/// </summary>
@ -3687,6 +3822,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 xray Freedom Resolution Strategy 的本地化字符串。
/// </summary>
public static string TbXrayFreedomResolveStrategy {
get {
return ResourceManager.GetString("TbXrayFreedomResolveStrategy", resourceCulture);
}
}
/// <summary>
/// 查找类似 The delay: {0} ms, {1} 的本地化字符串。
/// </summary>
@ -3696,6 +3840,24 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Advanced DNS Settings 的本地化字符串。
/// </summary>
public static string ThAdvancedDNSSettings {
get {
return ResourceManager.GetString("ThAdvancedDNSSettings", resourceCulture);
}
}
/// <summary>
/// 查找类似 Basic DNS Settings 的本地化字符串。
/// </summary>
public static string ThBasicDNSSettings {
get {
return ResourceManager.GetString("ThBasicDNSSettings", resourceCulture);
}
}
/// <summary>
/// 查找类似 Active 的本地化字符串。
/// </summary>

View File

@ -1398,4 +1398,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>Add [Anytls] Configuration</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>Remote DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>Domestic DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>Outbound DNS Resolution (sing-box)</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>Resolve Outbound Domains</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH Resolver Server</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>Fallback DNS Resolution, Suggest IP</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray Freedom Resolution Strategy</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box Direct Resolution Strategy</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box Remote Resolution Strategy</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>Add Common DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>Enable to Override sing-box DoH Resolver</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>Block SVCB and HTTPS Queries</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>Prevent DNS Leaks</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>Apply to Proxy Domains Only</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>Basic DNS Settings</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>Advanced DNS Settings</value>
</data>
</root>

View File

@ -1398,4 +1398,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>Add [Anytls] Configuration</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>Remote DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>Domestic DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>Outbound DNS Resolution (sing-box)</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>Resolve Outbound Domains</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH Resolver Server</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>Fallback DNS Resolution, Suggest IP</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray Freedom Resolution Strategy</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box Direct Resolution Strategy</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box Remote Resolution Strategy</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>Add Common DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>Enable to Override sing-box DoH Resolver</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>Block SVCB and HTTPS Queries</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>Prevent DNS Leaks</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>Apply to Proxy Domains Only</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>Basic DNS Settings</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>Advanced DNS Settings</value>
</data>
</root>

View File

@ -1398,4 +1398,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>Add [Anytls] Configuration</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>Remote DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>Domestic DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>Outbound DNS Resolution (sing-box)</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>Resolve Outbound Domains</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH Resolver Server</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>Fallback DNS Resolution, Suggest IP</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray Freedom Resolution Strategy</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box Direct Resolution Strategy</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box Remote Resolution Strategy</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>Add Common DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>Enable to Override sing-box DoH Resolver</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>Block SVCB and HTTPS Queries</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>Prevent DNS Leaks</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>Apply to Proxy Domains Only</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>Basic DNS Settings</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>Advanced DNS Settings</value>
</data>
</root>

View File

@ -807,9 +807,6 @@
<data name="menuMoveUp" xml:space="preserve">
<value>Вверх (U)</value>
</data>
<data name="menuMoveTo" xml:space="preserve">
<value>Переместить вверх/вниз</value>
</data>
<data name="MsgFilterTitle" xml:space="preserve">
<value>Фильтр, поддерживает regex</value>
</data>
@ -969,6 +966,9 @@
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>URL для тестирования скорости</value>
</data>
<data name="menuMoveTo" xml:space="preserve">
<value>Переместить вверх/вниз</value>
</data>
<data name="TbPublicKey" xml:space="preserve">
<value>PublicKey</value>
</data>
@ -1398,4 +1398,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>Add [Anytls] Configuration</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>Remote DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>Domestic DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>Outbound DNS Resolution (sing-box)</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>Resolve Outbound Domains</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH Resolver Server</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>Fallback DNS Resolution, Suggest IP</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray Freedom Resolution Strategy</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box Direct Resolution Strategy</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box Remote Resolution Strategy</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>Add Common DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>Enable to Override sing-box DoH Resolver</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>Block SVCB and HTTPS Queries</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>Prevent DNS Leaks</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>Apply to Proxy Domains Only</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>Basic DNS Settings</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>Advanced DNS Settings</value>
</data>
</root>

View File

@ -1395,4 +1395,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>添加 [Anytls] 配置文件</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>远程 DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>直连 DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>出站 DNS 解析</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>解析出站域名</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH 解析服务器</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>兜底解析其他 DNS 域名,建议设为 ip</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray freedom 解析策略</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box 直连解析策略</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box 远程解析策略</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>添加常用 DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>开启后可覆盖 sing-box DoH 解析服务器</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>阻止 SVCB 和 HTTPS 查询</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>避免 DNS 泄漏</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts“域名1 ip1 ip2” 一行一个)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>仅对代理域名生效</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>DNS 基础设置</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>DNS 进阶设置</value>
</data>
</root>

View File

@ -1395,4 +1395,58 @@
<data name="menuAddAnytlsServer" xml:space="preserve">
<value>新增 [Anytls] 設定檔</value>
</data>
<data name="TbRemoteDNS" xml:space="preserve">
<value>Remote DNS</value>
</data>
<data name="TbDomesticDNS" xml:space="preserve">
<value>Domestic DNS</value>
</data>
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
<value>Outbound DNS Resolution (sing-box)</value>
</data>
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
<value>Resolve Outbound Domains</value>
</data>
<data name="TbSBDoHResolverServer" xml:space="preserve">
<value>sing-box DoH Resolver Server</value>
</data>
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
<value>Fallback DNS Resolution, Suggest IP</value>
</data>
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
<value>xray Freedom Resolution Strategy</value>
</data>
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
<value>sing-box Direct Resolution Strategy</value>
</data>
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
<value>sing-box Remote Resolution Strategy</value>
</data>
<data name="TbAddCommonDNSHosts" xml:space="preserve">
<value>Add Common DNS Hosts</value>
</data>
<data name="TbSBDoHOverride" xml:space="preserve">
<value>Enable to Override sing-box DoH Resolver</value>
</data>
<data name="TbFakeIP" xml:space="preserve">
<value>FakeIP</value>
</data>
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
<value>Block SVCB and HTTPS Queries</value>
</data>
<data name="TbPreventDNSLeaks" xml:space="preserve">
<value>Prevent DNS Leaks</value>
</data>
<data name="TbDNSHostsConfig" xml:space="preserve">
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
</data>
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
<value>Apply to Proxy Domains Only</value>
</data>
<data name="ThBasicDNSSettings" xml:space="preserve">
<value>Basic DNS Settings</value>
</data>
<data name="ThAdvancedDNSSettings" xml:space="preserve">
<value>Advanced DNS Settings</value>
</data>
</root>

View File

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Net.NetworkInformation;
using System.Reactive;
using System.Text;
using DynamicData;
using ServiceLib.Models;
@ -73,7 +75,7 @@ public class CoreConfigSingboxService
await GenRouting(singboxConfig);
await GenDns(node, singboxConfig);
await GenDns(singboxConfig);
await GenExperimental(singboxConfig);
@ -243,7 +245,7 @@ public class CoreConfigSingboxService
singboxConfig.route.rules.Add(rule);
}
await GenDnsDomains(null, singboxConfig, null);
await GenDns(singboxConfig);
//var dnsServer = singboxConfig.dns?.servers.FirstOrDefault();
//if (dnsServer != null)
//{
@ -315,7 +317,7 @@ public class CoreConfigSingboxService
await GenOutbound(node, singboxConfig.outbounds.First());
}
await GenMoreOutbounds(node, singboxConfig);
await GenDnsDomains(null, singboxConfig, null);
await GenDns(singboxConfig);
singboxConfig.route.rules.Clear();
singboxConfig.inbounds.Clear();
@ -417,7 +419,7 @@ public class CoreConfigSingboxService
}
await GenOutboundsList(proxyProfiles, singboxConfig);
await GenDns(null, singboxConfig);
await GenDns(singboxConfig);
await ConvertGeo2Ruleset(singboxConfig);
ret.Success = true;
@ -648,17 +650,6 @@ public class CoreConfigSingboxService
outbound.server_port = node.Port;
outbound.type = Global.ProtocolTypes[node.ConfigType];
if (Utils.IsDomain(node.Address))
{
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
var localDnsAddress = string.IsNullOrEmpty(item?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : item?.DomainDNSAddress;
outbound.domain_resolver = new()
{
server = localDnsAddress.StartsWith("tag://") ? localDnsAddress.Substring(6) : "local_resolver",
strategy = string.IsNullOrEmpty(item?.DomainStrategy4Freedom) ? null : item?.DomainStrategy4Freedom
};
}
switch (node.ConfigType)
{
case EConfigType.VMess:
@ -788,17 +779,6 @@ public class CoreConfigSingboxService
endpoint.address = Utils.String2List(node.RequestHost);
endpoint.type = Global.ProtocolTypes[node.ConfigType];
if (Utils.IsDomain(node.Address))
{
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
var localDnsAddress = string.IsNullOrEmpty(item?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : item?.DomainDNSAddress;
endpoint.domain_resolver = new()
{
server = localDnsAddress.StartsWith("tag://") ? localDnsAddress.Substring(6) : "local_resolver",
strategy = string.IsNullOrEmpty(item?.DomainStrategy4Freedom) ? null : item?.DomainStrategy4Freedom
};
}
switch (node.ConfigType)
{
case EConfigType.WireGuard:
@ -1245,6 +1225,13 @@ public class CoreConfigSingboxService
try
{
singboxConfig.route.final = Global.ProxyTag;
var item = _config.DNSItem;
singboxConfig.route.default_domain_resolver = new()
{
server = "outbound_resolver",
strategy = item.SingboxStrategy4Direct
}
;
if (_config.TunModeItem.EnableTun)
{
@ -1325,14 +1312,14 @@ public class CoreConfigSingboxService
if (routing != null)
{
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules ?? [])
foreach (var item1 in rules ?? [])
{
if (item.Enabled)
if (item1.Enabled)
{
await GenRoutingUserRule(item, singboxConfig);
if (item.Ip != null && item.Ip.Count > 0)
await GenRoutingUserRule(item1, singboxConfig);
if (item1.Ip != null && item1.Ip.Count > 0)
{
ipRules.Add(item);
ipRules.Add(item1);
}
}
}
@ -1340,9 +1327,9 @@ public class CoreConfigSingboxService
if (_config.RoutingBasicItem.DomainStrategy == "IPIfNonMatch")
{
singboxConfig.route.rules.Add(resolveRule);
foreach (var item in ipRules)
foreach (var item2 in ipRules)
{
await GenRoutingUserRule(item, singboxConfig);
await GenRoutingUserRule(item2, singboxConfig);
}
}
}
@ -1585,36 +1572,17 @@ public class CoreConfigSingboxService
return server.tag;
}
private async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
private async Task<int> GenDns(SingboxConfig singboxConfig)
{
try
{
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
var strDNS = string.Empty;
if (_config.TunModeItem.EnableTun)
{
strDNS = string.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;
}
else
{
strDNS = string.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS;
}
var dNSItem = _config.DNSItem;
await GenDnsServers(singboxConfig, dNSItem);
await GenDnsRules(singboxConfig, dNSItem);
var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);
if (dns4Sbox is null)
{
return 0;
}
singboxConfig.dns = dns4Sbox;
if (dns4Sbox.servers != null && dns4Sbox.servers.Count > 0 && dns4Sbox.servers.First().address.IsNullOrEmpty())
{
await GenDnsDomains(node, singboxConfig, item);
}
else
{
await GenDnsDomainsLegacy(node, singboxConfig, item);
}
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.independent_cache = true;
singboxConfig.dns.final = "dns_remote"; // TODO
}
catch (Exception ex)
{
@ -1623,211 +1591,280 @@ public class CoreConfigSingboxService
return 0;
}
private async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
private async Task<int> GenDnsServers(SingboxConfig singboxConfig, DNSItem dNSItem)
{
var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= [];
dns4Sbox.rules ??= [];
var finalDns = ParseDnsAddress(dNSItem.SingboxFinalResolveDNS);
finalDns.tag = "final_resolver";
var tag = "local_resolver";
var localDnsAddress = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress;
var directDns = ParseDnsAddress(dNSItem.DirectDNS);
directDns.tag = "dns_direct";
directDns.domain_resolver = "final_resolver";
if (localDnsAddress.StartsWith("tag://"))
var remoteDns = ParseDnsAddress(dNSItem.RemoteDNS);
remoteDns.tag = "dns_remote";
remoteDns.detour = Global.ProxyTag;
remoteDns.domain_resolver = "final_resolver";
var resolverDns = ParseDnsAddress(dNSItem.SingboxOutboundsResolveDNS);
resolverDns.tag = "outbound_resolver";
resolverDns.domain_resolver = "final_resolver";
var hostsDns = new Server4Sbox
{
tag = localDnsAddress.Substring(6);
var localDnsTag = "local_local";
dns4Sbox.servers.Add(new()
tag = "dns_hosts",
type = "hosts",
};
if (dNSItem.AddCommonHosts == true)
{
tag = localDnsTag,
type = "local"
});
dns4Sbox.rules.Insert(0, new()
{
server = localDnsTag,
clash_mode = ERuleMode.Direct.ToString()
});
hostsDns.predefined = Global.PredefinedHosts;
}
else
var userHostsMap = dNSItem.Hosts?
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Where(line => line.Contains(' '))
.ToDictionary(
line =>
{
var (dnsType, dnsHost, dnsPort, dnsPath) = ParseDnsAddress(localDnsAddress);
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
return parts[0];
},
line =>
{
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
var values = parts.Skip(1).ToList();
return values;
}
);
dns4Sbox.servers.Add(new()
if (userHostsMap != null)
{
tag = tag,
type = dnsType,
server = dnsHost,
Interface = dnsType == "dhcp" ? dnsHost : null,
server_port = dnsPort,
path = dnsPath
});
dns4Sbox.rules.Insert(0, new()
foreach (var kvp in userHostsMap)
{
server = tag,
clash_mode = ERuleMode.Direct.ToString()
});
hostsDns.predefined[kvp.Key] = kvp.Value;
}
}
dns4Sbox.rules.Insert(0, new()
foreach (var host in hostsDns.predefined)
{
server = dns4Sbox.servers.Where(t => t.detour == Global.ProxyTag).Select(t => t.tag).FirstOrDefault() ?? "remote",
clash_mode = ERuleMode.Global.ToString()
});
//Tun2SocksAddress
if (_config.TunModeItem.EnableTun && node?.ConfigType == EConfigType.SOCKS && Utils.IsDomain(node?.Sni))
if (finalDns.server == host.Key)
{
dns4Sbox.rules.Insert(0, new()
finalDns.domain_resolver = "dns_hosts";
}
if (remoteDns.server == host.Key)
{
server = tag,
domain = [node?.Sni],
strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom
});
remoteDns.domain_resolver = "dns_hosts";
}
if (resolverDns.server == host.Key)
{
resolverDns.domain_resolver = "dns_hosts";
}
if (directDns.server == host.Key)
{
directDns.domain_resolver = "dns_hosts";
}
}
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.servers ??= new List<Server4Sbox>();
singboxConfig.dns.servers.Add(remoteDns);
singboxConfig.dns.servers.Add(directDns);
singboxConfig.dns.servers.Add(finalDns);
singboxConfig.dns.servers.Add(resolverDns);
singboxConfig.dns.servers.Add(hostsDns);
// fake ip
if (dNSItem.FakeIP == true)
{
var fakeip = new Server4Sbox
{
tag = "dns-fake",
type = "fakeip",
inet4_range = "198.18.0.0/15",
inet6_range = "fc00::/18",
};
singboxConfig.dns.servers.Add(fakeip);
}
singboxConfig.dns = dns4Sbox;
return await Task.FromResult(0);
}
private async Task<int> GenDnsDomainsLegacy(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
private async Task<int> GenDnsRules(SingboxConfig singboxConfig, DNSItem dNSItem)
{
var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= [];
dns4Sbox.rules ??= [];
var tag = "local_local";
dns4Sbox.servers.Add(new()
singboxConfig.dns ??= new Dns4Sbox();
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
// hosts
singboxConfig.dns.rules.Add(new Rule4Sbox
{
tag = tag,
address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress,
detour = Global.DirectTag,
strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom,
ip_accept_any = true,
server = "dns_hosts",
});
dns4Sbox.rules.Insert(0, new()
// clash mode
singboxConfig.dns.rules.Add(new Rule4Sbox
{
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",
server = "dns_remote",
strategy = dNSItem.SingboxStrategy4Proxy.IsNullOrEmpty() ? null : dNSItem.SingboxStrategy4Proxy,
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)
singboxConfig.dns.rules.Add(new Rule4Sbox
{
dns4Sbox.rules.Insert(0, new()
{
server = tag,
domain = lstDomain
server = "dns_direct",
strategy = dNSItem.SingboxStrategy4Direct.IsNullOrEmpty() ? null : dNSItem.SingboxStrategy4Direct,
clash_mode = ERuleMode.Direct.ToString()
});
// block binding query
singboxConfig.dns.rules.Add(new Rule4Sbox
{
query_type = new List<int> { 64, 65 },
action = "predefined",
rcode = "NOTIMP"
});
var routing = await ConfigHandler.GetDefaultRouting(_config);
if (routing != null)
{
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules ?? [])
{
if (!item.Enabled)
{
continue;
}
if (item.Domain == null || item.Domain.Count == 0)
{
continue;
}
var rule = new Rule4Sbox();
var countDomain = 0;
foreach (var it in item.Domain)
{
if (ParseV2Domain(it, rule))
{
countDomain++;
}
}
if (countDomain <= 0)
{
continue;
}
if (item.OutboundTag == Global.DirectTag)
{
rule.server = "dns_direct";
rule.strategy = dNSItem.SingboxStrategy4Direct.IsNullOrEmpty() ? null : dNSItem.SingboxStrategy4Direct;
}
else if (item.OutboundTag == Global.ProxyTag)
{
if (dNSItem.FakeIP == true)
{
var rule4Fake = JsonUtils.DeepCopy(rule);
rule4Fake.server = "dns-fake";
singboxConfig.dns.rules.Add(rule4Fake);
}
rule.server = "dns_remote";
rule.strategy = dNSItem.SingboxStrategy4Proxy.IsNullOrEmpty() ? null : dNSItem.SingboxStrategy4Proxy;
}
else if (item.OutboundTag == Global.BlockTag)
{
rule.action = "predefined";
rule.rcode = "NOERROR";
rule.answer = new List<string> { "A" };
}
singboxConfig.dns.rules.Add(rule);
}
}
//Tun2SocksAddress
if (_config.TunModeItem.EnableTun && node?.ConfigType == EConfigType.SOCKS && Utils.IsDomain(node?.Sni))
{
dns4Sbox.rules.Insert(0, new()
{
server = tag,
domain = [node?.Sni]
});
}
singboxConfig.dns = dns4Sbox;
return await Task.FromResult(0);
}
private (string type, string? host, int? port, string? path) ParseDnsAddress(string address)
private static Server4Sbox? ParseDnsAddress(string address)
{
string type = "udp";
string? host = null;
int? port = null;
string? path = null;
if (string.IsNullOrEmpty(address))
{
return null;
}
var server = new Server4Sbox();
if (address is "local" or "localhost")
{
return ("local", null, null, null);
server.type = "local";
return server;
}
if (address.StartsWith("dhcp://", StringComparison.OrdinalIgnoreCase))
{
string interface_name = address.Substring(7);
return ("dhcp", interface_name == "auto" ? null : interface_name, null, null);
var interface_name = address.Substring(7);
server.type = "dhcp";
server.Interface = interface_name == "auto" ? null : interface_name;
return server;
}
if (!address.Contains("://"))
{
// udp dns
host = address;
return (type, host, port, path);
server.type = "udp";
server.server = address;
return server;
}
try
{
int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
type = address.Substring(0, protocolEndIndex).ToLower();
var protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
server.type = address.Substring(0, protocolEndIndex).ToLower();
var uri = new Uri(address);
host = uri.Host;
server.server = uri.Host;
if (!uri.IsDefaultPort)
{
port = uri.Port;
server.server_port = uri.Port;
}
if ((type == "https" || type == "h3") && !string.IsNullOrEmpty(uri.AbsolutePath) && uri.AbsolutePath != "/")
if ((server.type == "https" || server.type == "h3") && !string.IsNullOrEmpty(uri.AbsolutePath) && uri.AbsolutePath != "/")
{
path = uri.AbsolutePath;
server.path = uri.AbsolutePath;
}
}
catch (UriFormatException)
{
int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
var protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
if (protocolEndIndex > 0)
{
type = address.Substring(0, protocolEndIndex).ToLower();
string remaining = address.Substring(protocolEndIndex + 3);
server.type = address.Substring(0, protocolEndIndex).ToLower();
var remaining = address.Substring(protocolEndIndex + 3);
int portIndex = remaining.IndexOf(':');
int pathIndex = remaining.IndexOf('/');
var portIndex = remaining.IndexOf(':');
var pathIndex = remaining.IndexOf('/');
if (portIndex > 0)
{
host = remaining.Substring(0, portIndex);
string portPart = pathIndex > portIndex
server.server = remaining.Substring(0, portIndex);
var portPart = pathIndex > portIndex
? remaining.Substring(portIndex + 1, pathIndex - portIndex - 1)
: remaining.Substring(portIndex + 1);
if (int.TryParse(portPart, out int parsedPort))
if (int.TryParse(portPart, out var parsedPort))
{
port = parsedPort;
server.server_port = parsedPort;
}
}
else if (pathIndex > 0)
{
host = remaining.Substring(0, pathIndex);
server.server = remaining.Substring(0, pathIndex);
}
else
{
host = remaining;
server.server = remaining;
}
if (pathIndex > 0 && (type == "https" || type == "h3"))
if (pathIndex > 0 && (server.type == "https" || server.type == "h3"))
{
path = remaining.Substring(pathIndex);
server.path = remaining.Substring(pathIndex);
}
}
}
return (type, host, port, path);
return server;
}
private async Task<int> GenExperimental(SingboxConfig singboxConfig)

View File

@ -1135,13 +1135,8 @@ public class CoreConfigV2rayService
{
try
{
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
var normalDNS = item?.NormalDNS;
var domainStrategy4Freedom = item?.DomainStrategy4Freedom;
if (normalDNS.IsNullOrEmpty())
{
normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
}
var dNSItem = _config.DNSItem;
var domainStrategy4Freedom = dNSItem?.RayStrategy4Freedom;
//Outbound Freedom domainStrategy
if (domainStrategy4Freedom.IsNotEmpty())
@ -1149,47 +1144,16 @@ public class CoreConfigV2rayService
var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag });
if (outbound != null)
{
outbound.settings = new();
outbound.settings.domainStrategy = domainStrategy4Freedom;
outbound.settings.userLevel = 0;
outbound.settings = new()
{
domainStrategy = domainStrategy4Freedom,
userLevel = 0
};
}
}
var obj = JsonUtils.ParseJson(normalDNS);
if (obj is null)
{
List<string> servers = [];
string[] arrDNS = normalDNS.Split(',');
foreach (string str in arrDNS)
{
servers.Add(str);
}
obj = JsonUtils.ParseJson("{}");
obj["servers"] = JsonUtils.SerializeToNode(servers);
}
// Append to dns settings
if (item.UseSystemHosts)
{
var systemHosts = Utils.GetSystemHosts();
if (systemHosts.Count > 0)
{
var normalHost = obj["hosts"];
if (normalHost != null)
{
foreach (var host in systemHosts)
{
if (normalHost[host.Key] != null)
continue;
normalHost[host.Key] = host.Value;
}
}
}
}
await GenDnsDomains(node, obj, item);
v2rayConfig.dns = obj;
await GenDnsServers(node, v2rayConfig, dNSItem);
await GenDnsHosts(v2rayConfig, dNSItem);
}
catch (Exception ex)
{
@ -1198,19 +1162,70 @@ public class CoreConfigV2rayService
return 0;
}
private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
private async Task<int> GenDnsServers(ProfileItem? node, V2rayConfig v2rayConfig, DNSItem dNSItem)
{
if (node == null)
var directDomainList = new List<string>();
var directGeositeList = new List<string>();
var proxyDomainList = new List<string>();
var proxyGeositeList = new List<string>();
var routing = await ConfigHandler.GetDefaultRouting(_config);
if (routing != null)
{
return 0;
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules ?? [])
{
if (!item.Enabled)
{
continue;
}
var servers = dns["servers"];
if (servers != null)
if (item.Domain == null || item.Domain.Count == 0)
{
var domainList = new List<string>();
continue;
}
if (item.OutboundTag == Global.DirectTag)
{
foreach (var domain in item.Domain)
{
if (domain.StartsWith('#'))
{
continue;
}
var domain1 = domain.Replace(Global.RoutingRuleComma, ",");
if (domain1.StartsWith("geosite:"))
{
directGeositeList.Add(domain1);
}
else
{
directDomainList.Add(domain1);
}
}
}
else if (item.OutboundTag == Global.ProxyTag)
{
foreach (var domain in item.Domain)
{
if (domain.StartsWith('#'))
{
continue;
}
var domain1 = domain.Replace(Global.RoutingRuleComma, ",");
if (domain1.StartsWith("geosite:"))
{
proxyGeositeList.Add(domain1);
}
else
{
proxyDomainList.Add(domain1);
}
}
}
}
}
if (Utils.IsDomain(node.Address))
{
domainList.Add(node.Address);
directDomainList.Add(node.Address);
}
var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
if (subItem is not null)
@ -1223,7 +1238,7 @@ public class CoreConfigV2rayService
&& prevNode.ConfigType != EConfigType.TUIC
&& Utils.IsDomain(prevNode.Address))
{
domainList.Add(prevNode.Address);
directDomainList.Add(prevNode.Address);
}
// Next proxy
@ -1234,18 +1249,113 @@ public class CoreConfigV2rayService
&& nextNode.ConfigType != EConfigType.TUIC
&& Utils.IsDomain(nextNode.Address))
{
domainList.Add(nextNode.Address);
directDomainList.Add(nextNode.Address);
}
}
if (domainList.Count > 0)
v2rayConfig.dns ??= new Dns4Ray();
v2rayConfig.dns.servers ??= new List<object>();
if (proxyDomainList.Count > 0)
{
var dnsServer = new DnsServer4Ray()
{
address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress,
address = dNSItem.RemoteDNS,
skipFallback = true,
domains = domainList
domains = proxyDomainList
};
servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer));
v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer));
}
if (proxyGeositeList.Count > 0)
{
var dnsServer = new DnsServer4Ray()
{
address = dNSItem.RemoteDNS,
skipFallback = true,
domains = proxyGeositeList
};
v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer));
}
if (directDomainList.Count > 0)
{
var dnsServer = new DnsServer4Ray()
{
address = dNSItem.DirectDNS,
skipFallback = true,
domains = directDomainList
};
v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer));
}
if (directGeositeList.Count > 0)
{
var dnsServer = new DnsServer4Ray()
{
address = dNSItem.DirectDNS,
skipFallback = true,
domains = directGeositeList
};
v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer));
}
v2rayConfig.dns.servers.Add(dNSItem.RemoteDNS); // fallback DNS server
return await Task.FromResult(0);
}
private async Task<int> GenDnsHosts(V2rayConfig v2rayConfig, DNSItem dNSItem)
{
if (dNSItem.AddCommonHosts == false && dNSItem.UseSystemHosts == false && dNSItem.Hosts.IsNullOrEmpty())
{
return await Task.FromResult(0);
}
v2rayConfig.dns ??= new Dns4Ray();
v2rayConfig.dns.hosts ??= new Dictionary<string, List<string>>();
if (dNSItem.AddCommonHosts == true)
{
v2rayConfig.dns.hosts = Global.PredefinedHosts;
}
if (dNSItem.UseSystemHosts == true)
{
var systemHosts = Utils.GetSystemHosts();
if (systemHosts.Count > 0)
{
var normalHost = v2rayConfig.dns.hosts;
if (normalHost != null)
{
foreach (var host in systemHosts)
{
if (normalHost[host.Key] != null)
{
continue;
}
normalHost[host.Key] = new List<string> { host.Value };
}
}
}
}
var userHostsMap = dNSItem.Hosts?
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Where(line => line.Contains(' '))
.ToDictionary(
line =>
{
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
return parts[0];
},
line =>
{
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
var values = parts.Skip(1).ToList();
return values;
}
);
if (userHostsMap != null)
{
foreach (var kvp in userHostsMap)
{
v2rayConfig.dns.hosts[kvp.Key] = kvp.Value;
}
}
return await Task.FromResult(0);

View File

@ -6,111 +6,81 @@ namespace ServiceLib.ViewModels;
public class DNSSettingViewModel : MyReactiveObject
{
[Reactive] public bool UseSystemHosts { get; set; }
[Reactive] public string DomainStrategy4Freedom { get; set; }
[Reactive] public string DomainDNSAddress { get; set; }
[Reactive] public string NormalDNS { get; set; }
[Reactive] public string DomainStrategy4Freedom2 { get; set; }
[Reactive] public string DomainDNSAddress2 { get; set; }
[Reactive] public string NormalDNS2 { get; set; }
[Reactive] public string TunDNS2 { get; set; }
[Reactive] public bool? UseSystemHosts { get; set; }
[Reactive] public bool? AddCommonHosts { get; set; }
[Reactive] public bool? FakeIP { get; set; }
[Reactive] public bool? BlockBindingQuery { get; set; }
[Reactive] public string? DirectDNS { get; set; }
[Reactive] public string? RemoteDNS { get; set; }
[Reactive] public string? SingboxOutboundsResolveDNS { get; set; }
[Reactive] public string? SingboxFinalResolveDNS { get; set; }
[Reactive] public string? RayStrategy4Freedom { get; set; }
[Reactive] public string? SingboxStrategy4Direct { get; set; }
[Reactive] public string? SingboxStrategy4Proxy { get; set; }
[Reactive] public string? Hosts { get; set; }
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; }
public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCmd { get; }
//public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; }
//public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCmd { get; }
public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = AppHandler.Instance.Config;
_updateView = updateView;
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
{
await SaveSettingAsync();
});
SaveCmd = ReactiveCommand.CreateFromTask(SaveSettingAsync);
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
{
NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
await Task.CompletedTask;
});
//ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
//{
// NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
// await Task.CompletedTask;
//});
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
{
NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
await Task.CompletedTask;
});
//ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
//{
// NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
// TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
// await Task.CompletedTask;
//});
_ = Init();
}
private async Task Init()
{
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
_config = AppHandler.Instance.Config;
var item = _config.DNSItem;
UseSystemHosts = item.UseSystemHosts;
DomainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty;
DomainDNSAddress = item?.DomainDNSAddress ?? string.Empty;
NormalDNS = item?.NormalDNS ?? string.Empty;
var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
DomainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty;
DomainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty;
NormalDNS2 = item2?.NormalDNS ?? string.Empty;
TunDNS2 = item2?.TunDNS ?? string.Empty;
AddCommonHosts = item.AddCommonHosts;
FakeIP = item.FakeIP;
BlockBindingQuery = item.BlockBindingQuery;
DirectDNS = item.DirectDNS;
RemoteDNS = item.RemoteDNS;
RayStrategy4Freedom = item.RayStrategy4Freedom;
SingboxOutboundsResolveDNS = item.SingboxOutboundsResolveDNS;
SingboxFinalResolveDNS = item.SingboxFinalResolveDNS;
SingboxStrategy4Direct = item.SingboxStrategy4Direct;
SingboxStrategy4Proxy = item.SingboxStrategy4Proxy;
Hosts = item.Hosts;
}
private async Task SaveSettingAsync()
{
if (NormalDNS.IsNotEmpty())
{
var obj = JsonUtils.ParseJson(NormalDNS);
if (obj != null && obj["servers"] != null)
_config.DNSItem.UseSystemHosts = UseSystemHosts;
_config.DNSItem.AddCommonHosts = AddCommonHosts;
_config.DNSItem.FakeIP = FakeIP;
_config.DNSItem.BlockBindingQuery = BlockBindingQuery;
_config.DNSItem.DirectDNS = DirectDNS;
_config.DNSItem.RemoteDNS = RemoteDNS;
_config.DNSItem.RayStrategy4Freedom = RayStrategy4Freedom;
_config.DNSItem.SingboxOutboundsResolveDNS = SingboxOutboundsResolveDNS;
_config.DNSItem.SingboxFinalResolveDNS = SingboxFinalResolveDNS;
_config.DNSItem.SingboxStrategy4Direct = SingboxStrategy4Direct;
_config.DNSItem.SingboxStrategy4Proxy = SingboxStrategy4Proxy;
_config.DNSItem.Hosts = Hosts;
await ConfigHandler.SaveConfig(_config);
if (_updateView != null)
{
await _updateView(EViewAction.CloseWindow, null);
}
else
{
if (NormalDNS.Contains('{') || NormalDNS.Contains('}'))
{
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
return;
}
}
}
if (NormalDNS2.IsNotEmpty())
{
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2);
if (obj2 == null)
{
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
return;
}
}
if (TunDNS2.IsNotEmpty())
{
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2);
if (obj2 == null)
{
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
return;
}
}
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
item.DomainStrategy4Freedom = DomainStrategy4Freedom;
item.DomainDNSAddress = DomainDNSAddress;
item.UseSystemHosts = UseSystemHosts;
item.NormalDNS = NormalDNS;
await ConfigHandler.SaveDNSItems(_config, item);
var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
item2.DomainStrategy4Freedom = DomainStrategy4Freedom2;
item2.DomainDNSAddress = DomainDNSAddress2;
item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2));
item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2));
await ConfigHandler.SaveDNSItems(_config, item2);
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
_ = _updateView?.Invoke(EViewAction.CloseWindow, null);
}
}

View File

@ -219,7 +219,6 @@ public class MainWindowViewModel : MyReactiveObject
_config.UiItem.ShowInTaskbar = true;
await ConfigHandler.InitBuiltinRouting(_config);
await ConfigHandler.InitBuiltinDNS(_config);
await ProfileExHandler.Instance.Init();
await CoreHandler.Instance.Init(_config, UpdateHandler);
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);

View File

@ -35,147 +35,220 @@
</StackPanel>
<TabControl HorizontalContentAlignment="Stretch">
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TabItem Header="{x:Static resx:ResUI.ThBasicDNSSettings}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid
Margin="{StaticResource Margin4}"
ColumnDefinitions="Auto,Auto,*"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
Text="{x:Static resx:ResUI.TbDomesticDNS}" />
<ComboBox
x:Name="cmbDirectDNS"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
<HyperlinkButton Classes="WithIcon" Click="linkDnsObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
</HyperlinkButton>
</TextBlock>
<Button
x:Name="btnImportDefConfig4V2ray"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand" />
</StackPanel>
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbRemoteDNS}" />
<ComboBox
x:Name="cmbRemoteDNS"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" />
<ComboBox
x:Name="cmbSBResolverDNS"
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" />
<ComboBox
x:Name="cmbSBFinalResolverDNS"
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock
Grid.Row="3"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" />
<ComboBox
x:Name="cmbRayFreedomDNSStrategy"
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
PlaceholderText="Default" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBDirectResolveStrategy}" />
<ComboBox
x:Name="cmbSBDirectDNSStrategy"
Grid.Row="5"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
PlaceholderText="Default" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBRemoteResolveStrategy}" />
<ComboBox
x:Name="cmbSBRemoteDNSStrategy"
Grid.Row="6"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
PlaceholderText="Default" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" />
<ToggleSwitch
x:Name="togAddCommonHosts"
Grid.Row="7"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="7"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSBDoHOverride}" />
</Grid>
</ScrollViewer>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.ThAdvancedDNSSettings}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid
Margin="{StaticResource Margin4}"
ColumnDefinitions="Auto,Auto,*"
RowDefinitions="Auto,Auto,Auto,Auto,*">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
<ToggleSwitch
x:Name="togUseSystemHosts"
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="150"
Margin="{StaticResource Margin4}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress"
Width="150"
Margin="{StaticResource Margin4}" />
</StackPanel>
</WrapPanel>
<HeaderedContentControl
Margin="{StaticResource Margin4}"
BorderBrush="Gray"
BorderThickness="1"
Header="HTTP/SOCKS">
<TextBox
Name="txtnormalDNS"
VerticalAlignment="Stretch"
Classes="TextArea"
MinLines="10"
TextWrapping="Wrap" />
</HeaderedContentControl>
</DockPanel>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
<HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
</HyperlinkButton>
</TextBlock>
<Button
x:Name="btnImportDefConfig4Singbox"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand" />
</StackPanel>
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
<ComboBox
x:Name="cmbdomainStrategy4Out"
Width="150"
Margin="{StaticResource Margin4}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress2"
Width="150"
Margin="{StaticResource Margin4}" />
</StackPanel>
</WrapPanel>
<Grid Margin="{StaticResource Margin4}" ColumnDefinitions="*,10,*">
<HeaderedContentControl
Grid.Row="1"
Grid.Column="0"
BorderBrush="Gray"
BorderThickness="1"
Header="HTTP/SOCKS">
<TextBox
Name="txtnormalDNS2"
VerticalAlignment="Stretch"
Classes="TextArea"
MinLines="10"
TextWrapping="Wrap" />
</HeaderedContentControl>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<HeaderedContentControl
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbFakeIP}" />
<ToggleSwitch
x:Name="togFakeIP"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
BorderBrush="Gray"
BorderThickness="1"
Header="{x:Static resx:ResUI.TbSettingsTunMode}">
<TextBox
Name="txttunDNS2"
VerticalAlignment="Stretch"
Classes="TextArea"
MinLines="10"
TextWrapping="Wrap" />
</HeaderedContentControl>
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbApplyProxyDomainsOnly}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" />
<ToggleSwitch
x:Name="togBlockBindingQuery"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbPreventDNSLeaks}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbDNSHostsConfig}" />
<TextBox
x:Name="txtHosts"
Grid.Row="4"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="{StaticResource Margin4}"
VerticalAlignment="Stretch"
Watermark="{x:Static resx:ResUI.TbDNSHostsConfig}"
BorderThickness="1"
Classes="TextArea"
TextWrapping="Wrap" />
</Grid>
</DockPanel>
</ScrollViewer>
</TabItem>
</TabControl>
</DockPanel>

View File

@ -17,26 +17,30 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
btnCancel.Click += (s, e) => this.Close();
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms;
cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress;
cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress;
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto" });
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress;
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
});
}

View File

@ -41,167 +41,269 @@
</StackPanel>
<TabControl HorizontalContentAlignment="Left">
<TabItem Header="{x:Static resx:ResUI.ThBasicDNSSettings}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Margin="{StaticResource Margin8}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
Text="{x:Static resx:ResUI.TbDomesticDNS}" />
<ComboBox
x:Name="cmbDirectDNS"
Grid.Row="0"
Grid.Column="1"
Width="200"
IsEditable="True"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink>
</TextBlock>
<Button
x:Name="btnImportDefConfig4V2ray"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRemoteDNS}" />
<ComboBox
x:Name="cmbRemoteDNS"
Grid.Row="1"
Grid.Column="1"
Width="200"
IsEditable="True"
Margin="{StaticResource Margin8}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
</StackPanel>
Style="{StaticResource DefComboBox}" />
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" />
<ComboBox
x:Name="cmbSBResolverDNS"
Grid.Row="2"
Grid.Column="1"
Width="200"
IsEditable="True"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" />
<ComboBox
x:Name="cmbSBFinalResolverDNS"
Grid.Row="3"
Grid.Column="1"
Width="200"
IsEditable="True"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="2"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" />
<ComboBox
x:Name="cmbRayFreedomDNSStrategy"
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
materialDesign:HintAssist.Hint="Default"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBDirectResolveStrategy}" />
<ComboBox
x:Name="cmbSBDirectDNSStrategy"
Grid.Row="5"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
materialDesign:HintAssist.Hint="Default"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBRemoteResolveStrategy}" />
<ComboBox
x:Name="cmbSBRemoteDNSStrategy"
Grid.Row="6"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
materialDesign:HintAssist.Hint="Default"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" />
<ToggleButton
x:Name="togAddCommonHosts"
Grid.Row="7"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="7"
Grid.Column="3"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSBDoHOverride}" />
</Grid>
</ScrollViewer>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.ThAdvancedDNSSettings}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Margin="{StaticResource Margin8}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
<ToggleButton
x:Name="togUseSystemHosts"
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="150"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress"
Width="150"
Margin="{StaticResource Margin8}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</WrapPanel>
<TextBox
x:Name="txtnormalDNS"
Margin="{StaticResource Margin8}"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="HTTP/SOCKS"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</DockPanel>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink>
</TextBlock>
<Button
x:Name="btnImportDefConfig4Singbox"
Margin="{StaticResource Margin8}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
</StackPanel>
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
<ComboBox
x:Name="cmbdomainStrategy4Out"
Width="150"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress2"
Width="150"
Margin="{StaticResource Margin8}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</WrapPanel>
<Grid Margin="{StaticResource Margin8}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<TextBox
x:Name="txtnormalDNS2"
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="HTTP/SOCKS"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<TextBox
x:Name="txttunDNS2"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFakeIP}" />
<ToggleButton
x:Name="togFakeIP"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbApplyProxyDomainsOnly}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" />
<ToggleButton
x:Name="togBlockBindingQuery"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPreventDNSLeaks}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbDNSHostsConfig}" />
<TextBox
x:Name="txtHosts"
Grid.Row="4"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="{StaticResource Margin8}"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbDNSHostsConfig}"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</Grid>
</DockPanel>
</ScrollViewer>
</TabItem>
</TabControl>
</DockPanel>

View File

@ -17,26 +17,30 @@ public partial class DNSSettingWindow
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms;
cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress;
cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress;
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto" });
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress;
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}