From 78bc763ceec24942d2d028f1db4acb5acee4e4e5 Mon Sep 17 00:00:00 2001 From: DHR60 Date: Sat, 12 Jul 2025 21:24:34 +0800 Subject: [PATCH] ExpectedIPs --- v2rayN/ServiceLib/Common/JsonUtils.cs | 5 +++- v2rayN/ServiceLib/Global.cs | 8 ++++++ v2rayN/ServiceLib/Models/ConfigItems.cs | 1 + v2rayN/ServiceLib/Models/V2rayConfig.cs | 2 ++ v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 20 +++++++++++++- v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | 8 +++++- v2rayN/ServiceLib/Resx/ResUI.hu.resx | 8 +++++- v2rayN/ServiceLib/Resx/ResUI.resx | 8 +++++- v2rayN/ServiceLib/Resx/ResUI.ru.resx | 8 +++++- v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 6 +++++ v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 8 +++++- .../CoreConfig/CoreConfigSingboxService.cs | 4 +++ .../CoreConfig/CoreConfigV2rayService.cs | 26 ++++++++++++------ .../ViewModels/DNSSettingViewModel.cs | 3 +++ .../Views/DNSSettingWindow.axaml | 23 ++++++++++++++-- .../Views/DNSSettingWindow.axaml.cs | 2 ++ v2rayN/v2rayN/Views/DNSSettingWindow.xaml | 27 ++++++++++++++++++- v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs | 2 ++ 18 files changed, 151 insertions(+), 18 deletions(-) diff --git a/v2rayN/ServiceLib/Common/JsonUtils.cs b/v2rayN/ServiceLib/Common/JsonUtils.cs index 773ba79c..6954e124 100644 --- a/v2rayN/ServiceLib/Common/JsonUtils.cs +++ b/v2rayN/ServiceLib/Common/JsonUtils.cs @@ -128,5 +128,8 @@ public class JsonUtils /// /// /// - public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); + public static JsonNode? SerializeToNode(object? obj, JsonSerializerOptions? options = null) + { + return JsonSerializer.SerializeToNode(obj, options); + } } diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index a667a335..180bd90c 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -571,5 +571,13 @@ public class Global { "engage.cloudflareclient.com", new List { "162.159.192.1", "2606:4700:d0::a29f:c001" } } }; + public static readonly List ExpectedIPs = + [ + "geoip:cn", + "geoip:ir", + "geoip:ru", + "" + ]; + #endregion const } diff --git a/v2rayN/ServiceLib/Models/ConfigItems.cs b/v2rayN/ServiceLib/Models/ConfigItems.cs index 8847782b..ea73ffe2 100644 --- a/v2rayN/ServiceLib/Models/ConfigItems.cs +++ b/v2rayN/ServiceLib/Models/ConfigItems.cs @@ -269,4 +269,5 @@ public class DNSItem public string? SingboxStrategy4Direct { get; set; } public string? SingboxStrategy4Proxy { 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 a18c7e34..664ab923 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -212,6 +212,8 @@ public class DnsServer4Ray public string? address { get; set; } public List? domains { get; set; } public bool? skipFallback { get; set; } + public List? expectedIPs { get; set; } + public List? unexpectedIPs { get; set; } } public class Routing4Ray diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 589ff0a5..152ee845 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -2824,7 +2824,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Enable to Override sing-box DoH Resolver 的本地化字符串。 + /// 查找类似 The sing-box DoH resolution server can be overwritten 的本地化字符串。 /// public static string TbSBDoHOverride { get { @@ -3822,6 +3822,24 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Validate Direct Expected IPs 的本地化字符串。 + /// + public static string TbValidateDirectExpectedIPs { + get { + return ResourceManager.GetString("TbValidateDirectExpectedIPs", resourceCulture); + } + } + + /// + /// 查找类似 After configuration, validates returned IPs, returning only expected IPs 的本地化字符串。 + /// + public static string TbValidateDirectExpectedIPsDesc { + get { + return ResourceManager.GetString("TbValidateDirectExpectedIPsDesc", resourceCulture); + } + } + /// /// 查找类似 xray Freedom Resolution Strategy 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 6ebf5697..c2e7676a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1429,7 +1429,7 @@ Add Common DNS Hosts - Enable to Override sing-box DoH Resolver + The sing-box DoH resolution server can be overwritten FakeIP @@ -1452,4 +1452,10 @@ Advanced DNS Settings + + Validate Direct Expected IPs + + + After configuration, validates returned IPs, returning only expected IPs + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 44504ffd..e7501327 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1429,7 +1429,7 @@ Add Common DNS Hosts - Enable to Override sing-box DoH Resolver + The sing-box DoH resolution server can be overwritten FakeIP @@ -1452,4 +1452,10 @@ Advanced DNS Settings + + Validate Direct Expected IPs + + + After configuration, validates returned IPs, returning only expected IPs + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 54a24060..7b111eef 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1429,7 +1429,7 @@ Add Common DNS Hosts - Enable to Override sing-box DoH Resolver + The sing-box DoH resolution server can be overwritten FakeIP @@ -1452,4 +1452,10 @@ Advanced DNS Settings + + Validate Direct Expected IPs + + + After configuration, validates returned IPs, returning only expected IPs + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 1eb7ed28..41f9e6ba 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1429,7 +1429,7 @@ Add Common DNS Hosts - Enable to Override sing-box DoH Resolver + The sing-box DoH resolution server can be overwritten FakeIP @@ -1452,4 +1452,10 @@ Advanced DNS Settings + + Validate Direct Expected IPs + + + After configuration, validates returned IPs, returning only expected IPs + \ 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 04d0b16f..3b3a5796 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1449,4 +1449,10 @@ DNS 进阶设置 + + 校验直连期望 IP + + + 配置后,会对返回的 IP 的进行校验,只返回期望 IP + \ 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 5a9e9a02..5d2a2413 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1426,7 +1426,7 @@ Add Common DNS Hosts - Enable to Override sing-box DoH Resolver + The sing-box DoH resolution server can be overwritten FakeIP @@ -1449,4 +1449,10 @@ Advanced DNS Settings + + Validate Direct Expected IPs + + + After configuration, validates returned IPs, returning only expected IPs + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs index 993d8ad8..0de63bca 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs @@ -1758,6 +1758,10 @@ public class CoreConfigSingboxService { rule.server = "dns_direct"; rule.strategy = dNSItem.SingboxStrategy4Direct.IsNullOrEmpty() ? null : dNSItem.SingboxStrategy4Direct; + if (!dNSItem.DirectExpectedIPs.IsNullOrEmpty()) + { + rule.rule_set = new() { dNSItem.DirectExpectedIPs }; + } } else if (item.OutboundTag == Global.ProxyTag) { diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index 0374d74e..d2868be1 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -1,6 +1,8 @@ using System.Net; using System.Net.NetworkInformation; +using System.Text.Json; using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace ServiceLib.Services.CoreConfig; @@ -1282,30 +1284,37 @@ public class CoreConfigV2rayService v2rayConfig.dns ??= new Dns4Ray(); v2rayConfig.dns.servers ??= new List(); + var options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + if (proxyDomainList.Count > 0) { foreach (var dnsDomain in remoteDNSAddress) { - var dnsServer = new DnsServer4Ray() + var dnsServer = new DnsServer4Ray { address = dnsDomain, skipFallback = true, domains = proxyDomainList }; - v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer)); + v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer, options)); } } + if (directDomainList.Count > 0) { foreach (var dnsDomain in directDNSAddress) { - var dnsServer = new DnsServer4Ray() + var dnsServer = new DnsServer4Ray { address = dnsDomain, skipFallback = true, - domains = directDomainList + domains = directDomainList, + expectedIPs = dNSItem.DirectExpectedIPs.IsNullOrEmpty() ? null : new() { dNSItem.DirectExpectedIPs } }; - v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer)); + v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer, options)); } } if (proxyGeositeList.Count > 0) @@ -1318,7 +1327,7 @@ public class CoreConfigV2rayService skipFallback = true, domains = proxyGeositeList }; - v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer)); + v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer, options)); } } if (directGeositeList.Count > 0) @@ -1329,9 +1338,10 @@ public class CoreConfigV2rayService { address = dnsDomain, skipFallback = true, - domains = directGeositeList + domains = directGeositeList, + expectedIPs = dNSItem.DirectExpectedIPs.IsNullOrEmpty() ? null : new() { dNSItem.DirectExpectedIPs } }; - v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer)); + v2rayConfig.dns.servers.Add(JsonUtils.SerializeToNode(dnsServer, options)); } } diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index 734d97bf..ff6620d6 100644 --- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -18,6 +18,7 @@ public class DNSSettingViewModel : MyReactiveObject [Reactive] public string? SingboxStrategy4Direct { get; set; } [Reactive] public string? SingboxStrategy4Proxy { get; set; } [Reactive] public string? Hosts { get; set; } + [Reactive] public string? DirectExpectedIPs { get; set; } public ReactiveCommand SaveCmd { get; } //public ReactiveCommand ImportDefConfig4V2rayCmd { get; } @@ -61,6 +62,7 @@ public class DNSSettingViewModel : MyReactiveObject SingboxStrategy4Direct = item.SingboxStrategy4Direct; SingboxStrategy4Proxy = item.SingboxStrategy4Proxy; Hosts = item.Hosts; + DirectExpectedIPs = item.DirectExpectedIPs; } private async Task SaveSettingAsync() @@ -77,6 +79,7 @@ public class DNSSettingViewModel : MyReactiveObject _config.DNSItem.SingboxStrategy4Direct = SingboxStrategy4Direct; _config.DNSItem.SingboxStrategy4Proxy = SingboxStrategy4Proxy; _config.DNSItem.Hosts = Hosts; + _config.DNSItem.DirectExpectedIPs = DirectExpectedIPs; await ConfigHandler.SaveConfig(_config); if (_updateView != null) { diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml index 59cffdc5..9db53ea5 100644 --- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml @@ -175,7 +175,7 @@ + RowDefinitions="Auto,Auto,Auto,Auto,Auto,*"> + + + + 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; this.WhenActivated(disposables => { @@ -39,6 +40,7 @@ public partial class DNSSettingWindow : WindowBase 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.SelectedItem).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); }); diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml index 4731ab05..c8c8e31f 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml @@ -217,6 +217,7 @@ + @@ -281,9 +282,33 @@ Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.TbPreventDNSLeaks}" /> + + + + + { @@ -39,6 +40,7 @@ public partial class DNSSettingWindow 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.SelectedItem).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); });