From ad11a7e6a5373c6e811a759102fec4e060b7d9d2 Mon Sep 17 00:00:00 2001 From: DHR60 Date: Tue, 24 Mar 2026 03:24:42 +0000 Subject: [PATCH] Support new hysteria2 stream settings (#8908) * Support new hysteria2 stream settings * Fix * Sync --- v2rayN/ServiceLib/Models/V2rayConfig.cs | 21 ++++--- .../Singbox/SingboxOutboundService.cs | 9 +-- .../CoreConfig/V2ray/V2rayOutboundService.cs | 59 +++++++++++-------- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index a6e6e8c7..4d3f9512 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -337,7 +337,7 @@ public class StreamSettings4Ray public HysteriaSettings4Ray? hysteriaSettings { get; set; } - public Finalmask4Ray? finalmask { get; set; } + public object? finalmask { get; set; } public Sockopt4Ray? sockopt { get; set; } } @@ -462,27 +462,24 @@ public class HysteriaSettings4Ray { public int version { get; set; } public string? auth { get; set; } - public string? up { get; set; } - public string? down { get; set; } - public HysteriaUdpHop4Ray? udphop { get; set; } } -public class HysteriaUdpHop4Ray +public class UdpHop4Ray { - public string? port { get; set; } + public string? ports { get; set; } public string? interval { get; set; } } public class Finalmask4Ray { - public List? tcp { get; set; } public List? udp { get; set; } + public QuicParams4Ray? quicParams { get; set; } } public class Mask4Ray { public string type { get; set; } - public object? settings { get; set; } + public MaskSettings4Ray? settings { get; set; } } public class MaskSettings4Ray @@ -491,6 +488,14 @@ public class MaskSettings4Ray public string? domain { get; set; } } +public class QuicParams4Ray +{ + public string? congestion { get; set; } + public string? brutalUp { get; set; } + public string? brutalDown { get; set; } + public UdpHop4Ray? udpHop { get; set; } +} + public class AccountsItem4Ray { public string user { get; set; } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 99fbba90..0fc9733c 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -224,13 +224,14 @@ public partial class CoreConfigSingboxService password = protocolExtra.SalamanderPass.TrimEx(), }; } - - outbound.up_mbps = protocolExtra?.UpMbps is { } su and >= 0 + int? upMbps = protocolExtra?.UpMbps is { } su and >= 0 ? su : _config.HysteriaItem.UpMbps; - outbound.down_mbps = protocolExtra?.DownMbps is { } sd and >= 0 + int? downMbps = protocolExtra?.DownMbps is { } sd and >= 0 ? sd - : _config.HysteriaItem.DownMbps; + : _config.HysteriaItem.UpMbps; + outbound.up_mbps = upMbps > 0 ? upMbps : null; + outbound.down_mbps = downMbps > 0 ? downMbps : null; var ports = protocolExtra?.Ports?.IsNullOrEmpty() == false ? protocolExtra.Ports : null; if ((!ports.IsNullOrEmpty()) && (ports.Contains(':') || ports.Contains('-') || ports.Contains(','))) { diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index 98fda303..e9241030 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -441,10 +441,10 @@ public partial class CoreConfigV2rayService kcpSettings.congestion = _config.KcpItem.Congestion; kcpSettings.readBufferSize = _config.KcpItem.ReadBufferSize; kcpSettings.writeBufferSize = _config.KcpItem.WriteBufferSize; - streamSettings.finalmask ??= new(); + var kcpFinalmask = new Finalmask4Ray(); if (Global.KcpHeaderMaskMap.TryGetValue(_node.HeaderType, out var header)) { - streamSettings.finalmask.udp = + kcpFinalmask.udp = [ new Mask4Ray { @@ -453,23 +453,24 @@ public partial class CoreConfigV2rayService } ]; } - streamSettings.finalmask.udp ??= []; + kcpFinalmask.udp ??= []; if (path.IsNullOrEmpty()) { - streamSettings.finalmask.udp.Add(new Mask4Ray + kcpFinalmask.udp.Add(new Mask4Ray { type = "mkcp-original" }); } else { - streamSettings.finalmask.udp.Add(new Mask4Ray + kcpFinalmask.udp.Add(new Mask4Ray { type = "mkcp-aes128gcm", settings = new MaskSettings4Ray { password = path } }); } streamSettings.kcpSettings = kcpSettings; + streamSettings.finalmask = kcpFinalmask; break; //ws case nameof(ETransport.ws): @@ -598,36 +599,46 @@ public partial class CoreConfigV2rayService : (_config.HysteriaItem.HopInterval >= 5 ? _config.HysteriaItem.HopInterval : Global.Hysteria2DefaultHopInt).ToString(); - HysteriaUdpHop4Ray? udpHop = null; + var hy2Finalmask = new Finalmask4Ray(); + var quicParams = new QuicParams4Ray(); if (!ports.IsNullOrEmpty() && (ports.Contains(':') || ports.Contains('-') || ports.Contains(','))) { - udpHop = new HysteriaUdpHop4Ray + var udpHop = new UdpHop4Ray { - port = ports.Replace(':', '-'), + ports = ports.Replace(':', '-'), interval = hopInterval, }; + quicParams.udpHop = udpHop; + } + if (upMbps > 0 || downMbps > 0) + { + quicParams.congestion = "brutal"; + quicParams.brutalUp = upMbps > 0 ? $"{upMbps}mbps" : null; + quicParams.brutalDown = downMbps > 0 ? $"{downMbps}mbps" : null; + } + else + { + quicParams.congestion = "bbr"; + } + hy2Finalmask.quicParams = quicParams; + if (!protocolExtra.SalamanderPass.IsNullOrEmpty()) + { + hy2Finalmask.udp = + [ + new Mask4Ray + { + type = "salamander", + settings = new MaskSettings4Ray { password = protocolExtra.SalamanderPass.TrimEx(), } + } + ]; } streamSettings.hysteriaSettings = new() { version = 2, auth = _node.Password, - up = upMbps > 0 ? $"{upMbps}mbps" : null, - down = downMbps > 0 ? $"{downMbps}mbps" : null, - udphop = udpHop, }; - if (!protocolExtra.SalamanderPass.IsNullOrEmpty()) - { - streamSettings.finalmask ??= new(); - streamSettings.finalmask.udp = - [ - new Mask4Ray - { - type = "salamander", - settings = new MaskSettings4Ray { password = protocolExtra.SalamanderPass.TrimEx(), } - } - ]; - } + streamSettings.finalmask = hy2Finalmask; break; default: @@ -665,7 +676,7 @@ public partial class CoreConfigV2rayService if (!_node.Finalmask.IsNullOrEmpty()) { - streamSettings.finalmask = JsonUtils.Deserialize(_node.Finalmask); + streamSettings.finalmask = JsonUtils.ParseJson(_node.Finalmask); } } catch (Exception ex)