From 846616244dfca4256fbe43d4d423e8e757d11f54 Mon Sep 17 00:00:00 2001 From: hellcat Date: Thu, 27 Aug 2026 19:12:28 +0800 Subject: [PATCH] no message --- src/Services/Subscribe/V2Ray.php | 96 +++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 27 deletions(-) diff --git a/src/Services/Subscribe/V2Ray.php b/src/Services/Subscribe/V2Ray.php index c7a9a0ad0..416fe823c 100755 --- a/src/Services/Subscribe/V2Ray.php +++ b/src/Services/Subscribe/V2Ray.php @@ -60,35 +60,77 @@ final class V2Ray extends Base $links .= 'ss://' . base64_encode($user->method . ':' . $user->passwd . '@' . $node_raw->server . ':' . $port) . '#' . rawurlencode($node_raw->name) . PHP_EOL; } else if ((int) $node_raw->sort === 11) { - - $network = $node_custom_config['network'] ?? 'tcp'; - $reality_opts = $node_custom_config['reality-opts'] ?? []; - $browser = $node_custom_config['browser'] ?? 'chrome'; - $flow = $node_custom_config['flow'] ?? ''; - $servername = $node_custom_config['servername'] ?? ''; - $security = $node_custom_config['security'] ?? 'none'; - - $uuid = $user->uuid; - $server = $node_raw->server; - $port = $node_custom_config['offset_port_user'] ?? ($node_custom_config['offset_port_node'] ?? 443); - $name = $node_raw->name; - - if ($reality_opts) { - $security = 'reality'; - } + // 基础传输与安全配置 + $sNetwork = $node_custom_config['network'] ?? 'tcp'; + $sSecurity = $node_custom_config['security'] ?? 'none'; + $sBrowser = $node_custom_config['browser'] ?? 'chrome'; + $sFlow = $node_custom_config['flow'] ?? ''; + + // SNI 与 Host 解析逻辑(兼容多种写法,提供优雅降级) + $sHost = $node_custom_config['host'] ?? ''; + $sSni = $node_custom_config['sni'] ?? ($node_custom_config['servername'] ?? $sHost); + + // WS 特有路径配置 + $sWsPath = $node_custom_config['path'] ?? '/'; - // 构建查询参数 - $aParams = [ - 'type' => $network, - 'security' => $security, - 'fp' => $browser, - 'sni' => $servername, - 'flow' => $flow, - 'sid' => $reality_opts['short-id'] ?? '', - 'pbk' => $reality_opts['public-key'] ?? '' - ]; + // REALITY 参数解析 + $aRealityOpts = $node_custom_config['reality-opts'] ?? []; + if (! empty($aRealityOpts)) { + $sSecurity = 'reality'; + } - $links .= 'vless://' . $uuid . '@' . $server . ':' . $port . '?' . http_build_query($aParams) . '#' . rawurlencode($name) . PHP_EOL; + // 端口计算:优先提取节点通信端口 offset_port_node,回退机制保障安全 + $iPort = (int) ($node_custom_config['offset_port_node'] ?? ($node_custom_config['offset_port_user'] ?? 443)); + + // 用户与节点凭据 + $sUuid = $user->uuid; + $sServer = $node_raw->server; + $sName = $node_raw->name; + + // 严谨构建 Query 参数映射表 + $aQueryParams = array_filter([ + 'type' => $sNetwork, + 'security' => $sSecurity, + 'fp' => $sBrowser, + 'sni' => $sSni, + 'host' => $sHost, + 'path' => ($sNetwork === 'ws') ? $sWsPath : null, + 'flow' => $sFlow, + 'sid' => $aRealityOpts['short-id'] ?? null, + 'pbk' => $aRealityOpts['public-key'] ?? null, + ], fn ($xValue) => $xValue !== null && $xValue !== ''); + + // 拼接标准 VLESS URI + $sQueryString = http_build_query($aQueryParams, '', '&', PHP_QUERY_RFC3986); + $links .= 'vless://' . $sUuid . '@' . $sServer . ':' . $iPort . '?' . $sQueryString . '#' . rawurlencode($sName) . PHP_EOL; +// $network = $node_custom_config['network'] ?? 'tcp'; +// $reality_opts = $node_custom_config['reality-opts'] ?? []; +// $browser = $node_custom_config['browser'] ?? 'chrome'; +// $flow = $node_custom_config['flow'] ?? ''; +// $servername = $node_custom_config['servername'] ?? ''; +// $security = $node_custom_config['security'] ?? 'none'; +// +// $uuid = $user->uuid; +// $server = $node_raw->server; +// $port = $node_custom_config['offset_port_user'] ?? ($node_custom_config['offset_port_node'] ?? 443); +// $name = $node_raw->name; +// +// if ($reality_opts) { +// $security = 'reality'; +// } +// +// // 构建查询参数 +// $aParams = [ +// 'type' => $network, +// 'security' => $security, +// 'fp' => $browser, +// 'sni' => $servername, +// 'flow' => $flow, +// 'sid' => $reality_opts['short-id'] ?? '', +// 'pbk' => $reality_opts['public-key'] ?? '' +// ]; +// +// $links .= 'vless://' . $uuid . '@' . $server . ':' . $port . '?' . http_build_query($aParams) . '#' . rawurlencode($name) . PHP_EOL; } }