diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs index 9ce27fa3..7824ff4a 100644 --- a/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayN/ServiceLib/Common/Utils.cs @@ -462,6 +462,18 @@ public class Utils return (domain, port); } + public static string? DomainStrategy4Sbox(string? strategy) + { + return strategy switch + { + not null when strategy.StartsWith("UseIPv4") => "prefer_ipv4", + not null when strategy.StartsWith("UseIPv6") => "prefer_ipv6", + not null when strategy.StartsWith("ForceIPv4") => "ipv4_only", + not null when strategy.StartsWith("ForceIPv6") => "ipv6_only", + _ => null + }; + } + #endregion Conversion Functions #region Data Checks diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index 6c22a045..486e53ed 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -339,13 +339,13 @@ public class Global IPOnDemand ]; - public static readonly List DomainStrategies4Singbox = + public static readonly List DomainStrategies4Sbox = [ - "ipv4_only", - "ipv6_only", + "", "prefer_ipv4", "prefer_ipv6", - "" + "ipv4_only", + "ipv6_only" ]; public static readonly List Fingerprints = @@ -387,28 +387,22 @@ public class Global "" ]; - public static readonly List DomainStrategy4Freedoms = + public static readonly List DomainStrategy = [ "AsIs", "UseIP", + "UseIPv4v6", + "UseIPv6v4", "UseIPv4", "UseIPv6", "" ]; - public static readonly List SingboxDomainStrategy4Out = - [ - "", - "ipv4_only", - "prefer_ipv4", - "prefer_ipv6", - "ipv6_only" - ]; - public static readonly List DomainDirectDNSAddress = [ "https://dns.alidns.com/dns-query", "https://doh.pub/dns-query", + "https://dns.alidns.com/dns-query,https://doh.pub/dns-query", "223.5.5.5", "119.29.29.29", "localhost" @@ -417,8 +411,9 @@ public class Global public static readonly List DomainRemoteDNSAddress = [ "https://cloudflare-dns.com/dns-query", - "https://dns.cloudflare.com/dns-query", "https://dns.google/dns-query", + "https://cloudflare-dns.com/dns-query,https://dns.google/dns-query,8.8.8.8", + "https://dns.cloudflare.com/dns-query", "https://doh.dns.sb/dns-query", "https://doh.opendns.com/dns-query", "https://common.dot.dns.yandex.net", @@ -616,20 +611,20 @@ public class Global public static readonly Dictionary> PredefinedHosts = new() { - { "dns.google", new List { "8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844" } }, - { "dns.alidns.com", new List { "223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1" } }, - { "one.one.one.one", new List { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } }, - { "1dot1dot1dot1.cloudflare-dns.com", new List { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } }, - { "cloudflare-dns.com", new List { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } }, - { "dns.cloudflare.com", new List { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } }, - { "dot.pub", new List { "1.12.12.12", "120.53.53.53" } }, - { "doh.pub", new List { "1.12.12.12", "120.53.53.53" } }, - { "dns.quad9.net", new List { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } }, - { "dns.yandex.net", new List { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } }, - { "dns.sb", new List { "185.222.222.222", "2a09::" } }, - { "dns.umbrella.com", new List { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } }, - { "dns.sse.cisco.com", new List { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } }, - { "engage.cloudflareclient.com", new List { "162.159.192.1", "2606:4700:d0::a29f:c001" } } + { "dns.google", ["8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844"] }, + { "dns.alidns.com", ["223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1"] }, + { "one.one.one.one", ["1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"] }, + { "1dot1dot1dot1.cloudflare-dns.com", ["1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"] }, + { "cloudflare-dns.com", ["104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9"] }, + { "dns.cloudflare.com", ["104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5"] }, + { "dot.pub", ["1.12.12.12", "120.53.53.53"] }, + { "doh.pub", ["1.12.12.12", "120.53.53.53"] }, + { "dns.quad9.net", ["9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9"] }, + { "dns.yandex.net", ["77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff"] }, + { "dns.sb", ["185.222.222.222", "2a09::"] }, + { "dns.umbrella.com", ["208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53"] }, + { "dns.sse.cisco.com", ["208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53"] }, + { "engage.cloudflareclient.com", ["162.159.192.1"] } }; public static readonly List ExpectedIPs = diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index 5877d012..f9ff4494 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -114,6 +114,8 @@ public static class ConfigHandler config.SimpleDNSItem ??= InitBuiltinSimpleDNS(); config.SimpleDNSItem.GlobalFakeIp ??= true; config.SimpleDNSItem.BootstrapDNS ??= Global.DomainPureIPDNSAddress.FirstOrDefault(); + config.SimpleDNSItem.ServeStale ??= false; + config.SimpleDNSItem.ParallelQuery ??= false; config.SpeedTestItem ??= new(); if (config.SpeedTestItem.SpeedTestTimeout < 10) diff --git a/v2rayN/ServiceLib/Models/ConfigItems.cs b/v2rayN/ServiceLib/Models/ConfigItems.cs index eeb88deb..46297e40 100644 --- a/v2rayN/ServiceLib/Models/ConfigItems.cs +++ b/v2rayN/ServiceLib/Models/ConfigItems.cs @@ -265,9 +265,10 @@ public class SimpleDNSItem public string? DirectDNS { get; set; } public string? RemoteDNS { get; set; } public string? BootstrapDNS { get; set; } - public string? RayStrategy4Freedom { get; set; } - public string? SingboxStrategy4Direct { get; set; } - public string? SingboxStrategy4Proxy { get; set; } + public string? Strategy4Freedom { get; set; } + public string? Strategy4Proxy { get; set; } + public bool? ServeStale { get; set; } + public bool? ParallelQuery { get; set; } public string? Hosts { get; set; } public string? DirectExpectedIPs { get; set; } } diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index acf17532..c752168a 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -3,7 +3,7 @@ namespace ServiceLib.Models; public class V2rayConfig { public Log4Ray log { get; set; } - public Dns4Ray dns { get; set; } + public object dns { get; set; } public List inbounds { get; set; } public List outbounds { get; set; } public Routing4Ray routing { get; set; } @@ -105,6 +105,8 @@ public class Outbounds4Ray public string protocol { get; set; } + public string? targetStrategy { get; set; } + public Outboundsettings4Ray settings { get; set; } public StreamSettings4Ray streamSettings { get; set; } @@ -206,12 +208,8 @@ public class Dns4Ray { public Dictionary? hosts { get; set; } public List servers { get; set; } - public string? clientIp { get; set; } - public string? queryStrategy { get; set; } - public bool? disableCache { get; set; } - public bool? disableFallback { get; set; } - public bool? disableFallbackIfMatch { get; set; } - public bool? useSystemHosts { get; set; } + public bool? serveStale { get; set; } + public bool? enableParallelQuery { get; set; } public string? tag { get; set; } } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index bf30c985..fd3b2d9f 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -2727,6 +2727,24 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Direct Target Resolution Strategy 的本地化字符串。 + /// + public static string TbDirectResolveStrategy { + get { + return ResourceManager.GetString("TbDirectResolveStrategy", resourceCulture); + } + } + + /// + /// 查找类似 If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. 的本地化字符串。 + /// + public static string TbDirectResolveStrategyTips { + get { + return ResourceManager.GetString("TbDirectResolveStrategyTips", resourceCulture); + } + } + /// /// 查找类似 Display GUI 的本地化字符串。 /// @@ -2799,6 +2817,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 By default, invoked only during routing for resolution 的本地化字符串。 + /// + public static string TbDomesticDNSTips { + get { + return ResourceManager.GetString("TbDomesticDNSTips", resourceCulture); + } + } + /// /// 查找类似 EchConfigList 的本地化字符串。 /// @@ -3060,6 +3087,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Parallel Query 的本地化字符串。 + /// + public static string TbParallelQuery { + get { + return ResourceManager.GetString("TbParallelQuery", resourceCulture); + } + } + /// /// 查找类似 Path 的本地化字符串。 /// @@ -3214,7 +3250,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Via proxy — please ensure remote availability 的本地化字符串。 + /// 查找类似 By default, invoked only during routing for resolution; ensure the remote server can reach this DNS 的本地化字符串。 /// public static string TbRemoteDNSTips { get { @@ -3222,6 +3258,24 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Proxy Target Resolution Strategy 的本地化字符串。 + /// + public static string TbRemoteResolveStrategy { + get { + return ResourceManager.GetString("TbRemoteResolveStrategy", resourceCulture); + } + } + + /// + /// 查找类似 If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. 的本地化字符串。 + /// + public static string TbRemoteResolveStrategyTips { + get { + return ResourceManager.GetString("TbRemoteResolveStrategyTips", resourceCulture); + } + } + /// /// 查找类似 Camouflage domain(host) 的本地化字符串。 /// @@ -3357,15 +3411,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 sing-box Direct Resolution Strategy 的本地化字符串。 - /// - public static string TbSBDirectResolveStrategy { - get { - return ResourceManager.GetString("TbSBDirectResolveStrategy", resourceCulture); - } - } - /// /// 查找类似 sing-box Full Config Template 的本地化字符串。 /// @@ -3384,15 +3429,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 sing-box Remote Resolution Strategy 的本地化字符串。 - /// - public static string TbSBRemoteResolveStrategy { - get { - return ResourceManager.GetString("TbSBRemoteResolveStrategy", resourceCulture); - } - } - /// /// 查找类似 Encryption method (security) 的本地化字符串。 /// @@ -3438,6 +3474,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Serve Stale 的本地化字符串。 + /// + public static string TbServeStale { + get { + return ResourceManager.GetString("TbServeStale", resourceCulture); + } + } + /// /// 查找类似 Set system proxy 的本地化字符串。 /// @@ -4411,7 +4456,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs 的本地化字符串。 + /// 查找类似 When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs 的本地化字符串。 /// public static string TbValidateDirectExpectedIPsDesc { get { @@ -4419,15 +4464,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 xray Freedom Resolution Strategy 的本地化字符串。 - /// - public static string TbXrayFreedomStrategy { - get { - return ResourceManager.GetString("TbXrayFreedomStrategy", resourceCulture); - } - } - /// /// 查找类似 The delay: {0} ms, {1} 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 3a720cdd..16fe442f 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1419,17 +1419,11 @@ Domestic DNS - - Via proxy — please ensure remote availability + + Direct Target Resolution Strategy - - xray Freedom Resolution Strategy - - - sing-box Direct Resolution Strategy - - - sing-box Remote Resolution Strategy + + Proxy Target Resolution Strategy Add Common DNS Hosts @@ -1453,7 +1447,7 @@ Validate Regional Domain IPs - When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs + When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs Enable Custom DNS @@ -1653,4 +1647,22 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index f1710de6..a114ac21 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1416,17 +1416,11 @@ DNS direct - - Via le proxy ; assurez-vous que le serveur distant est disponible + + Direct Target Resolution Strategy - - Stratégie de résolution xray freedom - - - Stratégie de résolution directe sing-box - - - Stratégie de résolution distante sing-box + + Proxy Target Resolution Strategy Ajouter des hôtes DNS courants @@ -1450,7 +1444,7 @@ Valider les IP des domaines de la région concernée - Après config, les IP renvoyées des domaines régionaux (ex. geosite:cn) seront vérifiées ; seules les IP attendues seront retournées. + Après config, les IP renvoyées des domaines régionaux (ex. geosite:cn - geoip:cn) seront vérifiées ; seules les IP attendues seront retournées. Activer le DNS personnalisé @@ -1650,4 +1644,22 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 4787f0f1..21e4e68d 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1419,17 +1419,11 @@ Domestic DNS - - Via proxy — please ensure remote availability + + Direct Target Resolution Strategy - - xray Freedom Resolution Strategy - - - sing-box Direct Resolution Strategy - - - sing-box Remote Resolution Strategy + + Proxy Target Resolution Strategy Add Common DNS Hosts @@ -1453,7 +1447,7 @@ Validate Regional Domain IPs - When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs + When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs Enable Custom DNS @@ -1653,4 +1647,22 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 6ad8a6e4..91095de4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1419,17 +1419,11 @@ Domestic DNS - - Via proxy — please ensure remote availability + + Direct Target Resolution Strategy - - xray Freedom Resolution Strategy - - - sing-box Direct Resolution Strategy - - - sing-box Remote Resolution Strategy + + Proxy Target Resolution Strategy Add Common DNS Hosts @@ -1453,7 +1447,7 @@ Validate Regional Domain IPs - When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs + When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs Enable Custom DNS @@ -1653,4 +1647,22 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 3a0f9fef..adc9cc98 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1419,17 +1419,11 @@ Внутренний DNS - - Via proxy — please ensure remote availability + + Direct Target Resolution Strategy - - Стратегия резолвинга Freedom (Xray) - - - Стратегия прямого резолвинга (sing-box) - - - Стратегия удалённого резолвинга (sing-box) + + Proxy Target Resolution Strategy Добавить стандартные записи hosts (DNS) @@ -1453,7 +1447,7 @@ Проверять IP-адреса региональных доменов - При включении проверяет IP-адреса, возвращаемые для региональных доменов (например, geosite:cn), и оставляет только ожидаемые IP-адреса + При включении проверяет IP-адреса, возвращаемые для региональных доменов (например, geosite:cn - geoip:cn), и оставляет только ожидаемые IP-адреса Включить пользовательский DNS @@ -1653,4 +1647,22 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index b37e0ccb..b1675d48 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1416,17 +1416,11 @@ 直连 DNS - - 通过代理,请确保远程可用 + + 直连目标解析策略 - - xray freedom 解析策略 - - - sing-box 直连解析策略 - - - sing-box 远程解析策略 + + 代理目标解析策略 添加常用 DNS Hosts @@ -1450,7 +1444,7 @@ 校验相应地区域名 IP - 配置后,会对相应地区域名(如 geosite:cn)的返回 IP 进行校验,仅返回期望 IP + 配置后,会对相应地区域名(如 geosite:cn - geoip:cn)的返回 IP 进行校验,仅返回期望 IP 启用自定义 DNS @@ -1650,4 +1644,22 @@ 证书指纹(SHA-256) + + 乐观缓存 + + + 并行查询 + + + 默认仅在路由阶段被调用解析 + + + 默认仅在路由阶段被调用解析;请确保远程服务器可访问该 DNS + + + 当未选择或 "AsIs" 时,使用系统 DNS 进行解析;否则,使用内部 DNS 模块解析。 + + + 当未选择或 "AsIs" 时,由远程服务器端 DNS 解析;否则,使用内部 DNS 模块解析。 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index b5acd049..73a7dfe5 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1416,17 +1416,11 @@ 直連 DNS - - 通过代理,请确保远程可用 + + 直連目標解析策略 - - xray freedom 解析策略 - - - sing-box 直連解析策略 - - - sing-box 遠程解析策略 + + 代理目標解析策略 新增常用 DNS Hosts @@ -1450,7 +1444,7 @@ 校驗相應地區域名 IP - 配置後,會對相應地區域名(如 geosite:cn)的返回 IP 進行校驗,僅返回期望 IP + 配置後,會對相應地區域名(如 geosite:cn - geoip:cn)的返回 IP 進行校驗,僅返回期望 IP 啟用自訂 DNS @@ -1650,4 +1644,22 @@ Certificate fingerprint (SHA-256) + + Serve Stale + + + Parallel Query + + + By default, invoked only during routing for resolution + + + By default, invoked only during routing for resolution; ensure the remote server can reach this DNS + + + If unset or "AsIs", DNS resolution uses the system DNS; otherwise, the internal DNS module is used. + + + If unset or "AsIs", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs index fa089140..6079b2fb 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs @@ -175,18 +175,18 @@ public partial class CoreConfigSingboxService singboxConfig.dns.rules ??= new List(); singboxConfig.dns.rules.AddRange(new[] - { + { new Rule4Sbox { ip_accept_any = true, server = Global.SingboxHostsDNSTag }, new Rule4Sbox { server = Global.SingboxRemoteDNSTag, - strategy = simpleDNSItem.SingboxStrategy4Proxy.NullIfEmpty(), + strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Proxy), clash_mode = ERuleMode.Global.ToString() }, new Rule4Sbox { server = Global.SingboxDirectDNSTag, - strategy = simpleDNSItem.SingboxStrategy4Direct.NullIfEmpty(), + strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Freedom), clash_mode = ERuleMode.Direct.ToString() } }); @@ -309,7 +309,7 @@ public partial class CoreConfigSingboxService if (item.OutboundTag == Global.DirectTag) { rule.server = Global.SingboxDirectDNSTag; - rule.strategy = string.IsNullOrEmpty(simpleDNSItem.SingboxStrategy4Direct) ? null : simpleDNSItem.SingboxStrategy4Direct; + rule.strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Freedom); if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0) { @@ -343,7 +343,7 @@ public partial class CoreConfigSingboxService singboxConfig.dns.rules.Add(rule4Fake); } rule.server = Global.SingboxRemoteDNSTag; - rule.strategy = string.IsNullOrEmpty(simpleDNSItem.SingboxStrategy4Proxy) ? null : simpleDNSItem.SingboxStrategy4Proxy; + rule.strategy = Utils.DomainStrategy4Sbox(simpleDNSItem.Strategy4Proxy); } singboxConfig.dns.rules.Add(rule); diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs index d53f29f8..cb4a2af1 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs @@ -7,21 +7,21 @@ public partial class CoreConfigSingboxService try { singboxConfig.route.final = Global.ProxyTag; - var item = _config.SimpleDNSItem; + var simpleDnsItem = _config.SimpleDNSItem; var defaultDomainResolverTag = Global.SingboxDirectDNSTag; - var directDNSStrategy = item.SingboxStrategy4Direct.IsNullOrEmpty() ? Global.SingboxDomainStrategy4Out.FirstOrDefault() : item.SingboxStrategy4Direct; + var directDnsStrategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom); var rawDNSItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box); - if (rawDNSItem != null && rawDNSItem.Enabled == true) + if (rawDNSItem is { Enabled: true }) { defaultDomainResolverTag = Global.SingboxLocalDNSTag; - directDNSStrategy = rawDNSItem.DomainStrategy4Freedom.IsNullOrEmpty() ? Global.SingboxDomainStrategy4Out.FirstOrDefault() : rawDNSItem.DomainStrategy4Freedom; + directDnsStrategy = rawDNSItem.DomainStrategy4Freedom.IsNullOrEmpty() ? null : rawDNSItem.DomainStrategy4Freedom; } singboxConfig.route.default_domain_resolver = new() { server = defaultDomainResolverTag, - strategy = directDNSStrategy + strategy = directDnsStrategy }; if (_config.TunModeItem.EnableTun) @@ -73,18 +73,17 @@ public partial class CoreConfigSingboxService var hostsDomains = new List(); var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box); - if (dnsItem == null || dnsItem.Enabled == false) + if (dnsItem == null || !dnsItem.Enabled) { - var simpleDNSItem = _config.SimpleDNSItem; - if (!simpleDNSItem.Hosts.IsNullOrEmpty()) + if (!simpleDnsItem.Hosts.IsNullOrEmpty()) { - var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts); + var userHostsMap = Utils.ParseHostsToDictionary(simpleDnsItem.Hosts); foreach (var kvp in userHostsMap) { hostsDomains.Add(kvp.Key); } } - if (simpleDNSItem.UseSystemHosts == true) + if (simpleDnsItem.UseSystemHosts == true) { var systemHostsMap = Utils.GetSystemHosts(); foreach (var kvp in systemHostsMap) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs index 6ba45895..2329c395 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs @@ -7,48 +7,74 @@ public partial class CoreConfigV2rayService try { var item = await AppManager.Instance.GetDNSItem(ECoreType.Xray); - if (item != null && item.Enabled == true) + if (item is { Enabled: true }) { var result = await GenDnsCompatible(node, v2rayConfig); - if (v2rayConfig.routing.domainStrategy == Global.IPIfNonMatch) + if (v2rayConfig.routing.domainStrategy != Global.IPIfNonMatch) { - // DNS routing - v2rayConfig.dns.tag = Global.DnsTag; - v2rayConfig.routing.rules.Add(new RulesItem4Ray - { - type = "field", - inboundTag = new List { Global.DnsTag }, - outboundTag = Global.ProxyTag, - }); + return result; } + // DNS routing + var dnsObj = JsonUtils.SerializeToNode(v2rayConfig.dns); + if (dnsObj == null) + { + return result; + } + + dnsObj["tag"] = Global.DnsTag; + v2rayConfig.dns = JsonUtils.Deserialize(JsonUtils.Serialize(dnsObj)); + v2rayConfig.routing.rules.Add(new RulesItem4Ray + { + type = "field", + inboundTag = new List { Global.DnsTag }, + outboundTag = Global.ProxyTag, + }); + return result; } - var simpleDNSItem = _config.SimpleDNSItem; - var domainStrategy4Freedom = simpleDNSItem?.RayStrategy4Freedom; + var simpleDnsItem = _config.SimpleDNSItem; + var dnsItem = v2rayConfig.dns is Dns4Ray dns4Ray ? dns4Ray : new Dns4Ray(); + var strategy4Freedom = simpleDnsItem?.Strategy4Freedom ?? Global.AsIs; //Outbound Freedom domainStrategy - if (domainStrategy4Freedom.IsNotEmpty()) + if (strategy4Freedom.IsNotEmpty() && strategy4Freedom != Global.AsIs) { var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag }); if (outbound != null) { outbound.settings = new() { - domainStrategy = domainStrategy4Freedom, + domainStrategy = strategy4Freedom, userLevel = 0 }; } } - await GenDnsServers(node, v2rayConfig, simpleDNSItem); - await GenDnsHosts(v2rayConfig, simpleDNSItem); + var strategy4Proxy = simpleDnsItem?.Strategy4Proxy ?? Global.AsIs; + //Outbound Proxy domainStrategy + if (strategy4Proxy.IsNotEmpty() && strategy4Proxy != Global.AsIs) + { + var xraySupportConfigTypeNames = Global.XraySupportConfigType + .Select(x => x == EConfigType.Hysteria2 ? "hysteria" : Global.ProtocolTypes[x]) + .ToHashSet(); + v2rayConfig.outbounds + .Where(t => xraySupportConfigTypeNames.Contains(t.protocol)) + .ToList() + .ForEach(outbound => outbound.targetStrategy = strategy4Proxy); + } + + await GenDnsServers(node, dnsItem, simpleDnsItem); + await GenDnsHosts(dnsItem, simpleDnsItem); + + dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null; + dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null; if (v2rayConfig.routing.domainStrategy == Global.IPIfNonMatch) { // DNS routing - v2rayConfig.dns.tag = Global.DnsTag; + dnsItem.tag = Global.DnsTag; v2rayConfig.routing.rules.Add(new RulesItem4Ray { type = "field", @@ -56,6 +82,8 @@ public partial class CoreConfigV2rayService outboundTag = Global.ProxyTag, }); } + + v2rayConfig.dns = dnsItem; } catch (Exception ex) { @@ -64,7 +92,7 @@ public partial class CoreConfigV2rayService return 0; } - private async Task GenDnsServers(ProfileItem? node, V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem) + private async Task GenDnsServers(ProfileItem? node, Dns4Ray dnsItem, SimpleDNSItem simpleDNSItem) { static List ParseDnsAddresses(string? dnsInput, string defaultAddress) { @@ -77,7 +105,7 @@ public partial class CoreConfigV2rayService return addresses.Count > 0 ? addresses : new List { defaultAddress }; } - static object CreateDnsServer(string dnsAddress, List domains, List? expectedIPs = null) + static object? CreateDnsServer(string dnsAddress, List domains, List? expectedIPs = null) { var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress); var domainFinal = dnsAddress; @@ -106,8 +134,8 @@ public partial class CoreConfigV2rayService }); } - var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.FirstOrDefault()); - var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.FirstOrDefault()); + var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First()); + var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First()); var directDomainList = new List(); var directGeositeList = new List(); @@ -117,7 +145,7 @@ public partial class CoreConfigV2rayService var expectedIPs = new List(); var regionNames = new HashSet(); - var bootstrapDNSAddress = ParseDnsAddresses(simpleDNSItem?.BootstrapDNS, Global.DomainPureIPDNSAddress.FirstOrDefault()); + var bootstrapDNSAddress = ParseDnsAddresses(simpleDNSItem?.BootstrapDNS, Global.DomainPureIPDNSAddress.First()); var dnsServerDomains = new List(); foreach (var dns in directDNSAddress) @@ -171,51 +199,48 @@ public partial class CoreConfigV2rayService var routing = await ConfigHandler.GetDefaultRouting(_config); List? rules = null; - if (routing != null) + rules = JsonUtils.Deserialize>(routing.RuleSet) ?? []; + foreach (var item in rules) { - rules = JsonUtils.Deserialize>(routing.RuleSet) ?? []; - foreach (var item in rules) + if (!item.Enabled || item.Domain is null || item.Domain.Count == 0) { - if (!item.Enabled || item.Domain is null || item.Domain.Count == 0) + continue; + } + + if (item.RuleType == ERuleType.Routing) + { + continue; + } + + foreach (var domain in item.Domain) + { + if (domain.StartsWith('#')) { continue; } - if (item.RuleType == ERuleType.Routing) + var normalizedDomain = domain.Replace(Global.RoutingRuleComma, ","); + + if (item.OutboundTag == Global.DirectTag) { - continue; + if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) + { + (regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain); + } + else + { + directDomainList.Add(normalizedDomain); + } } - - foreach (var domain in item.Domain) + else if (item.OutboundTag != Global.BlockTag) { - if (domain.StartsWith('#')) + if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) { - continue; + proxyGeositeList.Add(normalizedDomain); } - - var normalizedDomain = domain.Replace(Global.RoutingRuleComma, ","); - - if (item.OutboundTag == Global.DirectTag) + else { - if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) - { - (regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain); - } - else - { - directDomainList.Add(normalizedDomain); - } - } - else if (item.OutboundTag != Global.BlockTag) - { - if (normalizedDomain.StartsWith("geosite:") || normalizedDomain.StartsWith("ext:")) - { - proxyGeositeList.Add(normalizedDomain); - } - else - { - proxyDomainList.Add(normalizedDomain); - } + proxyDomainList.Add(normalizedDomain); } } } @@ -244,8 +269,7 @@ public partial class CoreConfigV2rayService } } - v2rayConfig.dns ??= new Dns4Ray(); - v2rayConfig.dns.servers ??= new List(); + dnsItem.servers ??= []; void AddDnsServers(List dnsAddresses, List domains, List? expectedIPs = null) { @@ -253,7 +277,7 @@ public partial class CoreConfigV2rayService { foreach (var dnsAddress in dnsAddresses) { - v2rayConfig.dns.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs)); + dnsItem.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs)); } } } @@ -275,22 +299,21 @@ public partial class CoreConfigV2rayService || lastRule.Ip?.Contains("0.0.0.0/0") == true); var defaultDnsServers = useDirectDns ? directDNSAddress : remoteDNSAddress; - v2rayConfig.dns.servers.AddRange(defaultDnsServers); + dnsItem.servers.AddRange(defaultDnsServers); return 0; } - private async Task GenDnsHosts(V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem) + private async Task GenDnsHosts(Dns4Ray dnsItem, 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(); + dnsItem.hosts ??= new Dictionary(); if (simpleDNSItem.AddCommonHosts == true) { - v2rayConfig.dns.hosts = Global.PredefinedHosts.ToDictionary( + dnsItem.hosts = Global.PredefinedHosts.ToDictionary( kvp => kvp.Key, kvp => (object)kvp.Value ); @@ -299,7 +322,7 @@ public partial class CoreConfigV2rayService if (simpleDNSItem.UseSystemHosts == true) { var systemHosts = Utils.GetSystemHosts(); - var normalHost = v2rayConfig?.dns?.hosts; + var normalHost = dnsItem.hosts; if (normalHost != null && systemHosts?.Count > 0) { @@ -316,7 +339,7 @@ public partial class CoreConfigV2rayService foreach (var kvp in userHostsMap) { - v2rayConfig.dns.hosts[kvp.Key] = kvp.Value; + dnsItem.hosts[kvp.Key] = kvp.Value; } } return await Task.FromResult(0); diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index d53b960d..00178d17 100644 --- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -9,11 +9,12 @@ public class DNSSettingViewModel : MyReactiveObject [Reactive] public string? DirectDNS { get; set; } [Reactive] public string? RemoteDNS { get; set; } [Reactive] public string? BootstrapDNS { get; set; } - [Reactive] public string? RayStrategy4Freedom { get; set; } - [Reactive] public string? SingboxStrategy4Direct { get; set; } - [Reactive] public string? SingboxStrategy4Proxy { get; set; } + [Reactive] public string? Strategy4Freedom { get; set; } + [Reactive] public string? Strategy4Proxy { get; set; } [Reactive] public string? Hosts { get; set; } [Reactive] public string? DirectExpectedIPs { get; set; } + [Reactive] public bool? ParallelQuery { get; set; } + [Reactive] public bool? ServeStale { get; set; } [Reactive] public bool UseSystemHostsCompatible { get; set; } [Reactive] public string DomainStrategy4FreedomCompatible { get; set; } @@ -70,11 +71,12 @@ public class DNSSettingViewModel : MyReactiveObject DirectDNS = item.DirectDNS; RemoteDNS = item.RemoteDNS; BootstrapDNS = item.BootstrapDNS; - RayStrategy4Freedom = item.RayStrategy4Freedom; - SingboxStrategy4Direct = item.SingboxStrategy4Direct; - SingboxStrategy4Proxy = item.SingboxStrategy4Proxy; + Strategy4Freedom = item.Strategy4Freedom; + Strategy4Proxy = item.Strategy4Proxy; Hosts = item.Hosts; DirectExpectedIPs = item.DirectExpectedIPs; + ParallelQuery = item.ParallelQuery; + ServeStale = item.ServeStale; var item1 = await AppManager.Instance.GetDNSItem(ECoreType.Xray); RayCustomDNSEnableCompatible = item1.Enabled; @@ -100,11 +102,12 @@ public class DNSSettingViewModel : MyReactiveObject _config.SimpleDNSItem.DirectDNS = DirectDNS; _config.SimpleDNSItem.RemoteDNS = RemoteDNS; _config.SimpleDNSItem.BootstrapDNS = BootstrapDNS; - _config.SimpleDNSItem.RayStrategy4Freedom = RayStrategy4Freedom; - _config.SimpleDNSItem.SingboxStrategy4Direct = SingboxStrategy4Direct; - _config.SimpleDNSItem.SingboxStrategy4Proxy = SingboxStrategy4Proxy; + _config.SimpleDNSItem.Strategy4Freedom = Strategy4Freedom; + _config.SimpleDNSItem.Strategy4Proxy = Strategy4Proxy; _config.SimpleDNSItem.Hosts = Hosts; _config.SimpleDNSItem.DirectExpectedIPs = DirectExpectedIPs; + _config.SimpleDNSItem.ParallelQuery = ParallelQuery; + _config.SimpleDNSItem.ServeStale = ServeStale; if (NormalDNSCompatible.IsNotEmpty()) { diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml index e5a785b7..705e79e2 100644 --- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml @@ -61,7 +61,15 @@ Grid.Column="1" Width="300" Margin="{StaticResource Margin4}" + VerticalAlignment="Center" IsEditable="True" /> + - + + Text="{x:Static resx:ResUI.TbDirectResolveStrategy}" /> - - + Text="{x:Static resx:ResUI.TbDirectResolveStrategyTips}" + TextWrapping="Wrap" /> + Text="{x:Static resx:ResUI.TbRemoteResolveStrategy}" /> + + Text="{x:Static resx:ResUI.TbParallelQuery}" /> + HorizontalAlignment="Left" + VerticalAlignment="Center" /> + + + @@ -169,7 +196,7 @@ x:Name="gridAdvancedDNSSettings" Margin="{StaticResource Margin8}" ColumnDefinitions="Auto,Auto,*" - RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,*"> + RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,*"> + HorizontalAlignment="Left" + VerticalAlignment="Center" /> + Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" /> + HorizontalAlignment="Left" + VerticalAlignment="Center" /> + + + + HorizontalAlignment="Left" + VerticalAlignment="Center" /> btnCancel.Click += (s, e) => Close(); ViewModel = new DNSSettingViewModel(UpdateViewHandler); - cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms; - cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; - cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; + cmbDirectDNSStrategy.ItemsSource = Global.DomainStrategy; + cmbRemoteDNSStrategy.ItemsSource = Global.DomainStrategy; cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress; cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress; cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress; cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs; - cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy4Freedoms; - cmbdomainStrategy4OutCompatible.ItemsSource = Global.SingboxDomainStrategy4Out; + cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy; + cmbdomainStrategy4OutCompatible.ItemsSource = Global.DomainStrategies4Sbox; cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress; cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress; @@ -37,11 +36,12 @@ public partial class DNSSettingWindow : WindowBase this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.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.Strategy4Freedom, v => v.cmbDirectDNSStrategy.SelectedItem).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.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.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs index 076307ec..c2d90a33 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs @@ -26,7 +26,7 @@ public partial class RoutingRuleSettingWindow : WindowBase { diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs index 719acf94..e25f7237 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs @@ -22,7 +22,7 @@ public partial class RoutingSettingWindow : WindowBase ViewModel = new RoutingSettingViewModel(UpdateViewHandler); cmbdomainStrategy.ItemsSource = Global.DomainStrategies; - cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox; + cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox; this.WhenActivated(disposables => { diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml index 7deb7c25..8788e97d 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml @@ -84,6 +84,14 @@ Margin="{StaticResource Margin8}" IsEditable="True" Style="{StaticResource DefComboBox}" /> + + Text="{x:Static resx:ResUI.TbDirectResolveStrategy}" /> - - + Text="{x:Static resx:ResUI.TbDirectResolveStrategyTips}" + TextWrapping="Wrap" /> + Text="{x:Static resx:ResUI.TbRemoteResolveStrategy}" /> + + Text="{x:Static resx:ResUI.TbParallelQuery}" /> + + + @@ -207,6 +229,7 @@ + @@ -245,15 +268,29 @@ Margin="{StaticResource Margin8}" VerticalAlignment="Center" Style="{StaticResource ToolbarTextBlock}" - Text="{x:Static resx:ResUI.TbFakeIP}" /> + Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" /> + + + vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.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.Strategy4Freedom, v => v.cmbDirectDNSStrategy.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.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.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs index fd0cee6e..e736fb6b 100644 --- a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs @@ -18,7 +18,7 @@ public partial class RoutingRuleSettingWindow ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler); cmbdomainStrategy.ItemsSource = Global.DomainStrategies.AppendEmpty(); - cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox; + cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox; this.WhenActivated(disposables => { diff --git a/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml.cs index 98ccdc19..a9a781a4 100644 --- a/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml.cs @@ -17,7 +17,7 @@ public partial class RoutingSettingWindow ViewModel = new RoutingSettingViewModel(UpdateViewHandler); cmbdomainStrategy.ItemsSource = Global.DomainStrategies; - cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox; + cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox; this.WhenActivated(disposables => {