From ecf8b8f939a1ff44c754f91f3e03f013b72d6d35 Mon Sep 17 00:00:00 2001 From: DHR60 Date: Sun, 8 Mar 2026 16:36:55 +0800 Subject: [PATCH] Support new hysteria2 stream settings --- v2rayN/ServiceLib/Models/V2rayConfig.cs | 19 ++++--- .../CoreConfig/V2ray/V2rayOutboundService.cs | 57 +++++++++++-------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index 2393d5fb..40a64c1d 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -335,7 +335,7 @@ public class StreamSettings4Ray public HysteriaSettings4Ray? hysteriaSettings { get; set; } - public Finalmask4Ray? finalmask { get; set; } + public object? finalmask { get; set; } public Sockopt4Ray? sockopt { get; set; } } @@ -459,12 +459,9 @@ 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? interval { get; set; } @@ -472,14 +469,14 @@ public class HysteriaUdpHop4Ray 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 @@ -488,6 +485,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/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index c8862648..ca58623a 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -440,10 +440,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 { @@ -452,23 +452,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): @@ -597,36 +598,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(':', '-'), 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: @@ -664,7 +675,7 @@ public partial class CoreConfigV2rayService if (!_node.Finalmask.IsNullOrEmpty()) { - streamSettings.finalmask = JsonUtils.Deserialize(_node.Finalmask); + streamSettings.finalmask = JsonUtils.Deserialize(_node.Finalmask); } } catch (Exception ex)