diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index e5da7007..22fe0ab2 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -255,6 +255,7 @@ public static class ConfigHandler item.Cert = profileItem.Cert; item.CertSha = profileItem.CertSha; item.EchConfigList = profileItem.EchConfigList; + item.VerifyPeerCertByName = profileItem.VerifyPeerCertByName; item.Finalmask = profileItem.Finalmask; item.ProtoExtra = profileItem.ProtoExtra; item.TransportExtra = profileItem.TransportExtra; diff --git a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs index ff7d6d20..0f822427 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs @@ -73,6 +73,10 @@ public class BaseFmt { dicQuery.Add("ech", Utils.UrlEncode(item.EchConfigList)); } + if (item.VerifyPeerCertByName.IsNotEmpty()) + { + dicQuery.Add("vcn", Utils.UrlEncode(item.VerifyPeerCertByName)); + } if (item.CertSha.IsNotEmpty()) { dicQuery.Add("pcs", Utils.UrlEncode(item.CertSha)); @@ -227,6 +231,7 @@ public class BaseFmt item.SpiderX = GetQueryDecoded(query, "spx"); item.Mldsa65Verify = GetQueryDecoded(query, "pqv"); item.EchConfigList = GetQueryDecoded(query, "ech"); + item.VerifyPeerCertByName = GetQueryDecoded(query, "vcn"); item.CertSha = GetQueryDecoded(query, "pcs"); var finalmaskDecoded = GetQueryDecoded(query, "fm"); diff --git a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs index ed6219ab..0073eb9c 100644 --- a/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs @@ -373,6 +373,7 @@ public class TlsSettings4Ray public string? spiderX { get; set; } public string? mldsa65Verify { get; set; } public List? certificates { get; set; } + public string? verifyPeerCertByName { get; set; } public string? pinnedPeerCertSha256 { get; set; } public bool? disableSystemRoot { get; set; } public string? echConfigList { get; set; } diff --git a/v2rayN/ServiceLib/Models/Entities/ProfileItem.cs b/v2rayN/ServiceLib/Models/Entities/ProfileItem.cs index cb5deabd..94dd3a69 100644 --- a/v2rayN/ServiceLib/Models/Entities/ProfileItem.cs +++ b/v2rayN/ServiceLib/Models/Entities/ProfileItem.cs @@ -191,6 +191,7 @@ public class ProfileItem public string Cert { get; set; } public string CertSha { get; set; } public string EchConfigList { get; set; } + public string VerifyPeerCertByName { get; set; } public string Finalmask { get; set; } public string ProtoExtra { get; set; } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 2729e284..04e163c9 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行时版本:4.0.30319.42000 @@ -3005,7 +3005,16 @@ namespace ServiceLib.Resx { return ResourceManager.GetString("TbEchConfigList", resourceCulture); } } - + + /// + /// 查找类似 Verify Peer Cert By Name 的本地化字符串。 + /// + public static string TbVerifyPeerCertByName { + get { + return ResourceManager.GetString("TbVerifyPeerCertByName", resourceCulture); + } + } + /// /// 查找类似 Edit 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index df5fdeb0..ac4320b2 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1581,6 +1581,9 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if EchConfigList + + Verify Peer Cert By Name + Full certificate (chain), PEM format @@ -1749,4 +1752,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Warning: Xray will disable allowInsecure (skip certificate verification) in August 2026. Please switch to pinnedPeerCertSha256 (fixed certificate fingerprint) as soon as possible. allowInsecure will not be usable after its expiration. - \ 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 1577baf6..3d247f9a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1746,4 +1746,7 @@ 警告:Xray 将在 2026.8.1 禁用跳过证书验证 allowInsecure ,请尽快改用证书固定指纹 pinnedPeerCertSha256。到期后无法使用 + + Verify Peer Cert By Name + \ 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 f52b640f..e963e1bf 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1746,4 +1746,7 @@ 警告:Xray 將在 2026.8.1 停用跳過憑證驗證 allowInsecure ,請盡快改用憑證固定指紋 pinnedPeerCertSha256。到期後無法使用 allowInsecure。 + + Verify Peer Cert By Name + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index 0cd35085..beb0aa5b 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -384,6 +384,7 @@ public partial class CoreConfigV2rayService alpn = _node.GetAlpn(), fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint, echConfigList = _node.EchConfigList.NullIfEmpty(), + verifyPeerCertByName = _node.VerifyPeerCertByName.NullIfEmpty(), }; if (sni.IsNotEmpty()) { diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml index dbf031b1..574d4716 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml @@ -1060,7 +1060,7 @@ Grid.Row="8" ColumnDefinitions="300,Auto" IsVisible="False" - RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> + RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> + + + this.Bind(ViewModel, vm => vm.AllowInsecureCertFetch, v => v.togAllowInsecureCertFetch.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AllowInsecureCertFetch, v => v.txtAllowInsecureCertFetchTips.IsVisible).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.EchConfigList, v => v.txtEchConfigList.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.SelectedSource.VerifyPeerCertByName, v => v.txtVerifyPeerCertByName.Text).DisposeWith(disposables); //reality this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml index 16512751..4a8ef291 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml @@ -1377,6 +1377,7 @@ + @@ -1461,6 +1462,22 @@ HorizontalAlignment="Left" Style="{StaticResource DefTextBox}" /> + + + v.txtAllowInsecureCertFetchTips.Visibility); this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.EchConfigList, v => v.txtEchConfigList.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.SelectedSource.VerifyPeerCertByName, v => v.txtVerifyPeerCertByName.Text).DisposeWith(disposables); //reality this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables);