mirror of
				https://github.com/2dust/v2rayN.git
				synced 2025-10-30 12:02:53 +00:00 
			
		
		
		
	Compare commits
	
		
			50 commits
		
	
	
		
			57ebd7e896
			...
			0988cd0ff3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0988cd0ff3 | ||
|   | 86bdd20fe3 | ||
|   | 9077f55207 | ||
|   | 6200d909b7 | ||
|   | 7781dcd9fb | ||
|   | 5b44adfc68 | ||
|   | 48353d1892 | ||
|   | eb0e2aa5c5 | ||
|   | ea48dc5431 | ||
|   | dbe6f4083b | ||
|   | 774d6eeb8f | ||
|   | ef2728e248 | ||
|   | 54d936fd3e | ||
|   | ea1a7b6b46 | ||
|   | a2c4d4e424 | ||
|   | 65de9349dd | ||
|   | bdf3616a8e | ||
|   | 715a2b07a9 | ||
|   | e8590012c4 | ||
|   | 44634db5f4 | ||
|   | 0f46074283 | ||
|   | 7841c9fe84 | ||
|   | 59e69b4d66 | ||
|   | be09e8bc5d | ||
|   | 257bf51ded | ||
|   | 20883380d6 | ||
|   | 9bccdf1dac | ||
|   | 3ed34eb02f | ||
|   | 83c862afea | ||
|   | 8f0d4be095 | ||
|   | da8417165d | ||
|   | 56b619de1c | ||
|   | 0fbb2f6f32 | ||
|   | 8756e078a7 | ||
|   | 4f4ca3cf91 | ||
|   | 0be355ae8c | ||
|   | 9506e049e7 | ||
|   | 9a56824db5 | ||
|   | cfe56fad0c | ||
|   | 1bfd3e7d08 | ||
|   | aec8cb7e64 | ||
|   | 0f96af3142 | ||
|   | 9030830575 | ||
|   | fcdb46581b | ||
|   | ddedde53ea | ||
|   | 4f15452fe2 | ||
|   | 648fe837f5 | ||
|   | 5cdaae0a7f | ||
|   | 1a75faaf4f | ||
|   | 563396031f | 
					 23 changed files with 2309 additions and 368 deletions
				
			
		|  | @ -128,5 +128,8 @@ public class JsonUtils | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="obj"></param> |     /// <param name="obj"></param> | ||||||
|     /// <returns></returns> |     /// <returns></returns> | ||||||
|     public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); |     public static JsonNode? SerializeToNode(object? obj, JsonSerializerOptions? options = null) | ||||||
|  |     { | ||||||
|  |         return JsonSerializer.SerializeToNode(obj, options); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -76,6 +76,13 @@ public class Global | ||||||
|     public const int SpeedTestPageSize = 1000; |     public const int SpeedTestPageSize = 1000; | ||||||
|     public const string LinuxBash = "/bin/bash"; |     public const string LinuxBash = "/bin/bash"; | ||||||
| 
 | 
 | ||||||
|  |     public const string SingboxDirectDNSTag = "direct_dns"; | ||||||
|  |     public const string SingboxRemoteDNSTag = "remote_dns"; | ||||||
|  |     public const string SingboxOutboundResolverTag = "outbound_resolver"; | ||||||
|  |     public const string SingboxFinalResolverTag = "final_resolver"; | ||||||
|  |     public const string SingboxHostsDNSTag = "hosts_dns"; | ||||||
|  |     public const string SingboxFakeDNSTag = "fake_dns"; | ||||||
|  | 
 | ||||||
|     public static readonly List<string> IEProxyProtocols = |     public static readonly List<string> IEProxyProtocols = | ||||||
|     [ |     [ | ||||||
|         "{ip}:{http_port}", |         "{ip}:{http_port}", | ||||||
|  | @ -351,25 +358,42 @@ public class Global | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> SingboxDomainStrategy4Out = |     public static readonly List<string> SingboxDomainStrategy4Out = | ||||||
|     [ |     [ | ||||||
|  |         "", | ||||||
|             "ipv4_only", |             "ipv4_only", | ||||||
|             "prefer_ipv4", |             "prefer_ipv4", | ||||||
|             "prefer_ipv6", |             "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.5.5.5", | ||||||
|             "223.6.6.6", |             "119.29.29.29", | ||||||
|             "localhost" |             "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.5.5.5", | ||||||
|             "223.6.6.6", |             "119.29.29.29", | ||||||
|             "dhcp://auto" |             "localhost" | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> Languages = |     public static readonly List<string> Languages = | ||||||
|  | @ -539,5 +563,30 @@ public class Global | ||||||
|         BlockTag |         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" } } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |     public static readonly List<string> ExpectedIPs = | ||||||
|  |     [ | ||||||
|  |         "geoip:cn", | ||||||
|  |             "geoip:ir", | ||||||
|  |             "geoip:ru", | ||||||
|  |             "" | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|     #endregion const |     #endregion const | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -112,6 +112,11 @@ public class ConfigHandler | ||||||
| 
 | 
 | ||||||
|         config.ConstItem ??= new ConstItem(); |         config.ConstItem ??= new ConstItem(); | ||||||
| 
 | 
 | ||||||
|  |         if (config.SimpleDNSItem == null) | ||||||
|  |         { | ||||||
|  |             InitBuiltinSimpleDNS(config); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         config.SpeedTestItem ??= new(); |         config.SpeedTestItem ??= new(); | ||||||
|         if (config.SpeedTestItem.SpeedTestTimeout < 10) |         if (config.SpeedTestItem.SpeedTestTimeout < 10) | ||||||
|         { |         { | ||||||
|  | @ -2094,18 +2099,38 @@ public class ConfigHandler | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Initialize built-in DNS configurations |     /// Initialize built-in DNS configurations | ||||||
|     /// Creates default DNS items for V2Ray and sing-box |     /// Creates default DNS items for V2Ray and sing-box | ||||||
|  |     /// Also checks existing DNS items and disables those with empty NormalDNS | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="config">Current configuration</param> |     /// <param name="config">Current configuration</param> | ||||||
|     /// <returns>0 if successful</returns> |     /// <returns>0 if successful</returns> | ||||||
|     public static async Task<int> InitBuiltinDNS(Config config) |     public static async Task<int> InitBuiltinDNS(Config config) | ||||||
|     { |     { | ||||||
|         var items = await AppHandler.Instance.DNSItems(); |         var items = await AppHandler.Instance.DNSItems(); | ||||||
|  |          | ||||||
|  |         // Check existing DNS items and disable those with empty NormalDNS | ||||||
|  |         var needsUpdate = false; | ||||||
|  |         foreach (var existingItem in items) | ||||||
|  |         { | ||||||
|  |             if (existingItem.NormalDNS.IsNullOrEmpty() && existingItem.Enabled) | ||||||
|  |             { | ||||||
|  |                 existingItem.Enabled = false; | ||||||
|  |                 needsUpdate = true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // Update items if any changes were made | ||||||
|  |         if (needsUpdate) | ||||||
|  |         { | ||||||
|  |             await SQLiteHelper.Instance.UpdateAllAsync(items); | ||||||
|  |         } | ||||||
|  |          | ||||||
|         if (items.Count <= 0) |         if (items.Count <= 0) | ||||||
|         { |         { | ||||||
|             var item = new DNSItem() |             var item = new DNSItem() | ||||||
|             { |             { | ||||||
|                 Remarks = "V2ray", |                 Remarks = "V2ray", | ||||||
|                 CoreType = ECoreType.Xray, |                 CoreType = ECoreType.Xray, | ||||||
|  |                 Enabled = false, | ||||||
|             }; |             }; | ||||||
|             await SaveDNSItems(config, item); |             await SaveDNSItems(config, item); | ||||||
| 
 | 
 | ||||||
|  | @ -2113,6 +2138,7 @@ public class ConfigHandler | ||||||
|             { |             { | ||||||
|                 Remarks = "sing-box", |                 Remarks = "sing-box", | ||||||
|                 CoreType = ECoreType.sing_box, |                 CoreType = ECoreType.sing_box, | ||||||
|  |                 Enabled = false, | ||||||
|             }; |             }; | ||||||
|             await SaveDNSItems(config, item2); |             await SaveDNSItems(config, item2); | ||||||
|         } |         } | ||||||
|  | @ -2184,6 +2210,38 @@ public class ConfigHandler | ||||||
| 
 | 
 | ||||||
|     #endregion DNS |     #endregion DNS | ||||||
| 
 | 
 | ||||||
|  |     #region Simple DNS | ||||||
|  | 
 | ||||||
|  |     public static int InitBuiltinSimpleDNS(Config config) | ||||||
|  |     { | ||||||
|  |         config.SimpleDNSItem = new SimpleDNSItem() | ||||||
|  |         { | ||||||
|  |             UseSystemHosts = false, | ||||||
|  |             AddCommonHosts = true, | ||||||
|  |             FakeIP = false, | ||||||
|  |             BlockBindingQuery = true, | ||||||
|  |             DirectDNS = Global.DomainDirectDNSAddress.FirstOrDefault(), | ||||||
|  |             RemoteDNS = Global.DomainRemoteDNSAddress.FirstOrDefault(), | ||||||
|  |             SingboxOutboundsResolveDNS = Global.DomainDirectDNSAddress.FirstOrDefault(), | ||||||
|  |             SingboxFinalResolveDNS = Global.DomainPureIPDNSAddress.FirstOrDefault() | ||||||
|  |         }; | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static async Task<SimpleDNSItem> GetExternalSimpleDNSItem(string url) | ||||||
|  |     { | ||||||
|  |         var downloadHandle = new DownloadService(); | ||||||
|  |         var templateContent = await downloadHandle.TryDownloadString(url, true, ""); | ||||||
|  |         if (templateContent.IsNullOrEmpty()) | ||||||
|  |             return null; | ||||||
|  |         var template = JsonUtils.Deserialize<SimpleDNSItem>(templateContent); | ||||||
|  |         if (template == null) | ||||||
|  |             return null; | ||||||
|  |         return template; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #endregion Simple DNS | ||||||
|  | 
 | ||||||
|     #region Custom Config |     #region Custom Config | ||||||
| 
 | 
 | ||||||
|     public static async Task<int> InitBuiltinCustomConfig(Config config) |     public static async Task<int> InitBuiltinCustomConfig(Config config) | ||||||
|  | @ -2253,6 +2311,8 @@ public class ConfigHandler | ||||||
|                 await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>(); |                 await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>(); | ||||||
|                 await InitBuiltinDNS(config); |                 await InitBuiltinDNS(config); | ||||||
| 
 | 
 | ||||||
|  |                 InitBuiltinSimpleDNS(config); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             case EPresetType.Russia: |             case EPresetType.Russia: | ||||||
|  | @ -2263,6 +2323,8 @@ public class ConfigHandler | ||||||
|                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.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")); |                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); | ||||||
| 
 | 
 | ||||||
|  |                 config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[1] + "simple_dns.json"); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             case EPresetType.Iran: |             case EPresetType.Iran: | ||||||
|  | @ -2273,6 +2335,8 @@ public class ConfigHandler | ||||||
|                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.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")); |                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json")); | ||||||
| 
 | 
 | ||||||
|  |                 config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[2] + "simple_dns.json"); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,8 @@ public class CoreHandler | ||||||
|         Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); |         Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); | ||||||
|         Environment.SetEnvironmentVariable(Global.XrayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); |         Environment.SetEnvironmentVariable(Global.XrayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); | ||||||
|         Environment.SetEnvironmentVariable(Global.XrayLocalCert, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); |         Environment.SetEnvironmentVariable(Global.XrayLocalCert, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); | ||||||
|  |         // TODO Temporary addition to support proper use of sing-box v1.12 | ||||||
|  |         Environment.SetEnvironmentVariable("ENABLE_DEPRECATED_SPECIAL_OUTBOUNDS", "true", EnvironmentVariableTarget.Process); | ||||||
| 
 | 
 | ||||||
|         //Copy the bin folder to the storage location (for init) |         //Copy the bin folder to the storage location (for init) | ||||||
|         if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1") |         if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1") | ||||||
|  |  | ||||||
|  | @ -48,6 +48,7 @@ public class Config | ||||||
|     public List<InItem> Inbound { get; set; } |     public List<InItem> Inbound { get; set; } | ||||||
|     public List<KeyEventItem> GlobalHotkeys { get; set; } |     public List<KeyEventItem> GlobalHotkeys { get; set; } | ||||||
|     public List<CoreTypeItem> CoreTypeItem { get; set; } |     public List<CoreTypeItem> CoreTypeItem { get; set; } | ||||||
|  |     public SimpleDNSItem SimpleDNSItem { get; set; } | ||||||
| 
 | 
 | ||||||
|     #endregion other entities |     #endregion other entities | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -253,3 +253,21 @@ public class WindowSizeItem | ||||||
|     public int Width { get; set; } |     public int Width { get; set; } | ||||||
|     public int Height { get; set; } |     public int Height { get; set; } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | [Serializable] | ||||||
|  | public class SimpleDNSItem | ||||||
|  | { | ||||||
|  |     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; } | ||||||
|  |     public string? DirectExpectedIPs { get; set; } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ public class DNSItem | ||||||
|     public string Id { get; set; } |     public string Id { get; set; } | ||||||
| 
 | 
 | ||||||
|     public string Remarks { get; set; } |     public string Remarks { get; set; } | ||||||
|     public bool Enabled { get; set; } = true; |     public bool Enabled { get; set; } = false; | ||||||
|     public ECoreType CoreType { get; set; } |     public ECoreType CoreType { get; set; } | ||||||
|     public bool UseSystemHosts { get; set; } |     public bool UseSystemHosts { get; set; } | ||||||
|     public string? NormalDNS { get; set; } |     public string? NormalDNS { get; set; } | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ public class Dns4Sbox | ||||||
| 
 | 
 | ||||||
| public class Route4Sbox | public class Route4Sbox | ||||||
| { | { | ||||||
|  |     public Rule4Sbox? default_domain_resolver { get; set; } // or string | ||||||
|     public bool? auto_detect_interface { get; set; } |     public bool? auto_detect_interface { get; set; } | ||||||
|     public List<Rule4Sbox> rules { get; set; } |     public List<Rule4Sbox> rules { get; set; } | ||||||
|     public List<Ruleset4Sbox>? rule_set { get; set; } |     public List<Ruleset4Sbox>? rule_set { get; set; } | ||||||
|  | @ -75,7 +76,7 @@ public class Rule4Sbox | ||||||
|     public string? strategy { get; set; } |     public string? strategy { get; set; } | ||||||
|     public List<string>? sniffer { get; set; } |     public List<string>? sniffer { get; set; } | ||||||
|     public string? rcode { 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>? answer { get; set; } | ||||||
|     public List<string>? ns { get; set; } |     public List<string>? ns { get; set; } | ||||||
|     public List<string>? extra { get; set; } |     public List<string>? extra { get; set; } | ||||||
|  | @ -237,7 +238,7 @@ public class Server4Sbox : BaseServer4Sbox | ||||||
|     public string? path { get; set; } |     public string? path { get; set; } | ||||||
|     public Headers4Sbox? headers { get; set; } |     public Headers4Sbox? headers { get; set; } | ||||||
|     // public List<string>? path { get; set; } // hosts |     // public List<string>? path { get; set; } // hosts | ||||||
|     public Dictionary<string, object>? predefined { get; set; } |     public Dictionary<string, List<string>>? predefined { get; set; } | ||||||
|     // Deprecated |     // Deprecated | ||||||
|     public string? address { get; set; } |     public string? address { get; set; } | ||||||
|     public string? address_resolver { get; set; } |     public string? address_resolver { get; set; } | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ namespace ServiceLib.Models; | ||||||
| public class V2rayConfig | public class V2rayConfig | ||||||
| { | { | ||||||
|     public Log4Ray log { get; set; } |     public Log4Ray log { get; set; } | ||||||
|     public object dns { get; set; } |     public Dns4Ray dns { get; set; } | ||||||
|     public List<Inbounds4Ray> inbounds { get; set; } |     public List<Inbounds4Ray> inbounds { get; set; } | ||||||
|     public List<Outbounds4Ray> outbounds { get; set; } |     public List<Outbounds4Ray> outbounds { get; set; } | ||||||
|     public Routing4Ray routing { get; set; } |     public Routing4Ray routing { get; set; } | ||||||
|  | @ -203,7 +203,8 @@ public class Response4Ray | ||||||
| 
 | 
 | ||||||
| public class Dns4Ray | 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 | public class DnsServer4Ray | ||||||
|  | @ -211,6 +212,8 @@ public class DnsServer4Ray | ||||||
|     public string? address { get; set; } |     public string? address { get; set; } | ||||||
|     public List<string>? domains { get; set; } |     public List<string>? domains { get; set; } | ||||||
|     public bool? skipFallback { get; set; } |     public bool? skipFallback { get; set; } | ||||||
|  |     public List<string>? expectedIPs { get; set; } | ||||||
|  |     public List<string>? unexpectedIPs { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class Routing4Ray | public class Routing4Ray | ||||||
|  |  | ||||||
							
								
								
									
										119
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										119
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							|  | @ -1,4 +1,4 @@ | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // <auto-generated> | // <auto-generated> | ||||||
| //     此代码由工具生成。 | //     此代码由工具生成。 | ||||||
| //     运行时版本:4.0.30319.42000 | //     运行时版本:4.0.30319.42000 | ||||||
|  | @ -2238,6 +2238,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Add Common DNS Hosts 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbAddCommonDNSHosts { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbAddCommonDNSHosts", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Do Not Add Non-Proxy Protocol Outbound 的本地化字符串。 |         ///   查找类似 Do Not Add Non-Proxy Protocol Outbound 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2283,6 +2292,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Apply to Proxy Domains Only 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbApplyProxyDomainsOnly { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbApplyProxyDomainsOnly", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Auto refresh 的本地化字符串。 |         ///   查找类似 Auto refresh 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2310,6 +2328,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Block SVCB and HTTPS Queries 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbBlockSVCBHTTPSQueries { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbBlockSVCBHTTPSQueries", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Browse 的本地化字符串。 |         ///   查找类似 Browse 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2418,6 +2445,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 DNS Hosts: ("domain1 ip1 ip2" per line) 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbDNSHostsConfig { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbDNSHostsConfig", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。 |         ///   查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2463,6 +2499,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Domestic DNS 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbDomesticDNS { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbDomesticDNS", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Edit 的本地化字符串。 |         ///   查找类似 Edit 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2481,6 +2526,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 FakeIP 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbFakeIP { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbFakeIP", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Fingerprint 的本地化字符串。 |         ///   查找类似 Fingerprint 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2679,6 +2733,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Prevent DNS Leaks 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbPreventDNSLeaks { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbPreventDNSLeaks", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Private Key 的本地化字符串。 |         ///   查找类似 Private Key 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2733,6 +2796,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Remote DNS 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbRemoteDNS { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbRemoteDNS", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Camouflage domain(host) 的本地化字符串。 |         ///   查找类似 Camouflage domain(host) 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -3867,6 +3939,33 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Validate Regional Domain IPs 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbValidateDirectExpectedIPs { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbValidateDirectExpectedIPs", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbValidateDirectExpectedIPsDesc { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbValidateDirectExpectedIPsDesc", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 xray Freedom Resolution Strategy 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbXrayFreedomResolveStrategy { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbXrayFreedomResolveStrategy", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 The delay: {0} ms, {1} 的本地化字符串。 |         ///   查找类似 The delay: {0} ms, {1} 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -3876,6 +3975,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> |         /// <summary> | ||||||
|         ///   查找类似 Active 的本地化字符串。 |         ///   查找类似 Active 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  |  | ||||||
|  | @ -1404,6 +1404,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>Add [Anytls] Configuration</value> |     <value>Add [Anytls] Configuration</value> | ||||||
|   </data> |   </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>The sing-box DoH resolution server can be overwritten</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>Validate Regional Domain IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>Custom DNS Enabled, This Page's Settings Invalid</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>Custom Config</value> |     <value>Custom Config</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -1404,6 +1404,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>[Anytls] konfiguráció hozzáadása</value> |     <value>[Anytls] konfiguráció hozzáadása</value> | ||||||
|   </data> |   </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>The sing-box DoH resolution server can be overwritten</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>Validate Regional Domain IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>Custom DNS Enabled, This Page's Settings Invalid</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>Custom Config</value> |     <value>Custom Config</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -1404,6 +1404,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>Add [Anytls] Configuration</value> |     <value>Add [Anytls] Configuration</value> | ||||||
|   </data> |   </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>The sing-box DoH resolution server can be overwritten</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>Validate Regional Domain IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>Custom DNS Enabled, This Page's Settings Invalid</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>Custom Config</value> |     <value>Custom Config</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -807,9 +807,6 @@ | ||||||
|   <data name="menuMoveUp" xml:space="preserve"> |   <data name="menuMoveUp" xml:space="preserve"> | ||||||
|     <value>Вверх (U)</value> |     <value>Вверх (U)</value> | ||||||
|   </data> |   </data> | ||||||
|   <data name="menuMoveTo" xml:space="preserve"> |  | ||||||
|     <value>Переместить вверх/вниз</value> |  | ||||||
|   </data> |  | ||||||
|   <data name="MsgFilterTitle" xml:space="preserve"> |   <data name="MsgFilterTitle" xml:space="preserve"> | ||||||
|     <value>Фильтр, поддерживает regex</value> |     <value>Фильтр, поддерживает regex</value> | ||||||
|   </data> |   </data> | ||||||
|  | @ -969,6 +966,9 @@ | ||||||
|   <data name="TbSettingsSpeedTestUrl" xml:space="preserve"> |   <data name="TbSettingsSpeedTestUrl" xml:space="preserve"> | ||||||
|     <value>URL для тестирования скорости</value> |     <value>URL для тестирования скорости</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="menuMoveTo" xml:space="preserve"> | ||||||
|  |     <value>Переместить вверх/вниз</value> | ||||||
|  |   </data> | ||||||
|   <data name="TbPublicKey" xml:space="preserve"> |   <data name="TbPublicKey" xml:space="preserve"> | ||||||
|     <value>PublicKey</value> |     <value>PublicKey</value> | ||||||
|   </data> |   </data> | ||||||
|  | @ -1404,6 +1404,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>Добавить сервер [Anytls]</value> |     <value>Добавить сервер [Anytls]</value> | ||||||
|   </data> |   </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>The sing-box DoH resolution server can be overwritten</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>Validate Regional Domain IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>Custom DNS Enabled, This Page's Settings Invalid</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>Custom Config</value> |     <value>Custom Config</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -1401,6 +1401,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>添加 [Anytls] 配置文件</value> |     <value>添加 [Anytls] 配置文件</value> | ||||||
|   </data> |   </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 解析(sing-box)</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>校验相应地区域名 IP</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>配置后,会对相应地区域名(如 geosite:cn)的返回 IP 进行校验,仅返回期望 IP</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>启用自定义 DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>自定义 DNS 已启用,此页面配置将无效</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>请填写正确的自定义配置</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>自定义配置</value> |     <value>自定义配置</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -1401,6 +1401,75 @@ | ||||||
|   <data name="menuAddAnytlsServer" xml:space="preserve"> |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|     <value>新增 [Anytls] 設定檔</value> |     <value>新增 [Anytls] 設定檔</value> | ||||||
|   </data> |   </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>The sing-box DoH resolution server can be overwritten</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> | ||||||
|  |   <data name="TbValidateDirectExpectedIPs" xml:space="preserve"> | ||||||
|  |     <value>Validate Regional Domain IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve"> | ||||||
|  |     <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom DNS</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve"> | ||||||
|  |     <value>Custom DNS Enabled, This Page's Settings Invalid</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|   <data name="menuCustomConfig" xml:space="preserve"> |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|     <value>Custom Config</value> |     <value>Custom Config</value> | ||||||
|   </data> |   </data> | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | using System.Collections.Generic; | ||||||
| using System.Data; | using System.Data; | ||||||
| using System.Net; | using System.Net; | ||||||
| using System.Net.NetworkInformation; | using System.Net.NetworkInformation; | ||||||
|  | @ -75,7 +76,7 @@ public class CoreConfigSingboxService | ||||||
| 
 | 
 | ||||||
|             await GenRouting(singboxConfig); |             await GenRouting(singboxConfig); | ||||||
| 
 | 
 | ||||||
|             await GenDns(node, singboxConfig); |             await GenDns(singboxConfig); | ||||||
| 
 | 
 | ||||||
|             await GenExperimental(singboxConfig); |             await GenExperimental(singboxConfig); | ||||||
| 
 | 
 | ||||||
|  | @ -247,20 +248,20 @@ public class CoreConfigSingboxService | ||||||
|                 singboxConfig.route.rules.Add(rule); |                 singboxConfig.route.rules.Add(rule); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             await GenDnsDomains(null, singboxConfig, null); |             var rawDNSItem = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|             //var dnsServer = singboxConfig.dns?.servers.FirstOrDefault(); |             if (rawDNSItem != null && rawDNSItem.Enabled == true) | ||||||
|             //if (dnsServer != null) |             { | ||||||
|             //{ |                 await GenDnsDomainsCompatible(singboxConfig, rawDNSItem); | ||||||
|             //    dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound; |             } | ||||||
|             //} |             else | ||||||
|             //var dnsRule = singboxConfig.dns?.rules.Where(t => t.outbound != null).FirstOrDefault(); |             { | ||||||
|             //if (dnsRule != null) |                 await GenDnsDomains(singboxConfig, _config.SimpleDNSItem); | ||||||
|             //{ |             } | ||||||
|             //    singboxConfig.dns.rules = []; |             singboxConfig.route.default_domain_resolver = new() | ||||||
|             //    singboxConfig.dns.rules.Add(dnsRule); |             { | ||||||
|             //} |                 server = Global.SingboxFinalResolverTag | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|             //ret.Msg =string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); |  | ||||||
|             ret.Success = true; |             ret.Success = true; | ||||||
|             ret.Data = JsonUtils.Serialize(singboxConfig); |             ret.Data = JsonUtils.Serialize(singboxConfig); | ||||||
|             return ret; |             return ret; | ||||||
|  | @ -319,7 +320,19 @@ public class CoreConfigSingboxService | ||||||
|                 await GenOutbound(node, singboxConfig.outbounds.First()); |                 await GenOutbound(node, singboxConfig.outbounds.First()); | ||||||
|             } |             } | ||||||
|             await GenMoreOutbounds(node, singboxConfig); |             await GenMoreOutbounds(node, singboxConfig); | ||||||
|             await GenDnsDomains(null, singboxConfig, null); |             var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|  |             if (item != null && item.Enabled == true) | ||||||
|  |             { | ||||||
|  |                 await GenDnsDomainsCompatible(singboxConfig, item); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 await GenDnsDomains(singboxConfig, _config.SimpleDNSItem); | ||||||
|  |             } | ||||||
|  |             singboxConfig.route.default_domain_resolver = new() | ||||||
|  |             { | ||||||
|  |                 server = Global.SingboxFinalResolverTag | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|             singboxConfig.route.rules.Clear(); |             singboxConfig.route.rules.Clear(); | ||||||
|             singboxConfig.inbounds.Clear(); |             singboxConfig.inbounds.Clear(); | ||||||
|  | @ -421,7 +434,7 @@ public class CoreConfigSingboxService | ||||||
|             } |             } | ||||||
|             await GenOutboundsList(proxyProfiles, singboxConfig); |             await GenOutboundsList(proxyProfiles, singboxConfig); | ||||||
| 
 | 
 | ||||||
|             await GenDns(null, singboxConfig); |             await GenDns(singboxConfig); | ||||||
|             await ConvertGeo2Ruleset(singboxConfig); |             await ConvertGeo2Ruleset(singboxConfig); | ||||||
| 
 | 
 | ||||||
|             ret.Success = true; |             ret.Success = true; | ||||||
|  | @ -654,17 +667,6 @@ public class CoreConfigSingboxService | ||||||
|             outbound.server_port = node.Port; |             outbound.server_port = node.Port; | ||||||
|             outbound.type = Global.ProtocolTypes[node.ConfigType]; |             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) |             switch (node.ConfigType) | ||||||
|             { |             { | ||||||
|                 case EConfigType.VMess: |                 case EConfigType.VMess: | ||||||
|  | @ -799,17 +801,6 @@ public class CoreConfigSingboxService | ||||||
|             endpoint.address = Utils.String2List(node.RequestHost); |             endpoint.address = Utils.String2List(node.RequestHost); | ||||||
|             endpoint.type = Global.ProtocolTypes[node.ConfigType]; |             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) |             switch (node.ConfigType) | ||||||
|             { |             { | ||||||
|                 case EConfigType.WireGuard: |                 case EConfigType.WireGuard: | ||||||
|  | @ -1256,6 +1247,22 @@ public class CoreConfigSingboxService | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             singboxConfig.route.final = Global.ProxyTag; |             singboxConfig.route.final = Global.ProxyTag; | ||||||
|  |             var item = _config.SimpleDNSItem; | ||||||
|  | 
 | ||||||
|  |             var defaultDomainResolverTag = Global.SingboxOutboundResolverTag; | ||||||
|  |             var directDNSStrategy = item.SingboxStrategy4Direct.IsNullOrEmpty() ? Global.SingboxDomainStrategy4Out.FirstOrDefault() : item.SingboxStrategy4Direct; | ||||||
|  | 
 | ||||||
|  |             var rawDNSItem = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|  |             if (rawDNSItem != null && rawDNSItem.Enabled == true) | ||||||
|  |             { | ||||||
|  |                 defaultDomainResolverTag = Global.SingboxFinalResolverTag; | ||||||
|  |                 directDNSStrategy = rawDNSItem.DomainStrategy4Freedom.IsNullOrEmpty() ? Global.SingboxDomainStrategy4Out.FirstOrDefault() : rawDNSItem.DomainStrategy4Freedom; | ||||||
|  |             } | ||||||
|  |             singboxConfig.route.default_domain_resolver = new() | ||||||
|  |             { | ||||||
|  |                 server = defaultDomainResolverTag, | ||||||
|  |                 strategy = directDNSStrategy | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|             if (_config.TunModeItem.EnableTun) |             if (_config.TunModeItem.EnableTun) | ||||||
|             { |             { | ||||||
|  | @ -1336,14 +1343,14 @@ public class CoreConfigSingboxService | ||||||
|             if (routing != null) |             if (routing != null) | ||||||
|             { |             { | ||||||
|                 var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet); |                 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); |                         await GenRoutingUserRule(item1, singboxConfig); | ||||||
|                         if (item.Ip != null && item.Ip.Count > 0) |                         if (item1.Ip != null && item1.Ip.Count > 0) | ||||||
|                         { |                         { | ||||||
|                             ipRules.Add(item); |                             ipRules.Add(item1); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -1351,9 +1358,9 @@ public class CoreConfigSingboxService | ||||||
|             if (_config.RoutingBasicItem.DomainStrategy == "IPIfNonMatch") |             if (_config.RoutingBasicItem.DomainStrategy == "IPIfNonMatch") | ||||||
|             { |             { | ||||||
|                 singboxConfig.route.rules.Add(resolveRule); |                 singboxConfig.route.rules.Add(resolveRule); | ||||||
|                 foreach (var item in ipRules) |                 foreach (var item2 in ipRules) | ||||||
|                 { |                 { | ||||||
|                     await GenRoutingUserRule(item, singboxConfig); |                     await GenRoutingUserRule(item2, singboxConfig); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -1596,7 +1603,278 @@ public class CoreConfigSingboxService | ||||||
|         return server.tag; |         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); | ||||||
|  |             if (item != null && item.Enabled == true) | ||||||
|  |             { | ||||||
|  |                 return await GenDnsCompatible(singboxConfig); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var simpleDNSItem = _config.SimpleDNSItem; | ||||||
|  |             await GenDnsServers(singboxConfig, simpleDNSItem); | ||||||
|  |             await GenDnsRules(singboxConfig, simpleDNSItem); | ||||||
|  | 
 | ||||||
|  |             singboxConfig.dns ??= new Dns4Sbox(); | ||||||
|  |             singboxConfig.dns.independent_cache = true; | ||||||
|  | 
 | ||||||
|  |             var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|  |             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); | ||||||
|  |             } | ||||||
|  |             singboxConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag; | ||||||
|  |         } | ||||||
|  |         catch (Exception ex) | ||||||
|  |         { | ||||||
|  |             Logging.SaveLog(_tag, ex); | ||||||
|  |         } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsServers(SingboxConfig singboxConfig, SimpleDNSItem simpleDNSItem) | ||||||
|  |     { | ||||||
|  |         var finalDns = await GenDnsDomains(singboxConfig, simpleDNSItem); | ||||||
|  | 
 | ||||||
|  |         var directDns = ParseDnsAddress(simpleDNSItem.DirectDNS); | ||||||
|  |         directDns.tag = Global.SingboxDirectDNSTag; | ||||||
|  |         directDns.domain_resolver = Global.SingboxFinalResolverTag; | ||||||
|  | 
 | ||||||
|  |         var remoteDns = ParseDnsAddress(simpleDNSItem.RemoteDNS); | ||||||
|  |         remoteDns.tag = Global.SingboxRemoteDNSTag; | ||||||
|  |         remoteDns.detour = Global.ProxyTag; | ||||||
|  |         remoteDns.domain_resolver = Global.SingboxFinalResolverTag; | ||||||
|  | 
 | ||||||
|  |         var resolverDns = ParseDnsAddress(simpleDNSItem.SingboxOutboundsResolveDNS); | ||||||
|  |         resolverDns.tag = Global.SingboxOutboundResolverTag; | ||||||
|  |         resolverDns.domain_resolver = Global.SingboxFinalResolverTag; | ||||||
|  | 
 | ||||||
|  |         var hostsDns = new Server4Sbox | ||||||
|  |         { | ||||||
|  |             tag = Global.SingboxHostsDNSTag, | ||||||
|  |             type = "hosts", | ||||||
|  |         }; | ||||||
|  |         if (simpleDNSItem.AddCommonHosts == true) | ||||||
|  |         { | ||||||
|  |             hostsDns.predefined = Global.PredefinedHosts; | ||||||
|  |         } | ||||||
|  |         var userHostsMap = simpleDNSItem.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) | ||||||
|  |             { | ||||||
|  |                 hostsDns.predefined[kvp.Key] = kvp.Value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         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 (resolverDns.server == host.Key) | ||||||
|  |             { | ||||||
|  |                 resolverDns.domain_resolver = Global.SingboxHostsDNSTag; | ||||||
|  |             } | ||||||
|  |             if (directDns.server == host.Key) | ||||||
|  |             { | ||||||
|  |                 directDns.domain_resolver = Global.SingboxHostsDNSTag; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         singboxConfig.dns ??= new Dns4Sbox(); | ||||||
|  |         singboxConfig.dns.servers ??= new List<Server4Sbox>(); | ||||||
|  |         singboxConfig.dns.servers.Add(remoteDns); | ||||||
|  |         singboxConfig.dns.servers.Add(directDns); | ||||||
|  |         singboxConfig.dns.servers.Add(resolverDns); | ||||||
|  |         singboxConfig.dns.servers.Add(hostsDns); | ||||||
|  | 
 | ||||||
|  |         // fake ip | ||||||
|  |         if (simpleDNSItem.FakeIP == true) | ||||||
|  |         { | ||||||
|  |             var fakeip = new Server4Sbox | ||||||
|  |             { | ||||||
|  |                 tag = Global.SingboxFakeDNSTag, | ||||||
|  |                 type = "fakeip", | ||||||
|  |                 inet4_range = "198.18.0.0/15", | ||||||
|  |                 inet6_range = "fc00::/18", | ||||||
|  |             }; | ||||||
|  |             singboxConfig.dns.servers.Add(fakeip); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return await Task.FromResult(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<Server4Sbox> GenDnsDomains(SingboxConfig singboxConfig, SimpleDNSItem? simpleDNSItem) | ||||||
|  |     { | ||||||
|  |         var finalDns = ParseDnsAddress(simpleDNSItem.SingboxFinalResolveDNS); | ||||||
|  |         finalDns.tag = Global.SingboxFinalResolverTag; | ||||||
|  |         singboxConfig.dns ??= new Dns4Sbox(); | ||||||
|  |         singboxConfig.dns.servers ??= new List<Server4Sbox>(); | ||||||
|  |         singboxConfig.dns.servers.Add(finalDns); | ||||||
|  |         return await Task.FromResult(finalDns); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsRules(SingboxConfig singboxConfig, SimpleDNSItem simpleDNSItem) | ||||||
|  |     { | ||||||
|  |         singboxConfig.dns ??= new Dns4Sbox(); | ||||||
|  |         singboxConfig.dns.rules ??= new List<Rule4Sbox>(); | ||||||
|  | 
 | ||||||
|  |         singboxConfig.dns.rules.AddRange(new[] | ||||||
|  |             { | ||||||
|  |             new Rule4Sbox { ip_accept_any = true, server = Global.SingboxHostsDNSTag }, | ||||||
|  |             new Rule4Sbox | ||||||
|  |             { | ||||||
|  |                 server = Global.SingboxRemoteDNSTag, | ||||||
|  |                 strategy = simpleDNSItem.SingboxStrategy4Proxy.IsNullOrEmpty() ? null : simpleDNSItem.SingboxStrategy4Proxy, | ||||||
|  |                 clash_mode = ERuleMode.Global.ToString() | ||||||
|  |             }, | ||||||
|  |             new Rule4Sbox | ||||||
|  |             { | ||||||
|  |                 server = Global.SingboxDirectDNSTag, | ||||||
|  |                 strategy = simpleDNSItem.SingboxStrategy4Direct.IsNullOrEmpty() ? null : simpleDNSItem.SingboxStrategy4Direct, | ||||||
|  |                 clash_mode = ERuleMode.Direct.ToString() | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         if (simpleDNSItem.BlockBindingQuery == true) | ||||||
|  |         { | ||||||
|  |             singboxConfig.dns.rules.Add(new() | ||||||
|  |             { | ||||||
|  |                 query_type = new List<int> { 64, 65 }, | ||||||
|  |                 action = "predefined", | ||||||
|  |                 rcode = "NOTIMP" | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|  |         if (routing == null) | ||||||
|  |             return 0; | ||||||
|  | 
 | ||||||
|  |         var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? []; | ||||||
|  |         var expectedIPCidr = new List<string>(); | ||||||
|  |         var expectedIPsRegions = new List<string>(); | ||||||
|  |         var regionNames = new HashSet<string>(); | ||||||
|  | 
 | ||||||
|  |         if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs)) | ||||||
|  |         { | ||||||
|  |             var ipItems = simpleDNSItem.DirectExpectedIPs | ||||||
|  |                 .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) | ||||||
|  |                 .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; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             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; | ||||||
|  |                 rule.strategy = string.IsNullOrEmpty(simpleDNSItem.SingboxStrategy4Direct) ? null : simpleDNSItem.SingboxStrategy4Direct; | ||||||
|  | 
 | ||||||
|  |                 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.ProxyTag) | ||||||
|  |             { | ||||||
|  |                 if (simpleDNSItem.FakeIP == true) | ||||||
|  |                 { | ||||||
|  |                     var rule4Fake = JsonUtils.DeepCopy(rule); | ||||||
|  |                     rule4Fake.server = Global.SingboxFakeDNSTag; | ||||||
|  |                     singboxConfig.dns.rules.Add(rule4Fake); | ||||||
|  |                 } | ||||||
|  |                 rule.server = Global.SingboxRemoteDNSTag; | ||||||
|  |                 rule.strategy = string.IsNullOrEmpty(simpleDNSItem.SingboxStrategy4Proxy) ? null : simpleDNSItem.SingboxStrategy4Proxy; | ||||||
|  |             } | ||||||
|  |             else if (item.OutboundTag == Global.BlockTag) | ||||||
|  |             { | ||||||
|  |                 rule.action = "predefined"; | ||||||
|  |                 rule.rcode = "NOERROR"; | ||||||
|  |                 rule.answer = new List<string> { "A" }; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             singboxConfig.dns.rules.Add(rule); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsCompatible(SingboxConfig singboxConfig) | ||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|  | @ -1620,11 +1898,11 @@ public class CoreConfigSingboxService | ||||||
| 
 | 
 | ||||||
|             if (dns4Sbox.servers != null && dns4Sbox.servers.Count > 0 && dns4Sbox.servers.First().address.IsNullOrEmpty()) |             if (dns4Sbox.servers != null && dns4Sbox.servers.Count > 0 && dns4Sbox.servers.First().address.IsNullOrEmpty()) | ||||||
|             { |             { | ||||||
|                 await GenDnsDomains(node, singboxConfig, item); |                 await GenDnsDomainsCompatible(singboxConfig, item); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 await GenDnsDomainsLegacy(node, singboxConfig, item); |                 await GenDnsDomainsLegacyCompatible(singboxConfig, item); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|  | @ -1634,86 +1912,35 @@ public class CoreConfigSingboxService | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem) |     private async Task<int> GenDnsDomainsCompatible(SingboxConfig singboxConfig, DNSItem? dNSItem) | ||||||
|     { |     { | ||||||
|         var dns4Sbox = singboxConfig.dns ?? new(); |         var dns4Sbox = singboxConfig.dns ?? new(); | ||||||
|         dns4Sbox.servers ??= []; |         dns4Sbox.servers ??= []; | ||||||
|         dns4Sbox.rules ??= []; |         dns4Sbox.rules ??= []; | ||||||
| 
 | 
 | ||||||
|         var tag = "local_resolver"; |         var tag = Global.SingboxFinalResolverTag; | ||||||
|         var localDnsAddress = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress; |         var localDnsAddress = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress; | ||||||
| 
 | 
 | ||||||
|         if (localDnsAddress.StartsWith("tag://")) |         var localDnsServer = ParseDnsAddress(localDnsAddress); | ||||||
|         { |         localDnsServer.tag = tag; | ||||||
|             tag = localDnsAddress.Substring(6); |  | ||||||
| 
 | 
 | ||||||
|             var localDnsTag = "local_local"; |         dns4Sbox.servers.Add(localDnsServer); | ||||||
| 
 |  | ||||||
|             dns4Sbox.servers.Add(new() |  | ||||||
|             { |  | ||||||
|                 tag = localDnsTag, |  | ||||||
|                 type = "local" |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             dns4Sbox.rules.Insert(0, new() |  | ||||||
|             { |  | ||||||
|                 server = localDnsTag, |  | ||||||
|                 clash_mode = ERuleMode.Direct.ToString() |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             var (dnsType, dnsHost, dnsPort, dnsPath) = ParseDnsAddress(localDnsAddress); |  | ||||||
| 
 |  | ||||||
|             dns4Sbox.servers.Add(new() |  | ||||||
|             { |  | ||||||
|                 tag = tag, |  | ||||||
|                 type = dnsType, |  | ||||||
|                 server = dnsHost, |  | ||||||
|                 Interface = dnsType == "dhcp" ? dnsHost : null, |  | ||||||
|                 server_port = dnsPort, |  | ||||||
|                 path = dnsPath |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             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() |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         //Tun2SocksAddress |  | ||||||
|         if (_config.TunModeItem.EnableTun && node?.ConfigType == EConfigType.SOCKS && Utils.IsDomain(node?.Sni)) |  | ||||||
|         { |  | ||||||
|             dns4Sbox.rules.Insert(0, new() |  | ||||||
|             { |  | ||||||
|                 server = tag, |  | ||||||
|                 domain = [node?.Sni], |  | ||||||
|                 strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         singboxConfig.dns = dns4Sbox; |         singboxConfig.dns = dns4Sbox; | ||||||
|         return await Task.FromResult(0); |         return await Task.FromResult(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<int> GenDnsDomainsLegacy(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem) |     private async Task<int> GenDnsDomainsLegacyCompatible(SingboxConfig singboxConfig, DNSItem? dNSItem) | ||||||
|     { |     { | ||||||
|         var dns4Sbox = singboxConfig.dns ?? new(); |         var dns4Sbox = singboxConfig.dns ?? new(); | ||||||
|         dns4Sbox.servers ??= []; |         dns4Sbox.servers ??= []; | ||||||
|         dns4Sbox.rules ??= []; |         dns4Sbox.rules ??= []; | ||||||
| 
 | 
 | ||||||
|         var tag = "local_local"; |         var tag = Global.SingboxFinalResolverTag; | ||||||
|         dns4Sbox.servers.Add(new() |         dns4Sbox.servers.Add(new() | ||||||
|         { |         { | ||||||
|             tag = tag, |             tag = tag, | ||||||
|             address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, |             address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, | ||||||
|             detour = Global.DirectTag, |             detour = Global.DirectTag, | ||||||
|             strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom, |             strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom, | ||||||
|         }); |         }); | ||||||
|  | @ -1742,103 +1969,100 @@ public class CoreConfigSingboxService | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         //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; |         singboxConfig.dns = dns4Sbox; | ||||||
|         return await Task.FromResult(0); |         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"; |         var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim(); | ||||||
|         string? host = null; |         if (string.IsNullOrEmpty(addressFirst)) | ||||||
|         int? port = null; |  | ||||||
|         string? path = null; |  | ||||||
| 
 |  | ||||||
|         if (address is "local" or "localhost") |  | ||||||
|         { |         { | ||||||
|             return ("local", null, null, null); |             return null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (address.StartsWith("dhcp://", StringComparison.OrdinalIgnoreCase)) |         var server = new Server4Sbox(); | ||||||
|  | 
 | ||||||
|  |         if (addressFirst is "local" or "localhost") | ||||||
|         { |         { | ||||||
|             string interface_name = address.Substring(7); |             server.type = "local"; | ||||||
|             return ("dhcp", interface_name == "auto" ? null : interface_name, null, null); |             return server; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!address.Contains("://")) |         if (addressFirst.StartsWith("dhcp://", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |         { | ||||||
|  |             var interface_name = addressFirst.Substring(7); | ||||||
|  |             server.type = "dhcp"; | ||||||
|  |             server.Interface = interface_name == "auto" ? null : interface_name; | ||||||
|  |             return server; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!addressFirst.Contains("://")) | ||||||
|         { |         { | ||||||
|             // udp dns |             // udp dns | ||||||
|             host = address; |             server.type = "udp"; | ||||||
|             return (type, host, port, path); |             server.server = addressFirst; | ||||||
|  |             return server; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal); |             var protocolEndIndex = addressFirst.IndexOf("://", StringComparison.Ordinal); | ||||||
|             type = address.Substring(0, protocolEndIndex).ToLower(); |             server.type = addressFirst.Substring(0, protocolEndIndex).ToLower(); | ||||||
| 
 | 
 | ||||||
|             var uri = new Uri(address); |             var uri = new Uri(addressFirst); | ||||||
|             host = uri.Host; |             server.server = uri.Host; | ||||||
| 
 | 
 | ||||||
|             if (!uri.IsDefaultPort) |             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) |         catch (UriFormatException) | ||||||
|         { |         { | ||||||
|             int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal); |             var protocolEndIndex = addressFirst.IndexOf("://", StringComparison.Ordinal); | ||||||
|             if (protocolEndIndex > 0) |             if (protocolEndIndex > 0) | ||||||
|             { |             { | ||||||
|                 type = address.Substring(0, protocolEndIndex).ToLower(); |                 server.type = addressFirst.Substring(0, protocolEndIndex).ToLower(); | ||||||
|                 string remaining = address.Substring(protocolEndIndex + 3); |                 var remaining = addressFirst.Substring(protocolEndIndex + 3); | ||||||
| 
 | 
 | ||||||
|                 int portIndex = remaining.IndexOf(':'); |                 var portIndex = remaining.IndexOf(':'); | ||||||
|                 int pathIndex = remaining.IndexOf('/'); |                 var pathIndex = remaining.IndexOf('/'); | ||||||
| 
 | 
 | ||||||
|                 if (portIndex > 0) |                 if (portIndex > 0) | ||||||
|                 { |                 { | ||||||
|                     host = remaining.Substring(0, portIndex); |                     server.server = remaining.Substring(0, portIndex); | ||||||
|                     string portPart = pathIndex > portIndex |                     var portPart = pathIndex > portIndex | ||||||
|                         ? remaining.Substring(portIndex + 1, pathIndex - portIndex - 1) |                         ? remaining.Substring(portIndex + 1, pathIndex - portIndex - 1) | ||||||
|                         : remaining.Substring(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) |                 else if (pathIndex > 0) | ||||||
|                 { |                 { | ||||||
|                     host = remaining.Substring(0, pathIndex); |                     server.server = remaining.Substring(0, pathIndex); | ||||||
|                 } |                 } | ||||||
|                 else |                 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) |     private async Task<int> GenExperimental(SingboxConfig singboxConfig) | ||||||
|  | @ -1858,7 +2082,8 @@ public class CoreConfigSingboxService | ||||||
|             singboxConfig.experimental.cache_file = new CacheFile4Sbox() |             singboxConfig.experimental.cache_file = new CacheFile4Sbox() | ||||||
|             { |             { | ||||||
|                 enabled = true, |                 enabled = true, | ||||||
|                 path = Utils.GetBinPath("cache.db") |                 path = Utils.GetBinPath("cache.db"), | ||||||
|  |                 store_fakeip = _config.SimpleDNSItem.FakeIP == true | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1879,13 +2104,15 @@ public class CoreConfigSingboxService | ||||||
|         //convert route geosite & geoip to ruleset |         //convert route geosite & geoip to ruleset | ||||||
|         foreach (var rule in singboxConfig.route.rules.Where(t => t.geosite?.Count > 0).ToList() ?? []) |         foreach (var rule in singboxConfig.route.rules.Where(t => t.geosite?.Count > 0).ToList() ?? []) | ||||||
|         { |         { | ||||||
|             rule.rule_set = rule?.geosite?.Select(t => $"{geosite}-{t}").ToList(); |             rule.rule_set ??= new List<string>(); | ||||||
|  |             rule.rule_set.AddRange(rule?.geosite?.Select(t => $"{geosite}-{t}").ToList()); | ||||||
|             rule.geosite = null; |             rule.geosite = null; | ||||||
|             AddRuleSets(ruleSets, rule.rule_set); |             AddRuleSets(ruleSets, rule.rule_set); | ||||||
|         } |         } | ||||||
|         foreach (var rule in singboxConfig.route.rules.Where(t => t.geoip?.Count > 0).ToList() ?? []) |         foreach (var rule in singboxConfig.route.rules.Where(t => t.geoip?.Count > 0).ToList() ?? []) | ||||||
|         { |         { | ||||||
|             rule.rule_set = rule?.geoip?.Select(t => $"{geoip}-{t}").ToList(); |             rule.rule_set ??= new List<string>(); | ||||||
|  |             rule.rule_set.AddRange(rule?.geoip?.Select(t => $"{geoip}-{t}").ToList()); | ||||||
|             rule.geoip = null; |             rule.geoip = null; | ||||||
|             AddRuleSets(ruleSets, rule.rule_set); |             AddRuleSets(ruleSets, rule.rule_set); | ||||||
|         } |         } | ||||||
|  | @ -1893,12 +2120,14 @@ public class CoreConfigSingboxService | ||||||
|         //convert dns geosite & geoip to ruleset |         //convert dns geosite & geoip to ruleset | ||||||
|         foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geosite?.Count > 0).ToList() ?? []) |         foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geosite?.Count > 0).ToList() ?? []) | ||||||
|         { |         { | ||||||
|             rule.rule_set = rule?.geosite?.Select(t => $"{geosite}-{t}").ToList(); |             rule.rule_set ??= new List<string>(); | ||||||
|  |             rule.rule_set.AddRange(rule?.geosite?.Select(t => $"{geosite}-{t}").ToList()); | ||||||
|             rule.geosite = null; |             rule.geosite = null; | ||||||
|         } |         } | ||||||
|         foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geoip?.Count > 0).ToList() ?? []) |         foreach (var rule in singboxConfig.dns?.rules.Where(t => t.geoip?.Count > 0).ToList() ?? []) | ||||||
|         { |         { | ||||||
|             rule.rule_set = rule?.geoip?.Select(t => $"{geoip}-{t}").ToList(); |             rule.rule_set ??= new List<string>(); | ||||||
|  |             rule.rule_set.AddRange(rule?.geoip?.Select(t => $"{geoip}-{t}").ToList()); | ||||||
|             rule.geoip = null; |             rule.geoip = null; | ||||||
|         } |         } | ||||||
|         foreach (var dnsRule in singboxConfig.dns?.rules.Where(t => t.rule_set?.Count > 0).ToList() ?? []) |         foreach (var dnsRule in singboxConfig.dns?.rules.Where(t => t.rule_set?.Count > 0).ToList() ?? []) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| using System.Net; | using System.Net; | ||||||
| using System.Net.NetworkInformation; | using System.Net.NetworkInformation; | ||||||
|  | using System.Text.Json; | ||||||
| using System.Text.Json.Nodes; | using System.Text.Json.Nodes; | ||||||
| using System.Text.Json.Serialization; | using System.Text.Json.Serialization; | ||||||
| using ServiceLib.Models; | using ServiceLib.Models; | ||||||
|  | @ -1140,6 +1141,264 @@ public class CoreConfigV2rayService | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig) |     private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig) | ||||||
|  |     { | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|  |             if (item != null && item.Enabled == true) | ||||||
|  |             { | ||||||
|  |                 return await GenDnsCompatible(node, v2rayConfig); | ||||||
|  |             } | ||||||
|  |             var simpleDNSItem = _config.SimpleDNSItem; | ||||||
|  |             var domainStrategy4Freedom = simpleDNSItem?.RayStrategy4Freedom; | ||||||
|  | 
 | ||||||
|  |             //Outbound Freedom domainStrategy | ||||||
|  |             if (domainStrategy4Freedom.IsNotEmpty()) | ||||||
|  |             { | ||||||
|  |                 var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag }); | ||||||
|  |                 if (outbound != null) | ||||||
|  |                 { | ||||||
|  |                     outbound.settings = new() | ||||||
|  |                     { | ||||||
|  |                         domainStrategy = domainStrategy4Freedom, | ||||||
|  |                         userLevel = 0 | ||||||
|  |                     }; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             await GenDnsServers(node, v2rayConfig, simpleDNSItem); | ||||||
|  |             await GenDnsHosts(v2rayConfig, simpleDNSItem); | ||||||
|  |         } | ||||||
|  |         catch (Exception ex) | ||||||
|  |         { | ||||||
|  |             Logging.SaveLog(_tag, ex); | ||||||
|  |         } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsServers(ProfileItem? node, V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem) | ||||||
|  |     { | ||||||
|  |         static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress) | ||||||
|  |         { | ||||||
|  |             var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';') | ||||||
|  |                 .Select(addr => addr.Trim()) | ||||||
|  |                 .Where(addr => !string.IsNullOrEmpty(addr)) | ||||||
|  |                 .Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr) | ||||||
|  |                 .Distinct() | ||||||
|  |                 .ToList() ?? new List<string> { defaultAddress }; | ||||||
|  |             return addresses.Count > 0 ? addresses : new List<string> { defaultAddress }; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         static object CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null) | ||||||
|  |         { | ||||||
|  |             var dnsServer = new DnsServer4Ray | ||||||
|  |             { | ||||||
|  |                 address = dnsAddress, | ||||||
|  |                 skipFallback = true, | ||||||
|  |                 domains = domains.Count > 0 ? domains : null, | ||||||
|  |                 expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null | ||||||
|  |             }; | ||||||
|  |             return JsonUtils.SerializeToNode(dnsServer, new JsonSerializerOptions | ||||||
|  |             { | ||||||
|  |                 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.FirstOrDefault()); | ||||||
|  |         var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.FirstOrDefault()); | ||||||
|  | 
 | ||||||
|  |         var directDomainList = new List<string>(); | ||||||
|  |         var directGeositeList = new List<string>(); | ||||||
|  |         var proxyDomainList = new List<string>(); | ||||||
|  |         var proxyGeositeList = new List<string>(); | ||||||
|  |         var expectedDomainList = new List<string>(); | ||||||
|  |         var expectedIPs = new List<string>(); | ||||||
|  |         var regionNames = new HashSet<string>(); | ||||||
|  | 
 | ||||||
|  |         if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs)) | ||||||
|  |         { | ||||||
|  |             expectedIPs = simpleDNSItem.DirectExpectedIPs | ||||||
|  |                 .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) | ||||||
|  |                 .Select(s => s.Trim()) | ||||||
|  |                 .Where(s => !string.IsNullOrEmpty(s)) | ||||||
|  |                 .ToList(); | ||||||
|  | 
 | ||||||
|  |             foreach (var ip in expectedIPs) | ||||||
|  |             { | ||||||
|  |                 if (ip.StartsWith("geoip:", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                 { | ||||||
|  |                     var region = ip["geoip:".Length..]; | ||||||
|  |                     if (!string.IsNullOrEmpty(region)) | ||||||
|  |                     { | ||||||
|  |                         regionNames.Add($"geosite:{region}"); | ||||||
|  |                         regionNames.Add($"geosite:geolocation-{region}"); | ||||||
|  |                         regionNames.Add($"geosite:tld-{region}"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var routing = await ConfigHandler.GetDefaultRouting(_config); | ||||||
|  |         List<RulesItem>? rules = null; | ||||||
|  |         if (routing != null) | ||||||
|  |         { | ||||||
|  |             rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? []; | ||||||
|  |             foreach (var item in rules) | ||||||
|  |             { | ||||||
|  |                 if (!item.Enabled || item.Domain is null || item.Domain.Count == 0) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 foreach (var domain in item.Domain) | ||||||
|  |                 { | ||||||
|  |                     if (domain.StartsWith('#')) | ||||||
|  |                         continue; | ||||||
|  |                     var normalizedDomain = domain.Replace(Global.RoutingRuleComma, ","); | ||||||
|  | 
 | ||||||
|  |                     if (item.OutboundTag == Global.DirectTag) | ||||||
|  |                     { | ||||||
|  |                         if (normalizedDomain.StartsWith("geosite:")) | ||||||
|  |                         { | ||||||
|  |                             (regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             directDomainList.Add(normalizedDomain); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else if (item.OutboundTag == Global.ProxyTag) | ||||||
|  |                     { | ||||||
|  |                         if (normalizedDomain.StartsWith("geosite:")) | ||||||
|  |                         { | ||||||
|  |                             proxyGeositeList.Add(normalizedDomain); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             proxyDomainList.Add(normalizedDomain); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (Utils.IsDomain(node?.Address)) | ||||||
|  |         { | ||||||
|  |             directDomainList.Add(node.Address); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (node?.Subid is not null) | ||||||
|  |         { | ||||||
|  |             var subItem = await AppHandler.Instance.GetSubItem(node.Subid); | ||||||
|  |             if (subItem is not null) | ||||||
|  |             { | ||||||
|  |                 foreach (var profile in new[] { subItem.PrevProfile, subItem.NextProfile }) | ||||||
|  |                 { | ||||||
|  |                     var profileNode = await AppHandler.Instance.GetProfileItemViaRemarks(profile); | ||||||
|  |                     if (profileNode is not null && | ||||||
|  |                         profileNode.ConfigType is not (EConfigType.Custom or EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) && | ||||||
|  |                         Utils.IsDomain(profileNode.Address)) | ||||||
|  |                     { | ||||||
|  |                         directDomainList.Add(profileNode.Address); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         v2rayConfig.dns ??= new Dns4Ray(); | ||||||
|  |         v2rayConfig.dns.servers ??= new List<object>(); | ||||||
|  | 
 | ||||||
|  |         void AddDnsServers(List<string> dnsAddresses, List<string> domains, List<string>? expectedIPs = null) | ||||||
|  |         { | ||||||
|  |             if (domains.Count > 0) | ||||||
|  |             { | ||||||
|  |                 foreach (var dnsAddress in dnsAddresses) | ||||||
|  |                 { | ||||||
|  |                     v2rayConfig.dns.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         AddDnsServers(remoteDNSAddress, proxyDomainList); | ||||||
|  |         AddDnsServers(directDNSAddress, directDomainList); | ||||||
|  |         AddDnsServers(remoteDNSAddress, proxyGeositeList); | ||||||
|  |         AddDnsServers(directDNSAddress, directGeositeList); | ||||||
|  |         AddDnsServers(directDNSAddress, expectedDomainList, expectedIPs); | ||||||
|  | 
 | ||||||
|  |         var 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); | ||||||
|  | 
 | ||||||
|  |         var defaultDnsServers = useDirectDns ? directDNSAddress : remoteDNSAddress; | ||||||
|  |         v2rayConfig.dns.servers.AddRange(defaultDnsServers); | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsHosts(V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem) | ||||||
|  |     { | ||||||
|  |         if (simpleDNSItem.AddCommonHosts == false && simpleDNSItem.UseSystemHosts == false && simpleDNSItem.Hosts.IsNullOrEmpty()) | ||||||
|  |         { | ||||||
|  |             return await Task.FromResult(0); | ||||||
|  |         } | ||||||
|  |         v2rayConfig.dns ??= new Dns4Ray(); | ||||||
|  |         v2rayConfig.dns.hosts ??= new Dictionary<string, List<string>>(); | ||||||
|  |         if (simpleDNSItem.AddCommonHosts == true) | ||||||
|  |         { | ||||||
|  |             v2rayConfig.dns.hosts = Global.PredefinedHosts; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (simpleDNSItem.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 = simpleDNSItem.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); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<int> GenDnsCompatible(ProfileItem? node, V2rayConfig v2rayConfig) | ||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|  | @ -1182,22 +1441,33 @@ public class CoreConfigV2rayService | ||||||
|                 var systemHosts = Utils.GetSystemHosts(); |                 var systemHosts = Utils.GetSystemHosts(); | ||||||
|                 if (systemHosts.Count > 0) |                 if (systemHosts.Count > 0) | ||||||
|                 { |                 { | ||||||
|                     var normalHost = obj["hosts"]; |                     var normalHost1 = obj["hosts"]; | ||||||
|                     if (normalHost != null) |                     if (normalHost1 != null) | ||||||
|                     { |                     { | ||||||
|                         foreach (var host in systemHosts) |                         foreach (var host in systemHosts) | ||||||
|                         { |                         { | ||||||
|                             if (normalHost[host.Key] != null) |                             if (normalHost1[host.Key] != null) | ||||||
|                                 continue; |                                 continue; | ||||||
|                             normalHost[host.Key] = host.Value; |                             normalHost1[host.Key] = host.Value; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             var normalHost = obj["hosts"]; | ||||||
|  |             if (normalHost != null) | ||||||
|  |             { | ||||||
|  |                 foreach (var hostProp in normalHost.AsObject().ToList()) | ||||||
|  |                 { | ||||||
|  |                     if (hostProp.Value is JsonValue value && value.TryGetValue<string>(out var ip)) | ||||||
|  |                     { | ||||||
|  |                         normalHost[hostProp.Key] = new JsonArray(ip); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             await GenDnsDomains(node, obj, item); |             await GenDnsDomainsCompatible(node, obj, item); | ||||||
| 
 | 
 | ||||||
|             v2rayConfig.dns = obj; |             v2rayConfig.dns = JsonUtils.Deserialize<Dns4Ray>(JsonUtils.Serialize(obj)); | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -1206,7 +1476,7 @@ public class CoreConfigV2rayService | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem) |     private async Task<int> GenDnsDomainsCompatible(ProfileItem? node, JsonNode dns, DNSItem? dNSItem) | ||||||
|     { |     { | ||||||
|         if (node == null) |         if (node == null) | ||||||
|         { |         { | ||||||
|  | @ -1229,7 +1499,6 @@ public class CoreConfigV2rayService | ||||||
|                     && prevNode.ConfigType != EConfigType.Custom |                     && prevNode.ConfigType != EConfigType.Custom | ||||||
|                     && prevNode.ConfigType != EConfigType.Hysteria2 |                     && prevNode.ConfigType != EConfigType.Hysteria2 | ||||||
|                     && prevNode.ConfigType != EConfigType.TUIC |                     && prevNode.ConfigType != EConfigType.TUIC | ||||||
|                     && prevNode.ConfigType != EConfigType.Anytls |  | ||||||
|                     && Utils.IsDomain(prevNode.Address)) |                     && Utils.IsDomain(prevNode.Address)) | ||||||
|                 { |                 { | ||||||
|                     domainList.Add(prevNode.Address); |                     domainList.Add(prevNode.Address); | ||||||
|  | @ -1241,7 +1510,6 @@ public class CoreConfigV2rayService | ||||||
|                     && nextNode.ConfigType != EConfigType.Custom |                     && nextNode.ConfigType != EConfigType.Custom | ||||||
|                     && nextNode.ConfigType != EConfigType.Hysteria2 |                     && nextNode.ConfigType != EConfigType.Hysteria2 | ||||||
|                     && nextNode.ConfigType != EConfigType.TUIC |                     && nextNode.ConfigType != EConfigType.TUIC | ||||||
|                     && nextNode.ConfigType != EConfigType.Anytls |  | ||||||
|                     && Utils.IsDomain(nextNode.Address)) |                     && Utils.IsDomain(nextNode.Address)) | ||||||
|                 { |                 { | ||||||
|                     domainList.Add(nextNode.Address); |                     domainList.Add(nextNode.Address); | ||||||
|  | @ -1251,7 +1519,7 @@ public class CoreConfigV2rayService | ||||||
|             { |             { | ||||||
|                 var dnsServer = new DnsServer4Ray() |                 var dnsServer = new DnsServer4Ray() | ||||||
|                 { |                 { | ||||||
|                     address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, |                     address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress, | ||||||
|                     skipFallback = true, |                     skipFallback = true, | ||||||
|                     domains = domainList |                     domains = domainList | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|  | @ -6,39 +6,52 @@ namespace ServiceLib.ViewModels; | ||||||
| 
 | 
 | ||||||
| public class DNSSettingViewModel : MyReactiveObject | public class DNSSettingViewModel : MyReactiveObject | ||||||
| { | { | ||||||
|     [Reactive] public bool UseSystemHosts { get; set; } |     [Reactive] public bool? UseSystemHosts { get; set; } | ||||||
|     [Reactive] public string DomainStrategy4Freedom { get; set; } |     [Reactive] public bool? AddCommonHosts { get; set; } | ||||||
|     [Reactive] public string DomainDNSAddress { get; set; } |     [Reactive] public bool? FakeIP { get; set; } | ||||||
|     [Reactive] public string NormalDNS { 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; } | ||||||
|  |     [Reactive] public string? DirectExpectedIPs { get; set; } | ||||||
| 
 | 
 | ||||||
|     [Reactive] public string DomainStrategy4Freedom2 { get; set; } |     [Reactive] public bool UseSystemHostsCompatible { get; set; } | ||||||
|     [Reactive] public string DomainDNSAddress2 { get; set; } |     [Reactive] public string DomainStrategy4FreedomCompatible { get; set; } | ||||||
|     [Reactive] public string NormalDNS2 { get; set; } |     [Reactive] public string DomainDNSAddressCompatible { get; set; } | ||||||
|     [Reactive] public string TunDNS2 { get; set; } |     [Reactive] public string NormalDNSCompatible { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Reactive] public string DomainStrategy4Freedom2Compatible { get; set; } | ||||||
|  |     [Reactive] public string DomainDNSAddress2Compatible { get; set; } | ||||||
|  |     [Reactive] public string NormalDNS2Compatible { get; set; } | ||||||
|  |     [Reactive] public string TunDNS2Compatible { get; set; } | ||||||
|  |     [Reactive] public bool RayCustomDNSEnableCompatible { get; set; } | ||||||
|  |     [Reactive] public bool SBCustomDNSEnableCompatible { get; set; } | ||||||
| 
 | 
 | ||||||
|     public ReactiveCommand<Unit, Unit> SaveCmd { get; } |     public ReactiveCommand<Unit, Unit> SaveCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; } |     public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCompatibleCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCmd { get; } |     public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCompatibleCmd { get; } | ||||||
| 
 | 
 | ||||||
|     public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView) |     public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView) | ||||||
|     { |     { | ||||||
|         _config = AppHandler.Instance.Config; |         _config = AppHandler.Instance.Config; | ||||||
|         _updateView = updateView; |         _updateView = updateView; | ||||||
|         SaveCmd = ReactiveCommand.CreateFromTask(async () => |         SaveCmd = ReactiveCommand.CreateFromTask(SaveSettingAsync); | ||||||
|         { |  | ||||||
|             await SaveSettingAsync(); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () => |         ImportDefConfig4V2rayCompatibleCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); |             NormalDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); | ||||||
|             await Task.CompletedTask; |             await Task.CompletedTask; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () => |         ImportDefConfig4SingboxCompatibleCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); |             NormalDNS2Compatible = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); | ||||||
|             TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); |             TunDNS2Compatible = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); | ||||||
|             await Task.CompletedTask; |             await Task.CompletedTask; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | @ -47,48 +60,80 @@ public class DNSSettingViewModel : MyReactiveObject | ||||||
| 
 | 
 | ||||||
|     private async Task Init() |     private async Task Init() | ||||||
|     { |     { | ||||||
|         var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |         _config = AppHandler.Instance.Config; | ||||||
|  |         var item = _config.SimpleDNSItem; | ||||||
|         UseSystemHosts = item.UseSystemHosts; |         UseSystemHosts = item.UseSystemHosts; | ||||||
|         DomainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty; |         AddCommonHosts = item.AddCommonHosts; | ||||||
|         DomainDNSAddress = item?.DomainDNSAddress ?? string.Empty; |         FakeIP = item.FakeIP; | ||||||
|         NormalDNS = item?.NormalDNS ?? string.Empty; |         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; | ||||||
|  |         DirectExpectedIPs = item.DirectExpectedIPs; | ||||||
|  | 
 | ||||||
|  |         var item1 = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|  |         RayCustomDNSEnableCompatible = item1.Enabled; | ||||||
|  |         UseSystemHostsCompatible = item1.UseSystemHosts; | ||||||
|  |         DomainStrategy4FreedomCompatible = item1?.DomainStrategy4Freedom ?? string.Empty; | ||||||
|  |         DomainDNSAddressCompatible = item1?.DomainDNSAddress ?? string.Empty; | ||||||
|  |         NormalDNSCompatible = item1?.NormalDNS ?? string.Empty; | ||||||
| 
 | 
 | ||||||
|         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); |         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|         DomainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty; |         SBCustomDNSEnableCompatible = item2.Enabled; | ||||||
|         DomainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty; |         DomainStrategy4Freedom2Compatible = item2?.DomainStrategy4Freedom ?? string.Empty; | ||||||
|         NormalDNS2 = item2?.NormalDNS ?? string.Empty; |         DomainDNSAddress2Compatible = item2?.DomainDNSAddress ?? string.Empty; | ||||||
|         TunDNS2 = item2?.TunDNS ?? string.Empty; |         NormalDNS2Compatible = item2?.NormalDNS ?? string.Empty; | ||||||
|  |         TunDNS2Compatible = item2?.TunDNS ?? string.Empty; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task SaveSettingAsync() |     private async Task SaveSettingAsync() | ||||||
|     { |     { | ||||||
|         if (NormalDNS.IsNotEmpty()) |         _config.SimpleDNSItem.UseSystemHosts = UseSystemHosts; | ||||||
|  |         _config.SimpleDNSItem.AddCommonHosts = AddCommonHosts; | ||||||
|  |         _config.SimpleDNSItem.FakeIP = FakeIP; | ||||||
|  |         _config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery; | ||||||
|  |         _config.SimpleDNSItem.DirectDNS = DirectDNS; | ||||||
|  |         _config.SimpleDNSItem.RemoteDNS = RemoteDNS; | ||||||
|  |         _config.SimpleDNSItem.RayStrategy4Freedom = RayStrategy4Freedom; | ||||||
|  |         _config.SimpleDNSItem.SingboxOutboundsResolveDNS = SingboxOutboundsResolveDNS; | ||||||
|  |         _config.SimpleDNSItem.SingboxFinalResolveDNS = SingboxFinalResolveDNS; | ||||||
|  |         _config.SimpleDNSItem.SingboxStrategy4Direct = SingboxStrategy4Direct; | ||||||
|  |         _config.SimpleDNSItem.SingboxStrategy4Proxy = SingboxStrategy4Proxy; | ||||||
|  |         _config.SimpleDNSItem.Hosts = Hosts; | ||||||
|  |         _config.SimpleDNSItem.DirectExpectedIPs = DirectExpectedIPs; | ||||||
|  | 
 | ||||||
|  |         if (NormalDNSCompatible.IsNotEmpty()) | ||||||
|         { |         { | ||||||
|             var obj = JsonUtils.ParseJson(NormalDNS); |             var obj = JsonUtils.ParseJson(NormalDNSCompatible); | ||||||
|             if (obj != null && obj["servers"] != null) |             if (obj != null && obj["servers"] != null) | ||||||
|             { |             { | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (NormalDNS.Contains('{') || NormalDNS.Contains('}')) |                 if (NormalDNSCompatible.Contains('{') || NormalDNSCompatible.Contains('}')) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (NormalDNS2.IsNotEmpty()) |         if (NormalDNS2Compatible.IsNotEmpty()) | ||||||
|         { |         { | ||||||
|             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2); |             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible); | ||||||
|             if (obj2 == null) |             if (obj2 == null) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (TunDNS2.IsNotEmpty()) |         if (TunDNS2Compatible.IsNotEmpty()) | ||||||
|         { |         { | ||||||
|             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2); |             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible); | ||||||
|             if (obj2 == null) |             if (obj2 == null) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|  | @ -96,21 +141,26 @@ public class DNSSettingViewModel : MyReactiveObject | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |         var item1 = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|         item.DomainStrategy4Freedom = DomainStrategy4Freedom; |         item1.Enabled = RayCustomDNSEnableCompatible; | ||||||
|         item.DomainDNSAddress = DomainDNSAddress; |         item1.DomainStrategy4Freedom = DomainStrategy4FreedomCompatible; | ||||||
|         item.UseSystemHosts = UseSystemHosts; |         item1.DomainDNSAddress = DomainDNSAddressCompatible; | ||||||
|         item.NormalDNS = NormalDNS; |         item1.UseSystemHosts = UseSystemHostsCompatible; | ||||||
|         await ConfigHandler.SaveDNSItems(_config, item); |         item1.NormalDNS = NormalDNSCompatible; | ||||||
|  |         await ConfigHandler.SaveDNSItems(_config, item1); | ||||||
| 
 | 
 | ||||||
|         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); |         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|         item2.DomainStrategy4Freedom = DomainStrategy4Freedom2; |         item2.Enabled = RayCustomDNSEnableCompatible; | ||||||
|         item2.DomainDNSAddress = DomainDNSAddress2; |         item2.DomainStrategy4Freedom = DomainStrategy4Freedom2Compatible; | ||||||
|         item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2)); |         item2.DomainDNSAddress = DomainDNSAddress2Compatible; | ||||||
|         item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2)); |         item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2Compatible)); | ||||||
|  |         item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2Compatible)); | ||||||
|         await ConfigHandler.SaveDNSItems(_config, item2); |         await ConfigHandler.SaveDNSItems(_config, item2); | ||||||
| 
 | 
 | ||||||
|         NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); |         await ConfigHandler.SaveConfig(_config); | ||||||
|         _ = _updateView?.Invoke(EViewAction.CloseWindow, null); |         if (_updateView != null) | ||||||
|  |         { | ||||||
|  |             await _updateView(EViewAction.CloseWindow, null); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|     x:Class="v2rayN.Desktop.Views.DNSSettingWindow" |     x:Class="v2rayN.Desktop.Views.DNSSettingWindow" | ||||||
|     xmlns="https://github.com/avaloniaui" |     xmlns="https://github.com/avaloniaui" | ||||||
|     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||||
|  |     xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls" | ||||||
|     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||||||
|     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||||
|     xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" |     xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" | ||||||
|  | @ -35,9 +36,281 @@ | ||||||
|         </StackPanel> |         </StackPanel> | ||||||
| 
 | 
 | ||||||
|         <TabControl HorizontalContentAlignment="Stretch"> |         <TabControl HorizontalContentAlignment="Stretch"> | ||||||
|  |             <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,Auto"> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             x:Name="txtBasicDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
|  |                          | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbDomesticDNS}" /> | ||||||
|  |                         <ctrls:AutoCompleteBox | ||||||
|  |                             x:Name="cmbDirectDNS" | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             Text="{Binding DirectDNS, Mode=TwoWay}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbRemoteDNS}" /> | ||||||
|  |                         <ctrls:AutoCompleteBox | ||||||
|  |                             x:Name="cmbRemoteDNS" | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             Text="{Binding RemoteDNS, Mode=TwoWay}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" /> | ||||||
|  |                         <ctrls:AutoCompleteBox | ||||||
|  |                             x:Name="cmbSBResolverDNS" | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             Text="{Binding SingboxOutboundsResolveDNS, Mode=TwoWay}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" /> | ||||||
|  |                         <ctrls:AutoCompleteBox | ||||||
|  |                             x:Name="cmbSBFinalResolverDNS" | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             Text="{Binding SingboxFinalResolveDNS, Mode=TwoWay}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="5" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbRayFreedomDNSStrategy" | ||||||
|  |                             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.TbSBDirectResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBDirectDNSStrategy" | ||||||
|  |                             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.TbSBRemoteResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBRemoteDNSStrategy" | ||||||
|  |                             Grid.Row="7" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             PlaceholderText="Default" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" /> | ||||||
|  |                         <ToggleSwitch | ||||||
|  |                             x:Name="togAddCommonHosts" | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             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,Auto,Auto,*"> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             x:Name="txtAdvancedDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|  |                         <ToggleSwitch | ||||||
|  |                             x:Name="togUseSystemHosts" | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbFakeIP}" /> | ||||||
|  |                         <ToggleSwitch | ||||||
|  |                             x:Name="togFakeIP" | ||||||
|  |                             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.TbApplyProxyDomainsOnly}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" /> | ||||||
|  |                         <ToggleSwitch | ||||||
|  |                             x:Name="togBlockBindingQuery" | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbPreventDNSLeaks}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPs}" /> | ||||||
|  |                         <ctrls:AutoCompleteBox | ||||||
|  |                             x:Name="cmbDirectExpectedIPs" | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             Text="{Binding DirectExpectedIPs, Mode=TwoWay}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="5" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbDNSHostsConfig}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBox | ||||||
|  |                             x:Name="txtHosts" | ||||||
|  |                             Grid.Row="6" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|  |                             Margin="{StaticResource Margin4}" | ||||||
|  |                             VerticalAlignment="Stretch" | ||||||
|  |                             Watermark="{x:Static resx:ResUI.TbDNSHostsConfig}" | ||||||
|  |                             BorderThickness="1" | ||||||
|  |                             Classes="TextArea" | ||||||
|  |                             TextWrapping="Wrap" /> | ||||||
|  |                     </Grid> | ||||||
|  |                 </ScrollViewer> | ||||||
|  |             </TabItem> | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|  |                         <Grid.RowDefinitions> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|  |                             <ToggleSwitch | ||||||
|  |                                 x:Name="togRayCustomDNSEnableCompatible" | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 HorizontalAlignment="Left" /> | ||||||
|  |                         </StackPanel> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|                             <TextBlock |                             <TextBlock | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|  | @ -49,11 +322,12 @@ | ||||||
|                                 </HyperlinkButton> |                                 </HyperlinkButton> | ||||||
|                             </TextBlock> |                             </TextBlock> | ||||||
|                             <Button |                             <Button | ||||||
|                             x:Name="btnImportDefConfig4V2ray" |                                 x:Name="btnImportDefConfig4V2rayCompatible" | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" | ||||||
|                                 Cursor="Hand" /> |                                 Cursor="Hand" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  |                     </Grid> | ||||||
| 
 | 
 | ||||||
|                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -62,7 +336,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|                             <ToggleSwitch |                             <ToggleSwitch | ||||||
|                                 x:Name="togUseSystemHosts" |                                 x:Name="togUseSystemHostsCompatible" | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 HorizontalAlignment="Left" /> |                                 HorizontalAlignment="Left" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -73,7 +347,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Freedom" |                                 x:Name="cmbdomainStrategy4FreedomCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -83,10 +357,11 @@ | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ctrls:AutoCompleteBox | ||||||
|                                 x:Name="cmbdomainDNSAddress" |                                 x:Name="cmbdomainDNSAddressCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 Text="{Binding DomainDNSAddressCompatible, Mode=TwoWay}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|  | @ -96,7 +371,7 @@ | ||||||
|                         BorderThickness="1" |                         BorderThickness="1" | ||||||
|                         Header="HTTP/SOCKS"> |                         Header="HTTP/SOCKS"> | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             Name="txtnormalDNS" |                             Name="txtnormalDNSCompatible" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             Classes="TextArea" |                             Classes="TextArea" | ||||||
|                             MinLines="10" |                             MinLines="10" | ||||||
|  | @ -107,18 +382,36 @@ | ||||||
| 
 | 
 | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|  |                         <Grid.RowDefinitions> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|  |                             <ToggleSwitch | ||||||
|  |                                 x:Name="togSBCustomDNSEnableCompatible" | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 HorizontalAlignment="Left" /> | ||||||
|  |                         </StackPanel> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|                             <TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center"> |                             <TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center"> | ||||||
|                                 <HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click"> |                                 <HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click"> | ||||||
|                                     <TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" /> |                                     <TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" /> | ||||||
|                                 </HyperlinkButton> |                                 </HyperlinkButton> | ||||||
|                             </TextBlock> |                             </TextBlock> | ||||||
|                             <Button |                             <Button | ||||||
|                             x:Name="btnImportDefConfig4Singbox" |                                 x:Name="btnImportDefConfig4SingboxCompatible" | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" | ||||||
|                                 Cursor="Hand" /> |                                 Cursor="Hand" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  |                     </Grid> | ||||||
| 
 | 
 | ||||||
|                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -127,7 +420,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Out" |                                 x:Name="cmbdomainStrategy4OutCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -137,10 +430,11 @@ | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ctrls:AutoCompleteBox | ||||||
|                                 x:Name="cmbdomainDNSAddress2" |                                 x:Name="cmbdomainDNSAddress2Compatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 Text="{Binding DomainDNSAddress2Compatible, Mode=TwoWay}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|  | @ -152,7 +446,7 @@ | ||||||
|                             BorderThickness="1" |                             BorderThickness="1" | ||||||
|                             Header="HTTP/SOCKS"> |                             Header="HTTP/SOCKS"> | ||||||
|                             <TextBox |                             <TextBox | ||||||
|                                 Name="txtnormalDNS2" |                                 Name="txtnormalDNS2Compatible" | ||||||
|                                 VerticalAlignment="Stretch" |                                 VerticalAlignment="Stretch" | ||||||
|                                 Classes="TextArea" |                                 Classes="TextArea" | ||||||
|                                 MinLines="10" |                                 MinLines="10" | ||||||
|  | @ -167,7 +461,7 @@ | ||||||
|                             BorderThickness="1" |                             BorderThickness="1" | ||||||
|                             Header="{x:Static resx:ResUI.TbSettingsTunMode}"> |                             Header="{x:Static resx:ResUI.TbSettingsTunMode}"> | ||||||
|                             <TextBox |                             <TextBox | ||||||
|                                 Name="txttunDNS2" |                                 Name="txttunDNS2Compatible" | ||||||
|                                 VerticalAlignment="Stretch" |                                 VerticalAlignment="Stretch" | ||||||
|                                 Classes="TextArea" |                                 Classes="TextArea" | ||||||
|                                 MinLines="10" |                                 MinLines="10" | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||||
|  | using Avalonia.Controls; | ||||||
| using Avalonia.Interactivity; | using Avalonia.Interactivity; | ||||||
| using ReactiveUI; | using ReactiveUI; | ||||||
| using v2rayN.Desktop.Base; | using v2rayN.Desktop.Base; | ||||||
|  | @ -17,26 +18,64 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel> | ||||||
|         btnCancel.Click += (s, e) => this.Close(); |         btnCancel.Click += (s, e) => this.Close(); | ||||||
|         ViewModel = new DNSSettingViewModel(UpdateViewHandler); |         ViewModel = new DNSSettingViewModel(UpdateViewHandler); | ||||||
| 
 | 
 | ||||||
|         cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms; |         cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|         cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out; |         cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress; |         cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress; |         cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress; | ||||||
|  |         cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto,localhost" }); | ||||||
|  |         cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress; | ||||||
|  |         cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress.Concat(new[] { "dhcp://auto,localhost" }); | ||||||
|  |         cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs; | ||||||
|  | 
 | ||||||
|  |         cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|  |         cmbdomainStrategy4OutCompatible.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|  |         cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress; | ||||||
|  |         cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress; | ||||||
| 
 | 
 | ||||||
|         this.WhenActivated(disposables => |         this.WhenActivated(disposables => | ||||||
|         { |         { | ||||||
|             this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables); | ||||||
| 
 |             //this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).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.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|             this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).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); |             this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.SelectedItem).DisposeWith(disposables); | ||||||
|  |             //this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.SelectedItem).DisposeWith(disposables); | ||||||
|  |             //this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables); | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.WhenAnyValue( | ||||||
|  |                     x => x.ViewModel.RayCustomDNSEnableCompatible, | ||||||
|  |                     x => x.ViewModel.SBCustomDNSEnableCompatible, | ||||||
|  |                     (ray, sb) => ray && sb | ||||||
|  |                 ).BindTo(this.FindControl<TextBlock>("txtBasicDNSSettingsInvalid"), t => t.IsVisible); | ||||||
|  |             this.WhenAnyValue( | ||||||
|  |                     x => x.ViewModel.RayCustomDNSEnableCompatible, | ||||||
|  |                     x => x.ViewModel.SBCustomDNSEnableCompatible, | ||||||
|  |                     (ray, sb) => ray && sb | ||||||
|  |                 ).BindTo(this.FindControl<TextBlock>("txtAdvancedDNSSettingsInvalid"), t => t.IsVisible); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,10 +41,339 @@ | ||||||
|         </StackPanel> |         </StackPanel> | ||||||
| 
 | 
 | ||||||
|         <TabControl HorizontalContentAlignment="Left"> |         <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" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                         <Grid.ColumnDefinitions> | ||||||
|  |                             <ColumnDefinition Width="Auto" /> | ||||||
|  |                             <ColumnDefinition Width="Auto" /> | ||||||
|  |                             <ColumnDefinition Width="*" /> | ||||||
|  |                         </Grid.ColumnDefinitions> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             x:Name="txtBasicDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbDomesticDNS}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbDirectDNS" | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbRemoteDNS}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbRemoteDNS" | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBResolverDNS" | ||||||
|  |                             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.TbSBOutboundDomainResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBFinalResolverDNS" | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="5" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbRayFreedomDNSStrategy" | ||||||
|  |                             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.TbSBDirectResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBDirectDNSStrategy" | ||||||
|  |                             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.TbSBRemoteResolveStrategy}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbSBRemoteDNSStrategy" | ||||||
|  |                             Grid.Row="7" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             materialDesign:HintAssist.Hint="Default" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" /> | ||||||
|  |                         <ToggleButton | ||||||
|  |                             x:Name="togAddCommonHosts" | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="8" | ||||||
|  |                             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="Auto" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                             <RowDefinition Height="*" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                         <Grid.ColumnDefinitions> | ||||||
|  |                             <ColumnDefinition Width="Auto" /> | ||||||
|  |                             <ColumnDefinition Width="Auto" /> | ||||||
|  |                             <ColumnDefinition Width="*" /> | ||||||
|  |                         </Grid.ColumnDefinitions> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             x:Name="txtAdvancedDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|  |                         <ToggleButton | ||||||
|  |                             x:Name="togUseSystemHosts" | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="2" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbFakeIP}" /> | ||||||
|  |                         <ToggleButton | ||||||
|  |                             x:Name="togFakeIP" | ||||||
|  |                             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.TbApplyProxyDomainsOnly}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" /> | ||||||
|  |                         <ToggleButton | ||||||
|  |                             x:Name="togBlockBindingQuery" | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             HorizontalAlignment="Left" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbPreventDNSLeaks}" /> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPs}" /> | ||||||
|  |                         <ComboBox | ||||||
|  |                             x:Name="cmbDirectExpectedIPs" | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="1" | ||||||
|  |                             Width="200" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="5" | ||||||
|  |                             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="6" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Stretch" | ||||||
|  |                             materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbDNSHostsConfig}" | ||||||
|  |                             AcceptsReturn="True" | ||||||
|  |                             BorderThickness="1" | ||||||
|  |                             Style="{StaticResource MaterialDesignOutlinedTextBox}" | ||||||
|  |                             TextWrapping="Wrap" | ||||||
|  |                             VerticalScrollBarVisibility="Auto" /> | ||||||
|  |                     </Grid> | ||||||
|  |                 </ScrollViewer> | ||||||
|  |             </TabItem> | ||||||
| 
 | 
 | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|  |                         <Grid.RowDefinitions> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                     Margin="{StaticResource Margin8}" | ||||||
|  |                                     VerticalAlignment="Center" | ||||||
|  |                                     Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                     Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|  |                             <ToggleButton | ||||||
|  |                                     x:Name="togRayCustomDNSEnableCompatible" | ||||||
|  |                                     Margin="{StaticResource Margin8}" | ||||||
|  |                                     HorizontalAlignment="Left" /> | ||||||
|  |                         </StackPanel> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|                             <TextBlock |                             <TextBlock | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|  | @ -60,12 +389,13 @@ | ||||||
|                                 </Hyperlink> |                                 </Hyperlink> | ||||||
|                             </TextBlock> |                             </TextBlock> | ||||||
|                             <Button |                             <Button | ||||||
|                             x:Name="btnImportDefConfig4V2ray" |                                 x:Name="btnImportDefConfig4V2rayCompatible" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" | ||||||
|                                 Cursor="Hand" |                                 Cursor="Hand" | ||||||
|                                 Style="{StaticResource DefButton}" /> |                                 Style="{StaticResource DefButton}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  |                     </Grid> | ||||||
| 
 | 
 | ||||||
|                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -75,7 +405,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|                             <ToggleButton |                             <ToggleButton | ||||||
|                                 x:Name="togUseSystemHosts" |                                 x:Name="togUseSystemHostsCompatible" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 HorizontalAlignment="Left" /> |                                 HorizontalAlignment="Left" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -87,7 +417,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Freedom" |                                 x:Name="cmbdomainStrategy4FreedomCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Style="{StaticResource DefComboBox}" /> |                                 Style="{StaticResource DefComboBox}" /> | ||||||
|  | @ -100,7 +430,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainDNSAddress" |                                 x:Name="cmbdomainDNSAddressCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 IsEditable="True" |                                 IsEditable="True" | ||||||
|  | @ -109,7 +439,7 @@ | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|                     <TextBox |                     <TextBox | ||||||
|                         x:Name="txtnormalDNS" |                         x:Name="txtnormalDNSCompatible" | ||||||
|                         Margin="{StaticResource Margin8}" |                         Margin="{StaticResource Margin8}" | ||||||
|                         VerticalAlignment="Stretch" |                         VerticalAlignment="Stretch" | ||||||
|                         materialDesign:HintAssist.Hint="HTTP/SOCKS" |                         materialDesign:HintAssist.Hint="HTTP/SOCKS" | ||||||
|  | @ -123,7 +453,25 @@ | ||||||
| 
 | 
 | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|  |                         <Grid.RowDefinitions> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                             <RowDefinition Height="Auto" /> | ||||||
|  |                         </Grid.RowDefinitions> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                     Margin="{StaticResource Margin8}" | ||||||
|  |                                     VerticalAlignment="Center" | ||||||
|  |                                     Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                     Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|  |                             <ToggleButton | ||||||
|  |                                     x:Name="togSBCustomDNSEnableCompatible" | ||||||
|  |                                     Margin="{StaticResource Margin8}" | ||||||
|  |                                     HorizontalAlignment="Left" /> | ||||||
|  |                         </StackPanel> | ||||||
|  |                          | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|                             <TextBlock |                             <TextBlock | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|  | @ -134,12 +482,13 @@ | ||||||
|                                 </Hyperlink> |                                 </Hyperlink> | ||||||
|                             </TextBlock> |                             </TextBlock> | ||||||
|                             <Button |                             <Button | ||||||
|                             x:Name="btnImportDefConfig4Singbox" |                                 x:Name="btnImportDefConfig4SingboxCompatible" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                 Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" | ||||||
|                                 Cursor="Hand" |                                 Cursor="Hand" | ||||||
|                                 Style="{StaticResource DefButton}" /> |                                 Style="{StaticResource DefButton}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  |                     </Grid> | ||||||
| 
 | 
 | ||||||
|                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -149,7 +498,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Out" |                                 x:Name="cmbdomainStrategy4OutCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Style="{StaticResource DefComboBox}" /> |                                 Style="{StaticResource DefComboBox}" /> | ||||||
|  | @ -162,7 +511,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainDNSAddress2" |                                 x:Name="cmbdomainDNSAddress2Compatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 IsEditable="True" |                                 IsEditable="True" | ||||||
|  | @ -178,7 +527,7 @@ | ||||||
|                         </Grid.ColumnDefinitions> |                         </Grid.ColumnDefinitions> | ||||||
| 
 | 
 | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             x:Name="txtnormalDNS2" |                             x:Name="txtnormalDNS2Compatible" | ||||||
|                             Grid.Column="0" |                             Grid.Column="0" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             materialDesign:HintAssist.Hint="HTTP/SOCKS" |                             materialDesign:HintAssist.Hint="HTTP/SOCKS" | ||||||
|  | @ -191,7 +540,7 @@ | ||||||
|                         <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> |                         <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> | ||||||
| 
 | 
 | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             x:Name="txttunDNS2" |                             x:Name="txttunDNS2Compatible" | ||||||
|                             Grid.Column="2" |                             Grid.Column="2" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}" |                             materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}" | ||||||
|  |  | ||||||
|  | @ -17,26 +17,66 @@ public partial class DNSSettingWindow | ||||||
| 
 | 
 | ||||||
|         ViewModel = new DNSSettingViewModel(UpdateViewHandler); |         ViewModel = new DNSSettingViewModel(UpdateViewHandler); | ||||||
| 
 | 
 | ||||||
|         cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms; |         cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|         cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out; |         cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress; |         cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress; |         cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress; | ||||||
|  |         cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto,localhost" }); | ||||||
|  |         cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress; | ||||||
|  |         cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress.Concat(new[] { "dhcp://auto,localhost" }); | ||||||
|  |         cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs; | ||||||
|  | 
 | ||||||
|  |         cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|  |         cmbdomainStrategy4OutCompatible.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|  |         cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress; | ||||||
|  |         cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress; | ||||||
| 
 | 
 | ||||||
|         this.WhenActivated(disposables => |         this.WhenActivated(disposables => | ||||||
|         { |         { | ||||||
|             this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables); | ||||||
| 
 |             this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables); | ||||||
| 
 | 
 | ||||||
|             this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).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); |             this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables); | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables); | ||||||
|  | 
 | ||||||
|  |             this.WhenAnyValue( | ||||||
|  |                     x => x.ViewModel.RayCustomDNSEnableCompatible, | ||||||
|  |                     x => x.ViewModel.SBCustomDNSEnableCompatible, | ||||||
|  |                     (ray, sb) => ray && sb ? Visibility.Visible : Visibility.Collapsed) | ||||||
|  |                 .BindTo(this, x => x.txtBasicDNSSettingsInvalid.Visibility) | ||||||
|  |                 .DisposeWith(disposables); | ||||||
|  |             this.WhenAnyValue( | ||||||
|  |                     x => x.ViewModel.RayCustomDNSEnableCompatible, | ||||||
|  |                     x => x.ViewModel.SBCustomDNSEnableCompatible, | ||||||
|  |                     (ray, sb) => ray && sb ? Visibility.Visible : Visibility.Collapsed) | ||||||
|  |                 .BindTo(this, x => x.txtAdvancedDNSSettingsInvalid.Visibility) | ||||||
|  |                 .DisposeWith(disposables); | ||||||
|         }); |         }); | ||||||
|         WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme); |         WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue