From 35b98f945fb2628d5aca5adf050f53703aea7501 Mon Sep 17 00:00:00 2001 From: DHR60 Date: Sun, 19 Apr 2026 05:42:55 +0000 Subject: [PATCH] Support new fragment (#9122) --- v2rayN/ServiceLib/Handler/ConfigHandler.cs | 2 +- v2rayN/ServiceLib/Models/V2rayConfig.cs | 18 +++- .../CoreConfig/V2ray/V2rayOutboundService.cs | 97 +++++++++++++------ 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index da7258a7..a49f12f7 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -162,7 +162,7 @@ public static class ConfigHandler config.Fragment4RayItem ??= new() { Packets = "tlshello", - Length = "100-200", + Length = "50-100", Interval = "10-20" }; config.GlobalHotkeys ??= new(); diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index 909a37fb..b6aaa2df 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -140,11 +140,10 @@ public class Outboundsettings4Ray public int? userLevel { get; set; } - public FragmentItem4Ray? fragment { get; set; } - public string? secretKey { get; set; } - public Object? address { get; set; } + public object? address { get; set; } + public int? port { get; set; } public List? peers { get; set; } @@ -501,6 +500,19 @@ 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; } +} + +public class NoiseMask4Ray +{ + public string? rand { get; set; } + public string? delay { get; set; } } public class QuicParams4Ray diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index d40ed8a3..8b3da6b5 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -12,6 +12,10 @@ public partial class CoreConfigV2rayService GenObservatory(multipleLoad); GenBalancer(multipleLoad); } + if (_config.CoreBasicItem.EnableFragment) + { + ApplyOutboundFragment(); + } if (context.IsTunEnabled) { _coreConfig.outbounds.Add(BuildDnsOutbound()); @@ -29,35 +33,6 @@ public partial class CoreConfigV2rayService { proxyOutboundList.Add(BuildProxyOutbound(baseTagName)); } - - if (_config.CoreBasicItem.EnableFragment) - { - var fragmentOutbound = new Outbounds4Ray - { - protocol = "freedom", - tag = $"frag-{baseTagName}", - settings = new() - { - fragment = new() - { - packets = _config.Fragment4RayItem?.Packets, - length = _config.Fragment4RayItem?.Length, - interval = _config.Fragment4RayItem?.Interval - } - } - }; - var actOutboundWithTlsList = - proxyOutboundList.Where(n => n.streamSettings?.security.IsNullOrEmpty() == false - && (n.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true)).ToList(); - if (actOutboundWithTlsList.Count > 0) - { - proxyOutboundList.Add(fragmentOutbound); - } - foreach (var outbound in actOutboundWithTlsList) - { - FillDialerProxy(outbound, fragmentOutbound.tag); - } - } return proxyOutboundList; } @@ -837,4 +812,68 @@ public partial class CoreConfigV2rayService var outbound = new Outbounds4Ray { tag = Global.DnsOutboundTag, protocol = "dns", }; return outbound; } + + private void ApplyOutboundFragment() + { + var actOutboundWithTlsList = + _coreConfig.outbounds.Where(n => n.streamSettings?.security.IsNullOrEmpty() == false + && (n.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true)) + .ToList(); + + var configPackets = _config.Fragment4RayItem?.Packets ?? "tlshello"; + var configLength = _config.Fragment4RayItem?.Length ?? "50-100"; + var configDelay = _config.Fragment4RayItem?.Interval ?? "10-20"; + + var fragmentMask = new Mask4Ray + { + type = "fragment", + settings = new MaskSettings4Ray + { + packets = configPackets, + length = configLength, + delay = configDelay, + } + }; + var noiseMask = new Mask4Ray + { + type = "noise", + settings = new MaskSettings4Ray + { + length = "10-20", + delay = "10-16", + } + }; + + foreach (var outbound in actOutboundWithTlsList) + { + //var packets = configPackets; + //if (outbound.streamSettings.security == Global.StreamSecurityReality + // && packets == "tlshello") + //{ + // packets = "1-3"; + //} + //else if (outbound.streamSettings.security == Global.StreamSecurity + // && packets != "tlshello") + //{ + // packets = "tlshello"; + //} + var finalMaskJsonObj = JsonUtils.ParseJson(JsonUtils.Serialize(outbound.streamSettings?.finalmask)) as JsonObject ?? new JsonObject(); + // tcp fragment + var tcpFinalmaskList = finalMaskJsonObj["tcp"] as JsonArray ?? []; + if (tcpFinalmaskList.Count == 0) + { + tcpFinalmaskList.Add(JsonUtils.SerializeToNode(fragmentMask)); + finalMaskJsonObj["tcp"] = tcpFinalmaskList; + } + // udp noise + var udpFinalmaskList = finalMaskJsonObj["udp"] as JsonArray ?? []; + if (udpFinalmaskList.Count == 0) + { + udpFinalmaskList.Add(JsonUtils.SerializeToNode(noiseMask)); + finalMaskJsonObj["udp"] = udpFinalmaskList; + } + // write back + outbound.streamSettings.finalmask = finalMaskJsonObj; + } + } }