From ce380b861cb29af58c9faab9314568d15eb7eecd Mon Sep 17 00:00:00 2001 From: DHR60 <192860629+DHR60@users.noreply.github.com> Date: Sat, 20 Jun 2026 02:09:27 +0000 Subject: [PATCH] Node check (#9603) --- v2rayN/ServiceLib/Common/Utils.cs | 6 ++++ .../Builder/CoreConfigContextBuilder.cs | 24 +++++++++++++- .../Handler/Builder/NodeValidator.cs | 33 ++++++++++--------- v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 18 +++++----- v2rayN/ServiceLib/Resx/ResUI.fa.resx | 5 +-- v2rayN/ServiceLib/Resx/ResUI.fr.resx | 3 -- v2rayN/ServiceLib/Resx/ResUI.hu.resx | 3 -- v2rayN/ServiceLib/Resx/ResUI.id.resx | 9 ----- v2rayN/ServiceLib/Resx/ResUI.resx | 6 ++-- v2rayN/ServiceLib/Resx/ResUI.ru.resx | 3 -- v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 6 ++-- v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 3 -- .../Singbox/SingboxConfigTemplateService.cs | 8 ----- .../V2ray/V2rayConfigTemplateService.cs | 8 ----- .../ViewModels/OptionSettingViewModel.cs | 6 ---- 15 files changed, 62 insertions(+), 79 deletions(-) diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs index b6831dff..05d7c621 100644 --- a/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayN/ServiceLib/Common/Utils.cs @@ -728,6 +728,12 @@ public class Utils .Any(ua => ua.Address.Equals(targetAddress)); } + public static bool ContainsInterfaceName(string inInterfaceName) + { + return NetworkInterface.GetAllNetworkInterfaces() + .Any(ni => ni.Name.Equals(inInterfaceName, StringComparison.OrdinalIgnoreCase)); + } + #endregion Speed Test #region Miscellaneous diff --git a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs index e003adee..27e07b5b 100644 --- a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs +++ b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs @@ -96,17 +96,39 @@ public class CoreConfigContextBuilder } if (context.IsTunEnabled && context.AppConfig.TunModeItem.RouteExcludeAddress is { Count: > 0 }) { + var appConfig = JsonUtils.DeepCopy(config); + var routeExcludeAddressList = new List(); foreach (var addr in context.AppConfig.TunModeItem.RouteExcludeAddress) { try { IPNetwork2.Parse(addr); + routeExcludeAddressList.Add(addr); } catch { - validatorResult.Errors.Add(string.Format(ResUI.MsgTunRouteExcludeInvalidAddress, addr)); + validatorResult.Warnings.Add(string.Format(ResUI.MsgTunRouteExcludeInvalidAddress, addr)); } } + appConfig.TunModeItem.RouteExcludeAddress = routeExcludeAddressList; + context = context with { AppConfig = appConfig }; + } + if (!context.AppConfig.CoreBasicItem.SendThrough.IsNullOrEmpty() + && !Utils.IsLocalIP(context.AppConfig.CoreBasicItem.SendThrough)) + { + validatorResult.Warnings.Add(string.Format(ResUI.MsgInvalidProperty, ResUI.TbSettingsSendThrough)); + var appConfig = JsonUtils.DeepCopy(config); + appConfig.CoreBasicItem.SendThrough = string.Empty; + context = context with { AppConfig = appConfig }; + } + if (!context.AppConfig.CoreBasicItem.BindInterface.IsNullOrEmpty() + && (!Utils.ContainsInterfaceName(context.AppConfig.CoreBasicItem.BindInterface) + || !(context.IsTunEnabled || context.IsWindows))) + { + validatorResult.Warnings.Add(string.Format(ResUI.MsgInvalidProperty, ResUI.TbSettingsBindInterface)); + var appConfig = JsonUtils.DeepCopy(config); + appConfig.CoreBasicItem.BindInterface = string.Empty; + context = context with { AppConfig = appConfig }; } return new CoreConfigContextBuilderResult(context, validatorResult); diff --git a/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs b/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs index 9665144d..ad082161 100644 --- a/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs +++ b/v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs @@ -43,8 +43,8 @@ public class NodeValidator } // Basic Property Validation - v.Assert(!item.Address.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, "Address")); - v.Assert(item.Port is > 0 and <= 65535, string.Format(ResUI.MsgInvalidProperty, "Port")); + v.Assert(!item.Address.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, ResUI.TbAddress)); + v.Assert(item.Port is > 0 and <= 65535, string.Format(ResUI.MsgInvalidProperty, ResUI.TbPort)); // Network & Core Logic var net = item.GetNetwork(); @@ -75,25 +75,25 @@ public class NodeValidator { case EConfigType.VMess: v.Assert(!item.Password.IsNullOrEmpty() && Utils.IsGuidByParse(item.Password), - string.Format(ResUI.MsgInvalidProperty, "Password")); + string.Format(ResUI.MsgInvalidProperty, ResUI.TbId)); break; case EConfigType.VLESS: v.Assert( !item.Password.IsNullOrEmpty() && (Utils.IsGuidByParse(item.Password) || item.Password.Length <= 30), - string.Format(ResUI.MsgInvalidProperty, "Password") + string.Format(ResUI.MsgInvalidProperty, ResUI.TbId5) ); v.Assert(Global.Flows.Contains(protocolExtra.Flow ?? string.Empty), - string.Format(ResUI.MsgInvalidProperty, "Flow")); + string.Format(ResUI.MsgInvalidProperty, ResUI.TbFlow5)); break; case EConfigType.Shadowsocks: - v.Assert(!item.Password.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, "Password")); + v.Assert(!item.Password.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, ResUI.TbId3)); v.Assert( !string.IsNullOrEmpty(protocolExtra.SsMethod) && Global.SsSecuritiesInSingbox.Contains(protocolExtra.SsMethod), - string.Format(ResUI.MsgInvalidProperty, "SsMethod")); + string.Format(ResUI.MsgInvalidProperty, ResUI.TbSecurity3)); break; } @@ -115,10 +115,11 @@ public class NodeValidator // TLS & Security if (item.StreamSecurity == Global.StreamSecurity) { - if (!item.Cert.IsNullOrEmpty() && CertPemManager.ParsePemChain(item.Cert).Count == 0 && - !item.CertSha.IsNullOrEmpty()) + var isCertProvided = !item.Cert.IsNullOrEmpty(); + if (!item.Cert.IsNullOrEmpty() && CertPemManager.ParsePemChain(item.Cert).Count == 0) { - v.Error(string.Format(ResUI.MsgInvalidProperty, "TLS Certificate")); + v.Error(string.Format(ResUI.MsgInvalidProperty, ResUI.TbFullCertTips)); + isCertProvided = false; } // Check for deprecated allowInsecure property when TLS is enabled @@ -131,19 +132,19 @@ public class NodeValidator if ((coreType == ECoreType.Xray && item.GetAllowInsecure() - && item.Cert.IsNullOrEmpty() + && !isCertProvided && item.CertSha.IsNullOrEmpty()) || (coreType == ECoreType.sing_box && item.GetAllowInsecure() - && item.Cert.IsNullOrEmpty())) + && !isCertProvided)) { - v.Warning("Insecure configuration detected: AllowInsecure is enabled but no certificate is provided. This may cause MITM attacks."); + v.Warning(ResUI.MsgInsecureConfiguration); } } if (item.StreamSecurity == Global.StreamSecurityReality) { - v.Assert(!item.PublicKey.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, "PublicKey")); + v.Assert(!item.PublicKey.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, ResUI.TbPublicKey)); } var transport = item.GetTransportExtra(); @@ -151,7 +152,7 @@ public class NodeValidator { if (JsonUtils.ParseJson(transport.XhttpExtra) is not JsonObject) { - v.Error(string.Format(ResUI.MsgInvalidProperty, "XHTTP Extra")); + v.Error(string.Format(ResUI.MsgInvalidProperty, ResUI.TransportExtra)); } } @@ -159,7 +160,7 @@ public class NodeValidator { if (JsonUtils.ParseJson(item.Finalmask) is not JsonObject) { - v.Error(string.Format(ResUI.MsgInvalidProperty, "Finalmask")); + v.Error(string.Format(ResUI.MsgInvalidProperty, ResUI.TbFinalmask)); } } } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 35f09940..e35be02b 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -222,15 +222,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 Please fill in the correct IPv4 address for SendThrough. 的本地化字符串。 - /// - public static string FillCorrectSendThroughIPv4 { - get { - return ResourceManager.GetString("FillCorrectSendThroughIPv4", resourceCulture); - } - } - /// /// 查找类似 Please enter the correct port format. 的本地化字符串。 /// @@ -2076,6 +2067,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Insecure configuration detected: AllowInsecure is enabled but no certificate is provided. This may cause MITM attacks. 的本地化字符串。 + /// + public static string MsgInsecureConfiguration { + get { + return ResourceManager.GetString("MsgInsecureConfiguration", resourceCulture); + } + } + /// /// 查找类似 The {0} property is invalid, please check 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa.resx b/v2rayN/ServiceLib/Resx/ResUI.fa.resx index edcce692..104d4dab 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa.resx @@ -1710,9 +1710,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if For multi-interface environments, enter the local machine's IPv4 address - - Please fill in the correct IPv4 address for SendThrough. - Bind Interface @@ -1740,4 +1737,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if New Update - + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index ef4d7522..532a422b 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1701,9 +1701,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Pour environnements multi-interfaces, entrez l'adresse IPv4 de la machine locale - - Veuillez saisir l’adresse IPv4 correcte de SendThrough. - Lier l'interface diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 3635310e..51fbad89 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1710,9 +1710,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if For multi-interface environments, enter the local machine's IPv4 address - - Please fill in the correct IPv4 address for SendThrough. - Bind Interface diff --git a/v2rayN/ServiceLib/Resx/ResUI.id.resx b/v2rayN/ServiceLib/Resx/ResUI.id.resx index 6b0c97cb..db630764 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.id.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.id.resx @@ -1701,12 +1701,6 @@ Tindakan "Ambil sertifikat" mungkin gagal jika sertifikat self-signed digunakan XHTTP Extra - - Izinkan pengambilan sertifikat tidak aman (self-signed) - - - Hanya untuk mengambil sertifikat self-signed. Fitur ini dapat mengekspos Anda pada risiko MITM. - Uji latensi UDP konfigurasi @@ -1719,9 +1713,6 @@ Tindakan "Ambil sertifikat" mungkin gagal jika sertifikat self-signed digunakan Untuk lingkungan multi-antarmuka, masukkan alamat IPv4 mesin lokal. - - Isi alamat IPv4 yang benar untuk SendThrough. - Bind Interface diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index e8f7f73e..f0048800 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1713,9 +1713,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if For multi-interface environments, enter the local machine's IPv4 address - - Please fill in the correct IPv4 address for SendThrough. - Bind Interface @@ -1779,4 +1776,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Save rules + + Insecure configuration detected: AllowInsecure is enabled but no certificate is provided. This may cause MITM attacks. + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 3f4f74cb..0791d45c 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1710,9 +1710,6 @@ Для среды с несколькими сетевыми интерфейсами укажите IPv4-адрес локального компьютера - - Укажите корректный IPv4-адрес для SendThrough. - Привязать интерфейс diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index f18e25ae..ec25431d 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1707,9 +1707,6 @@ 用于多网口环境,请填写本机 IPv4 地址 - - 请填写正确的 SendThrough IPv4 地址。 - 绑定网口 @@ -1776,4 +1773,7 @@ 保存规则 + + 检测到不安全配置:AllowInsecure 已启用,但未提供证书。这可能会导致中间人攻击。 + \ 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 559d036a..04740fdb 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1707,9 +1707,6 @@ 適用於多網路介面環境,請填寫本機 IPv4 位址 - - 請填寫正確的 SendThrough IPv4 位址。 - 綁定網路介面 diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxConfigTemplateService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxConfigTemplateService.cs index 171c2ecd..c9d1193a 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxConfigTemplateService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxConfigTemplateService.cs @@ -66,10 +66,6 @@ public partial class CoreConfigSingboxService { return; } - if (!(context.IsTunEnabled || context.IsWindows)) - { - return; - } foreach (var outbound in _coreConfig.outbounds ?? []) { outbound.bind_interface = ShouldBindNet(outbound) ? bindInterface : null; @@ -83,10 +79,6 @@ public partial class CoreConfigSingboxService { return; } - if (!Utils.IsLocalIP(sendThrough)) - { - return; - } foreach (var outbound in _coreConfig.outbounds ?? []) { diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs index 6bc7079a..8d076390 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs @@ -138,10 +138,6 @@ public partial class CoreConfigV2rayService { return; } - if (!(context.IsTunEnabled || context.IsWindows)) - { - return; - } foreach (var outbound in _coreConfig.outbounds ?? []) { if (!ShouldBindNet(outbound)) @@ -176,10 +172,6 @@ public partial class CoreConfigV2rayService { return; } - if (!Utils.IsLocalIP(sendThrough)) - { - return; - } foreach (var outbound in _coreConfig.outbounds ?? []) { diff --git a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs index adc6d124..d15a3c07 100644 --- a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs @@ -300,12 +300,6 @@ public class OptionSettingViewModel : MyReactiveObject NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort); return; } - var sendThroughValue = SendThrough.TrimEx(); - if (sendThroughValue.IsNotEmpty() && !Utils.IsIpv4(sendThroughValue)) - { - NoticeManager.Instance.Enqueue(ResUI.FillCorrectSendThroughIPv4); - return; - } var needReboot = EnableStatistics != _config.GuiItem.EnableStatistics || DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed || EnableDragDropSort != _config.UiItem.EnableDragDropSort