Compare commits

...

3 commits

Author SHA1 Message Date
DHR60
7ddb46e74d
Xray browser header masquerading (#8981)
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release Linux / deb (push) Blocked by required conditions
release Linux / rpm (push) Blocked by required conditions
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
2026-03-24 11:25:02 +08:00
DHR60
ad11a7e6a5
Support new hysteria2 stream settings (#8908)
* Support new hysteria2 stream settings

* Fix

* Sync
2026-03-24 11:24:42 +08:00
DHR60
92c8c1463c
Fix (#8985) 2026-03-24 11:24:26 +08:00
4 changed files with 72 additions and 50 deletions

View file

@ -182,13 +182,14 @@ public class Global
@"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/main/v2rayN/"
];
public static readonly Dictionary<string, string> UserAgentTexts = new()
public static readonly Dictionary<string, string> TcpHttpUserAgentTexts = new()
{
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
{"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" },
{"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" },
{"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" },
{"none",""}
{"none",""},
{"golang",""}
};
public const string Hysteria2ProtocolShare = "hy2://";
@ -391,9 +392,8 @@ public class Global
[
"chrome",
"firefox",
"safari",
"edge",
"none"
"golang"
];
public static readonly List<string> XhttpMode =

View file

@ -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; }
}
@ -421,6 +421,8 @@ public class HttpupgradeSettings4Ray
public string? path { get; set; }
public string? host { get; set; }
public Headers4Ray headers { get; set; }
}
public class XhttpSettings4Ray
@ -456,33 +458,31 @@ public class GrpcSettings4Ray
public int? health_check_timeout { get; set; }
public bool? permit_without_stream { get; set; }
public int? initial_windows_size { get; set; }
public string? user_agent { get; set; }
}
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<Mask4Ray>? tcp { get; set; }
public List<Mask4Ray>? 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 +491,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; }

View file

@ -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(',')))
{
@ -608,7 +609,7 @@ public partial class CoreConfigSingboxService
{
var node = nodesReverse[i];
var currentTag = i == 0 ? baseTagName : $"chain-{baseTagName}-{i}-{node.Remarks}";
var dialerProxyTag = i != nodesReverse.Count - 1 ? $"chain-{baseTagName}-{i + 1}-{node.Remarks}" : null;
var dialerProxyTag = i != nodesReverse.Count - 1 ? $"chain-{baseTagName}-{i + 1}-{nodesReverse[i + 1].Remarks}" : null;
if (node.ConfigType.IsGroupType())
{
var childProfiles = new CoreConfigSingboxService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);

View file

@ -354,11 +354,7 @@ public partial class CoreConfigV2rayService
var host = _node.RequestHost.TrimEx();
var path = _node.Path.TrimEx();
var sni = _node.Sni.TrimEx();
var useragent = "";
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
{
useragent = Global.UserAgentTexts.GetValueOrDefault(_config.CoreBasicItem.DefUserAgent, _config.CoreBasicItem.DefUserAgent);
}
var useragent = _config.CoreBasicItem.DefUserAgent ?? string.Empty;
//if tls
if (_node.StreamSecurity == Global.StreamSecurity)
@ -441,10 +437,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 +449,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):
@ -495,13 +492,17 @@ public partial class CoreConfigV2rayService
case nameof(ETransport.httpupgrade):
HttpupgradeSettings4Ray httpupgradeSettings = new();
if (host.IsNotEmpty())
{
httpupgradeSettings.host = host;
}
if (path.IsNotEmpty())
{
httpupgradeSettings.path = path;
}
if (host.IsNotEmpty())
if (useragent.IsNotEmpty())
{
httpupgradeSettings.host = host;
httpupgradeSettings.headers.UserAgent = useragent;
}
streamSettings.httpupgradeSettings = httpupgradeSettings;
@ -580,6 +581,7 @@ public partial class CoreConfigV2rayService
health_check_timeout = _config.GrpcItem.HealthCheckTimeout,
permit_without_stream = _config.GrpcItem.PermitWithoutStream,
initial_windows_size = _config.GrpcItem.InitialWindowsSize,
user_agent = useragent.NullIfEmpty(),
};
streamSettings.grpcSettings = grpcSettings;
break;
@ -598,28 +600,32 @@ 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;
}
streamSettings.hysteriaSettings = new()
if (upMbps > 0 || downMbps > 0)
{
version = 2,
auth = _node.Password,
up = upMbps > 0 ? $"{upMbps}mbps" : null,
down = downMbps > 0 ? $"{downMbps}mbps" : null,
udphop = udpHop,
};
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())
{
streamSettings.finalmask ??= new();
streamSettings.finalmask.udp =
hy2Finalmask.udp =
[
new Mask4Ray
{
@ -628,6 +634,12 @@ public partial class CoreConfigV2rayService
}
];
}
streamSettings.hysteriaSettings = new()
{
version = 2,
auth = _node.Password,
};
streamSettings.finalmask = hy2Finalmask;
break;
default:
@ -644,10 +656,11 @@ public partial class CoreConfigV2rayService
//request Host
var request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
var useragentValue = Global.TcpHttpUserAgentTexts.GetValueOrDefault(useragent, useragent);
var arrHost = host.Split(',');
var host2 = string.Join(",".AppendQuotes(), arrHost);
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
request = request.Replace("$requestUserAgent$", $"{useragentValue.AppendQuotes()}");
//Path
var pathHttp = @"/";
if (path.IsNotEmpty())
@ -665,7 +678,7 @@ public partial class CoreConfigV2rayService
if (!_node.Finalmask.IsNullOrEmpty())
{
streamSettings.finalmask = JsonUtils.Deserialize<Finalmask4Ray>(_node.Finalmask);
streamSettings.finalmask = JsonUtils.ParseJson(_node.Finalmask);
}
}
catch (Exception ex)
@ -725,7 +738,7 @@ public partial class CoreConfigV2rayService
{
var node = nodesReverse[i];
var currentTag = i == 0 ? baseTagName : $"chain-{baseTagName}-{i}-{node.Remarks}";
var dialerProxyTag = i != nodesReverse.Count - 1 ? $"chain-{baseTagName}-{i + 1}-{node.Remarks}" : null;
var dialerProxyTag = i != nodesReverse.Count - 1 ? $"chain-{baseTagName}-{i + 1}-{nodesReverse[i + 1].Remarks}" : null;
if (node.ConfigType.IsGroupType())
{
var childProfiles = new CoreConfigV2rayService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);