diff --git a/v2rayN/ServiceLib.Tests/CoreConfig/Context/CoreConfigContextBuilderTests.cs b/v2rayN/ServiceLib.Tests/CoreConfig/Context/CoreConfigContextBuilderTests.cs index 5f185a9f..ee329845 100644 --- a/v2rayN/ServiceLib.Tests/CoreConfig/Context/CoreConfigContextBuilderTests.cs +++ b/v2rayN/ServiceLib.Tests/CoreConfig/Context/CoreConfigContextBuilderTests.cs @@ -9,105 +9,105 @@ namespace ServiceLib.Tests.CoreConfig.Context; public class CoreConfigContextBuilderTests { - [Fact] - public async Task ResolveNodeAsync_DirectCycleDependency_ShouldFailWithCycleError() - { - var config = CoreConfigTestFactory.CreateConfig(); - CoreConfigTestFactory.BindAppManagerConfig(config); + [Fact] + public async Task ResolveNodeAsync_DirectCycleDependency_ShouldFailWithCycleError() + { + var config = CoreConfigTestFactory.CreateConfig(); + CoreConfigTestFactory.BindAppManagerConfig(config); - var groupAId = NewId("group-a"); - var groupBId = NewId("group-b"); - var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId]); - var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupAId]); + var groupAId = NewId("group-a"); + var groupBId = NewId("group-b"); + var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId]); + var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupAId]); - await UpsertProfilesAsync(groupA, groupB); + await UpsertProfilesAsync(groupA, groupB); - var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); - context.AllProxiesMap.Clear(); + var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); + context.AllProxiesMap.Clear(); - var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); + var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); - validatorResult.Success.Should().BeFalse(); - validatorResult.Errors.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); - context.AllProxiesMap.Should().NotContainKey(groupA.IndexId); - context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); - } + validatorResult.Success.Should().BeFalse(); + validatorResult.Errors.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); + context.AllProxiesMap.Should().NotContainKey(groupA.IndexId); + context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); + } - [Fact] - public async Task ResolveNodeAsync_IndirectCycleDependency_ShouldFailWithCycleError() - { - var config = CoreConfigTestFactory.CreateConfig(); - CoreConfigTestFactory.BindAppManagerConfig(config); + [Fact] + public async Task ResolveNodeAsync_IndirectCycleDependency_ShouldFailWithCycleError() + { + var config = CoreConfigTestFactory.CreateConfig(); + CoreConfigTestFactory.BindAppManagerConfig(config); - var groupAId = NewId("group-a"); - var groupBId = NewId("group-b"); - var groupCId = NewId("group-c"); - var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId]); - var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupCId]); - var groupC = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupCId, "group-c", [groupAId]); + var groupAId = NewId("group-a"); + var groupBId = NewId("group-b"); + var groupCId = NewId("group-c"); + var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId]); + var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupCId]); + var groupC = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupCId, "group-c", [groupAId]); - await UpsertProfilesAsync(groupA, groupB, groupC); + await UpsertProfilesAsync(groupA, groupB, groupC); - var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); - context.AllProxiesMap.Clear(); + var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); + context.AllProxiesMap.Clear(); - var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); + var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); - validatorResult.Success.Should().BeFalse(); - validatorResult.Errors.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); - context.AllProxiesMap.Should().NotContainKey(groupA.IndexId); - context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); - context.AllProxiesMap.Should().NotContainKey(groupC.IndexId); - } + validatorResult.Success.Should().BeFalse(); + validatorResult.Errors.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); + context.AllProxiesMap.Should().NotContainKey(groupA.IndexId); + context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); + context.AllProxiesMap.Should().NotContainKey(groupC.IndexId); + } - [Fact] - public async Task ResolveNodeAsync_CycleWithValidBranch_ShouldSkipCycleAndKeepValidChild() - { - var config = CoreConfigTestFactory.CreateConfig(); - CoreConfigTestFactory.BindAppManagerConfig(config); + [Fact] + public async Task ResolveNodeAsync_CycleWithValidBranch_ShouldSkipCycleAndKeepValidChild() + { + var config = CoreConfigTestFactory.CreateConfig(); + CoreConfigTestFactory.BindAppManagerConfig(config); - var groupAId = NewId("group-a"); - var groupBId = NewId("group-b"); - var leafId = NewId("leaf"); - var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId, leafId]); - var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupAId]); - var leaf = CoreConfigTestFactory.CreateSocksNode(ECoreType.Xray, leafId, "leaf"); + var groupAId = NewId("group-a"); + var groupBId = NewId("group-b"); + var leafId = NewId("leaf"); + var groupA = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupAId, "group-a", [groupBId, leafId]); + var groupB = CoreConfigTestFactory.CreatePolicyGroupNode(ECoreType.Xray, groupBId, "group-b", [groupAId]); + var leaf = CoreConfigTestFactory.CreateSocksNode(ECoreType.Xray, leafId, "leaf"); - await UpsertProfilesAsync(groupA, groupB, leaf); + await UpsertProfilesAsync(groupA, groupB, leaf); - var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); - context.AllProxiesMap.Clear(); + var context = CoreConfigTestFactory.CreateContext(config, groupA, ECoreType.Xray); + context.AllProxiesMap.Clear(); - var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); + var (_, validatorResult) = await CoreConfigContextBuilder.ResolveNodeAsync(context, groupA, false); - validatorResult.Success.Should().BeTrue(); - validatorResult.Errors.Should().BeEmpty(); - validatorResult.Warnings.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); + validatorResult.Success.Should().BeTrue(); + validatorResult.Errors.Should().BeEmpty(); + validatorResult.Warnings.Should().Contain(msg => ContainsCycleDependencyMessage(msg)); - context.AllProxiesMap.Should().ContainKey(leaf.IndexId); - context.AllProxiesMap.Should().ContainKey(groupA.IndexId); - context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); - groupA.GetProtocolExtra().ChildItems.Should().Be(leaf.IndexId); - } + context.AllProxiesMap.Should().ContainKey(leaf.IndexId); + context.AllProxiesMap.Should().ContainKey(groupA.IndexId); + context.AllProxiesMap.Should().NotContainKey(groupB.IndexId); + groupA.GetProtocolExtra().ChildItems.Should().Be(leaf.IndexId); + } - private static string NewId(string prefix) - { - return $"{prefix}-{Guid.NewGuid():N}"; - } + private static string NewId(string prefix) + { + return $"{prefix}-{Guid.NewGuid():N}"; + } - private static bool ContainsCycleDependencyMessage(string message) - { - return message.Contains("cycle dependency", StringComparison.OrdinalIgnoreCase) - || message.Contains("循环依赖", StringComparison.Ordinal) - || message.Contains("循環依賴", StringComparison.Ordinal); - } + private static bool ContainsCycleDependencyMessage(string message) + { + return message.Contains("cycle dependency", StringComparison.OrdinalIgnoreCase) + || message.Contains("循环依赖", StringComparison.Ordinal) + || message.Contains("循環依賴", StringComparison.Ordinal); + } - private static async Task UpsertProfilesAsync(params ProfileItem[] profiles) - { - SQLiteHelper.Instance.CreateTable(); - foreach (var profile in profiles) - { - await SQLiteHelper.Instance.ReplaceAsync(profile); - } - } + private static async Task UpsertProfilesAsync(params ProfileItem[] profiles) + { + SQLiteHelper.Instance.CreateTable(); + foreach (var profile in profiles) + { + await SQLiteHelper.Instance.ReplaceAsync(profile); + } + } } diff --git a/v2rayN/ServiceLib.Tests/CoreConfig/CoreConfigTestFactory.cs b/v2rayN/ServiceLib.Tests/CoreConfig/CoreConfigTestFactory.cs index c5acd854..812a5a32 100644 --- a/v2rayN/ServiceLib.Tests/CoreConfig/CoreConfigTestFactory.cs +++ b/v2rayN/ServiceLib.Tests/CoreConfig/CoreConfigTestFactory.cs @@ -1,7 +1,7 @@ +using System.Reflection; using ServiceLib.Enums; using ServiceLib.Manager; using ServiceLib.Models; -using System.Reflection; namespace ServiceLib.Tests.CoreConfig; @@ -33,7 +33,10 @@ internal static class CoreConfigTestFactory UiItem = new UIItem { - CurrentLanguage = "en", CurrentFontFamily = "sans", MainColumnItem = [], WindowSizeItem = [] + CurrentLanguage = "en", + CurrentFontFamily = "sans", + MainColumnItem = [], + WindowSizeItem = [] }, ConstItem = new ConstItem(), SpeedTestItem = new SpeedTestItem @@ -51,7 +54,8 @@ internal static class CoreConfigTestFactory SystemProxyItem = new SystemProxyItem { - SystemProxyExceptions = string.Empty, SystemProxyAdvancedProtocol = string.Empty + SystemProxyExceptions = string.Empty, + SystemProxyAdvancedProtocol = string.Empty }, WebDavItem = new WebDavItem(), CheckUpdateItem = new CheckUpdateItem(), @@ -131,11 +135,15 @@ internal static class CoreConfigTestFactory { var node = new ProfileItem { - IndexId = indexId, ConfigType = EConfigType.PolicyGroup, CoreType = coreType, Remarks = remarks, + IndexId = indexId, + ConfigType = EConfigType.PolicyGroup, + CoreType = coreType, + Remarks = remarks, }; node.SetProtocolExtra(node.GetProtocolExtra() with { - GroupType = nameof(EConfigType.PolicyGroup), ChildItems = string.Join(",", childIndexIds), + GroupType = nameof(EConfigType.PolicyGroup), + ChildItems = string.Join(",", childIndexIds), }); return node; @@ -146,11 +154,15 @@ internal static class CoreConfigTestFactory { var node = new ProfileItem { - IndexId = indexId, ConfigType = EConfigType.ProxyChain, CoreType = coreType, Remarks = remarks, + IndexId = indexId, + ConfigType = EConfigType.ProxyChain, + CoreType = coreType, + Remarks = remarks, }; node.SetProtocolExtra(node.GetProtocolExtra() with { - GroupType = nameof(EConfigType.ProxyChain), ChildItems = string.Join(",", childIndexIds), + GroupType = nameof(EConfigType.ProxyChain), + ChildItems = string.Join(",", childIndexIds), }); return node; diff --git a/v2rayN/ServiceLib.Tests/Fmt/FmtHandlerTests.cs b/v2rayN/ServiceLib.Tests/Fmt/FmtHandlerTests.cs index 56fb0f97..143fa3e5 100644 --- a/v2rayN/ServiceLib.Tests/Fmt/FmtHandlerTests.cs +++ b/v2rayN/ServiceLib.Tests/Fmt/FmtHandlerTests.cs @@ -1,7 +1,7 @@ using AwesomeAssertions; +using ServiceLib.Enums; using ServiceLib.Handler.Fmt; using ServiceLib.Models; -using ServiceLib.Enums; using Xunit; namespace ServiceLib.Tests.Fmt; @@ -92,7 +92,7 @@ public class FmtHandlerTests var uri = FmtHandler.GetShareUri(source); uri.Should().NotBeNullOrWhiteSpace(); - (uri!.StartsWith(Global.ProtocolShares[source.ConfigType], StringComparison.OrdinalIgnoreCase)).Should() + uri!.StartsWith(Global.ProtocolShares[source.ConfigType], StringComparison.OrdinalIgnoreCase).Should() .BeTrue(); var resolved = FmtHandler.ResolveConfig(uri, out var msg); diff --git a/v2rayN/ServiceLib.UdpTest/Socks5UdpChannel.cs b/v2rayN/ServiceLib.UdpTest/Socks5UdpChannel.cs index 51a5b3ed..f9a2951f 100644 --- a/v2rayN/ServiceLib.UdpTest/Socks5UdpChannel.cs +++ b/v2rayN/ServiceLib.UdpTest/Socks5UdpChannel.cs @@ -239,7 +239,9 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl var clientAddrForSocks = new Socks5AddressData { - AddressType = Socks5AddressData.AddrTypeIPv4, Host = "0.0.0.0", Port = 0 + AddressType = Socks5AddressData.AddrTypeIPv4, + Host = "0.0.0.0", + Port = 0 }; using var udpAssociateReqMs = new MemoryStream(); udpAssociateReqMs.WriteByte(Socks5Version); @@ -267,7 +269,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl return true; } - #endregion + #endregion SOCKS5 Connection Handling #region SOCKS5 Address Handling @@ -298,6 +300,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl } break; + case AddrTypeDomain: if (string.IsNullOrEmpty(Host)) { @@ -311,6 +314,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl } break; + case AddrTypeIPv6: if (IPAddress.TryParse(Host, out var ip6) && ip6.AddressFamily == AddressFamily.InterNetworkV6) { @@ -322,6 +326,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl } break; + default: throw new NotSupportedException($"SOCKS5 address type {AddressType} not supported."); } @@ -355,6 +360,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl addr.Host = new IPAddress(ipv4Bytes).ToString(); break; + case AddrTypeDomain: var lenByte = new byte[1]; if (await stream.ReadAsync(lenByte.AsMemory(0, 1), ct).ConfigureAwait(false) < 1) @@ -379,6 +385,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl } break; + case AddrTypeIPv6: var ipv6Bytes = new byte[16]; if (await stream.ReadAsync(ipv6Bytes.AsMemory(0, 16), ct).ConfigureAwait(false) < 16) @@ -388,6 +395,7 @@ public class Socks5UdpChannel(string socks5Host, int socks5TcpPort) : IDisposabl addr.Host = new IPAddress(ipv6Bytes).ToString(); break; + default: return null; } diff --git a/v2rayN/ServiceLib.UdpTest/Tester/DnsService.cs b/v2rayN/ServiceLib.UdpTest/Tester/DnsService.cs index a6f5d910..81bea2b8 100644 --- a/v2rayN/ServiceLib.UdpTest/Tester/DnsService.cs +++ b/v2rayN/ServiceLib.UdpTest/Tester/DnsService.cs @@ -4,6 +4,7 @@ public class DnsService : IUdpTest { private const int DnsDefaultPort = 53; private const string DnsDefaultServer = "8.8.8.8"; // Google Public DNS + private static readonly byte[] DnsQueryPacket = [ // Header: ID=0x1234, Standard query with RD set, QDCOUNT=1 diff --git a/v2rayN/ServiceLib.UdpTest/Tester/IUdpTest.cs b/v2rayN/ServiceLib.UdpTest/Tester/IUdpTest.cs index 550f712e..af3fa6c5 100644 --- a/v2rayN/ServiceLib.UdpTest/Tester/IUdpTest.cs +++ b/v2rayN/ServiceLib.UdpTest/Tester/IUdpTest.cs @@ -3,7 +3,10 @@ namespace ServiceLib.UdpTest.Tester; public interface IUdpTest { public byte[] BuildUdpRequestPacket(); + public bool VerifyAndExtractUdpResponse(byte[] udpResponseBytes); + public ushort GetDefaultTargetPort(); + public string GetDefaultTargetHost(); } diff --git a/v2rayN/ServiceLib.UdpTest/Tester/McBeService.cs b/v2rayN/ServiceLib.UdpTest/Tester/McBeService.cs index 777928b1..b4ec0221 100644 --- a/v2rayN/ServiceLib.UdpTest/Tester/McBeService.cs +++ b/v2rayN/ServiceLib.UdpTest/Tester/McBeService.cs @@ -4,6 +4,7 @@ public class McBeService : IUdpTest { private const int McBeDefaultPort = 19132; private const string McBeDefaultServer = "pms.mc-complex.com"; + // 0x01 | client alive time in ms (unsigned long long) | magic | client GUID private static readonly byte[] McBeQueryPacket = [ @@ -18,11 +19,13 @@ public class McBeService : IUdpTest 0x66, 0x0E, 0xAB, 0xBC, 0x61, 0x0D, 0x1F, 0x4E, 0xA4, 0x40, 0x8C, 0x65, 0xC1, 0xBE, 0xF5, 0x4B ]; + private static readonly byte[] McBeMagicBytes = [ 0x00, 0xFF, 0xFF, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0x12, 0x34, 0x56, 0x78 ]; + private static readonly List ValidGameModes = [ "Survival", @@ -40,9 +43,9 @@ public class McBeService : IUdpTest { // 0x1c | client alive time in ms (recorded from previous ping) | // server GUID | Magic | string length | Edition - // + // // Edition Example: - // + // // MCPE;Dedicated Server;527;1.19.1;0;10;13253860892328930865;Bedrock level;Survival;1;19132;19133; if (mcbeResponseBytes.Length < 48) { diff --git a/v2rayN/ServiceLib.UdpTest/Tester/StunService.cs b/v2rayN/ServiceLib.UdpTest/Tester/StunService.cs index 1dc4d3e7..c6b925a3 100644 --- a/v2rayN/ServiceLib.UdpTest/Tester/StunService.cs +++ b/v2rayN/ServiceLib.UdpTest/Tester/StunService.cs @@ -4,6 +4,7 @@ public class StunService : IUdpTest { private const int StunDefaultPort = 3478; private const string StunDefaultServer = "stun.voztovoice.org"; + private static readonly byte[] StunBindingRequestPacket = [ // STUN Binding Request diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs index 312140d6..8de3d925 100644 --- a/v2rayN/ServiceLib/Global.cs +++ b/v2rayN/ServiceLib/Global.cs @@ -691,14 +691,6 @@ public class Global "" ]; - public static readonly List EchForceQuerys = - [ - "none", - "half", - "full", - "" - ]; - public static readonly List TunIcmpRoutingPolicies = [ "rule", diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index d319118f..12523ddf 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -256,7 +256,6 @@ public static class ConfigHandler item.Cert = profileItem.Cert; item.CertSha = profileItem.CertSha; item.EchConfigList = profileItem.EchConfigList; - item.EchForceQuery = profileItem.EchForceQuery; 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 722d97f5..ff7d6d20 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs @@ -5,6 +5,7 @@ namespace ServiceLib.Handler.Fmt; public class BaseFmt { private static readonly string[] _allowInsecureArray = new[] { "insecure", "allowInsecure", "allow_insecure" }; + private static string UrlEncodeSafe(string? value) => Utils.UrlEncode(value ?? string.Empty); protected static string GetIpv6(string address) diff --git a/v2rayN/ServiceLib/Models/ProfileItem.cs b/v2rayN/ServiceLib/Models/ProfileItem.cs index 6fe44a3b..ae5f77ad 100644 --- a/v2rayN/ServiceLib/Models/ProfileItem.cs +++ b/v2rayN/ServiceLib/Models/ProfileItem.cs @@ -191,7 +191,6 @@ public class ProfileItem public string Cert { get; set; } public string CertSha { get; set; } public string EchConfigList { get; set; } - public string EchForceQuery { get; set; } public string Finalmask { get; set; } public string ProtoExtra { get; set; } diff --git a/v2rayN/ServiceLib/Models/SingboxConfig.cs b/v2rayN/ServiceLib/Models/SingboxConfig.cs index 06449224..2282e830 100644 --- a/v2rayN/ServiceLib/Models/SingboxConfig.cs +++ b/v2rayN/ServiceLib/Models/SingboxConfig.cs @@ -237,6 +237,7 @@ public class Transport4Sbox public class Headers4Sbox { public string? Host { get; set; } + [JsonPropertyName("User-Agent")] public string UserAgent { get; set; } } diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index b6aaa2df..26739b69 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -500,12 +500,16 @@ public class MaskSettings4Ray { public string? password { get; set; } public string? domain { get; set; } + // fragment public string? packets { get; set; } + public string? length { get; set; } public string? delay { get; set; } + // noise public int? reset { get; set; } + public List? noise { get; set; } } @@ -533,6 +537,7 @@ public class AccountsItem4Ray public class Sockopt4Ray { public string? dialerProxy { get; set; } + [JsonPropertyName("interface")] public string? Interface { get; set; } } diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 616574e5..56f95191 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -2881,7 +2881,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。 + /// 查找类似 Please fill in DNS Object; Click to view documentation 的本地化字符串。 /// public static string TbDnsObjectDoc { get { @@ -2943,15 +2943,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 EchForceQuery 的本地化字符串。 - /// - public static string TbEchForceQuery { - get { - return ResourceManager.GetString("TbEchForceQuery", resourceCulture); - } - } - /// /// 查找类似 Edit 的本地化字符串。 /// @@ -4158,15 +4149,6 @@ namespace ServiceLib.Resx { } } - /// - /// 查找类似 Custom DNS (multiple, separated by commas (,)) 的本地化字符串。 - /// - public static string TbSettingsRemoteDNS { - get { - return ResourceManager.GetString("TbSettingsRemoteDNS", resourceCulture); - } - } - /// /// 查找类似 Route Only 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index bd4c9fea..f2818543 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -720,9 +720,6 @@ مجوز احراز هویت - - سفارشی DNS (multiple, separated by commas (,)) - تنظیم کردن Win10 UWP Loopback @@ -1584,9 +1581,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if EchConfigList - - EchForceQuery - Full certificate (chain), PEM format diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 9533c895..1a782f98 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -720,9 +720,6 @@ Mot de passe d’authentification - - DNS perso (plusieurs configurables, séparés par virgules) - Lever la restriction de proxy en boucle locale pour les applications Win10 UWP @@ -1590,9 +1587,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if EchConfigList - - EchForceQuery - Certificat complet (chaîne), format PEM diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 85fa0101..dbd24707 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -720,9 +720,6 @@ Hitelesítési jelszó - - Egyéni DNS (több, vesszővel (,) elválasztva) - Win10 UWP Loopback beállítása @@ -1584,9 +1581,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if EchConfigList - - EchForceQuery - Full certificate (chain), PEM format diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index db4e9222..b3cbc87e 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -720,9 +720,6 @@ Auth pass - - Custom DNS (multiple, separated by commas (,)) - Set Win10 UWP Loopback @@ -862,7 +859,7 @@ Rule object Doc - Supports DNS Object; Click to view documentation + Please fill in DNS Object; Click to view documentation For group please leave blank here @@ -1593,9 +1590,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if EchConfigList - - EchForceQuery - Full certificate (chain), PEM format diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 0b64698c..8f234843 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -673,7 +673,7 @@ Ядро: базовые настройки - Пользовательский DNS для V2ray + Пользовательский DNS для v2ray Ядро: настройки KCP @@ -720,9 +720,6 @@ Пароль авторизации - - Пользовательский DNS (если несколько, то делите запятыми (,)) - Разрешить loopback для приложений UWP (Win10) @@ -934,7 +931,7 @@ User-Agent - This parameter is valid only for raw/http, ws, gRPC and xhttp + Параметр действует только для raw/http, ws, gRPC и xhttp Шрифт (требуется перезапуск) @@ -1321,7 +1318,7 @@ XHTTP-режим - Raw JSON, format: { XHTTP Object } + Сырой JSON, формат: { XHTTP Object } Сворачивать в трей при закрытии окна @@ -1339,7 +1336,7 @@ Включить второй смешанный порт - socks: локальный порт, socks2: второй локальный порт, socks3: LAN порт + socks: локальный порт, socks2: второй локальный порт, socks3: LAN-порт Тема @@ -1381,7 +1378,7 @@ Mldsa65Verify - Добавить сервер [Anytls] + Добавить сервер [AnyTLS] Удалённый DNS @@ -1584,9 +1581,6 @@ EchConfigList - - EchForceQuery - Полный сертификат (цепочка) в формате PEM @@ -1696,27 +1690,33 @@ Устаревшая защита TUN (Legacy Protect) - For multi-interface environments, enter the local machine's IPv4 address + Для среды с несколькими сетевыми интерфейсами укажите IPv4-адрес локального компьютера Камуфляжный домен - Host + Хост - XHTTP Extra + Дополнительные параметры XHTTP (Extra) - Allow insecure cert fetch (self-signed) + Разрешить небезопасную загрузку сертификата (самоподписанного) - Only for fetching self-signed certificates. This may expose you to MITM risks. + Только для загрузки самоподписанных сертификатов. Это может подвергнуть вас риску атаки «человек посередине» (MITM). - Test Configurations UDP Delay + Тест UDP-задержки конфигураций - UDP Test Url + URL для UDP-теста - \ No newline at end of file + + Укажите корректный IPv4-адрес для SendThrough. + + + Локальный исходящий адрес (SendThrough) + + diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 42aa942b..4e2bd39d 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -720,9 +720,6 @@ 认证密码 - - 自定义 DNS (可多个,用逗号 (,) 分隔) - 解除 Win10 UWP 应用回环代理限制 @@ -862,7 +859,7 @@ 规则详细说明文档 - 支持填写 DnsObject,JSON 格式,点击查看文档 + 请填写 DnsObject,JSON 格式,点击查看文档 普通分组此处请留空 @@ -1590,9 +1587,6 @@ EchConfigList - - EchForceQuery - 完整证书(链),PEM 格式 diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index e5f34cf6..14cbec63 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -720,9 +720,6 @@ 認證密碼 - - 自訂 DNS (可多個,用逗號 (,) 分隔) - 解除 Win10 UWP 應用回環代理限制 @@ -862,7 +859,7 @@ 規則詳細說明檔案 - 支援填寫 DnsObject,JSON 格式,點擊查看說明 + 請填寫 DnsObject,JSON 格式,點擊查看說明 普通分組此處請留空 @@ -1581,9 +1578,6 @@ EchConfigList - - EchForceQuery - 完整憑證(鏈),PEM 格式 diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index ef22d545..d8985ccc 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -383,7 +383,6 @@ public partial class CoreConfigV2rayService alpn = _node.GetAlpn(), fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint, echConfigList = _node.EchConfigList.NullIfEmpty(), - echForceQuery = _node.EchForceQuery.NullIfEmpty() }; if (sni.IsNotEmpty()) { @@ -393,6 +392,11 @@ public partial class CoreConfigV2rayService { tlsSettings.serverName = Utils.String2List(host)?.First(); } + if (!tlsSettings.echConfigList.IsNullOrEmpty()) + { + // For legacy xray compatibility, remove this in the future + tlsSettings.echForceQuery = "full"; + } var certs = CertPemManager.ParsePemChain(_node.Cert); if (certs.Count > 0) { @@ -548,6 +552,7 @@ public partial class CoreConfigV2rayService FillOutboundMux(outbound); break; + case nameof(ETransport.grpc): GrpcSettings4Ray grpcSettings = new() { diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs index 1d690530..d77761ac 100644 --- a/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayN/ServiceLib/Services/UpdateService.cs @@ -299,7 +299,6 @@ public class UpdateService(Config config, Func updateFunc) return url; } - else if (Utils.IsLinux()) { return RuntimeInformation.ProcessArchitecture switch @@ -310,7 +309,6 @@ public class UpdateService(Config config, Func updateFunc) _ => null, }; } - else if (Utils.IsMacOS()) { return RuntimeInformation.ProcessArchitecture switch diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml index 00bcff1b..3ab748b1 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml @@ -306,7 +306,7 @@ x:Name="txtSecurity5" Grid.Row="3" Grid.Column="1" - Width="200" + Width="400" Margin="{StaticResource Margin4}" HorizontalAlignment="Left" /> @@ -1115,19 +1115,6 @@ Margin="{StaticResource Margin4}" HorizontalAlignment="Left" /> - - - cmbFingerprint2.ItemsSource = Global.Fingerprints; cmbAllowInsecure.ItemsSource = Global.AllowInsecure; cmbAlpn.ItemsSource = Global.Alpns; - cmbEchForceQuery.ItemsSource = Global.EchForceQuerys; - var lstStreamSecurity = new List(); - lstStreamSecurity.Add(string.Empty); - lstStreamSecurity.Add(Global.StreamSecurity); + var lstStreamSecurity = new List { string.Empty, Global.StreamSecurity }; switch (profileItem.ConfigType) { @@ -246,7 +243,6 @@ public partial class AddServerWindow : WindowBase 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.EchForceQuery, v => v.cmbEchForceQuery.SelectedValue).DisposeWith(disposables); //reality this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); @@ -338,21 +334,27 @@ public partial class AddServerWindow : WindowBase case nameof(ETransport.raw): gridTransportRaw.IsVisible = true; break; + case nameof(ETransport.kcp): gridTransportKcp.IsVisible = true; break; + case nameof(ETransport.ws): gridTransportWs.IsVisible = true; break; + case nameof(ETransport.httpupgrade): gridTransportHttpupgrade.IsVisible = true; break; + case nameof(ETransport.xhttp): gridTransportXhttp.IsVisible = true; break; + case nameof(ETransport.grpc): gridTransportGrpc.IsVisible = true; break; + default: gridTransportRaw.IsVisible = true; break; diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml index 1b2a691c..b736de32 100644 --- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml @@ -342,11 +342,6 @@ - - @@ -494,7 +489,6 @@ Header="{x:Static resx:ResUI.TbSettingsTunMode}"> - diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs index 11af7506..544a7242 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs @@ -64,7 +64,10 @@ public partial class RoutingSettingWindow : WindowBase private void RoutingSettingWindow_Closing(object? sender, WindowClosingEventArgs e) { - if (_closed) return; + if (_closed) + { + return; + } // DomainStrategy is auto-saved reactively; just ensure the caller knows changes were made if (ViewModel?.IsModified == true) diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs index 2d663eb1..1d2061cd 100644 --- a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs @@ -137,7 +137,7 @@ public class ThemeSettingViewModel : MyReactiveObject private void ModifyFontSize() { - double size = (long)CurrentFontSize; + double size = CurrentFontSize; if (size < Global.MinFontSize) { return; diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml index 4efb6b94..047d32e4 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml @@ -415,7 +415,7 @@ x:Name="txtSecurity5" Grid.Row="3" Grid.Column="1" - Width="200" + Width="400" Margin="{StaticResource Margin4}" HorizontalAlignment="Left" Style="{StaticResource DefTextBox}" /> @@ -1444,21 +1444,6 @@ HorizontalAlignment="Left" Style="{StaticResource DefTextBox}" /> - - - (); - lstStreamSecurity.Add(string.Empty); - lstStreamSecurity.Add(Global.StreamSecurity); + var lstStreamSecurity = new List { string.Empty, Global.StreamSecurity }; switch (profileItem.ConfigType) { @@ -247,7 +244,6 @@ public partial class AddServerWindow .BindTo(this, v => 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.EchForceQuery, v => v.cmbEchForceQuery.Text).DisposeWith(disposables); //reality this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); @@ -340,21 +336,27 @@ public partial class AddServerWindow case nameof(ETransport.raw): gridTransportRaw.Visibility = Visibility.Visible; break; + case nameof(ETransport.kcp): gridTransportKcp.Visibility = Visibility.Visible; break; + case nameof(ETransport.ws): gridTransportWs.Visibility = Visibility.Visible; break; + case nameof(ETransport.httpupgrade): gridTransportHttpupgrade.Visibility = Visibility.Visible; break; + case nameof(ETransport.xhttp): gridTransportXhttp.Visibility = Visibility.Visible; break; + case nameof(ETransport.grpc): gridTransportGrpc.Visibility = Visibility.Visible; break; + default: gridTransportRaw.Visibility = Visibility.Visible; break; diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml index d27188a4..d2bdcb9b 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml @@ -390,11 +390,6 @@ - + Application.Current?.Dispatcher.Invoke(() => { ShowHideWindow(true); - })); + }); } private async Task DelegateSnackMsg(string content)