Skip to content

Commit e9d2d25

Browse files
authored
实验性地适配了 sing-box 的 Hysteria 2 端口跳跃 (#220)
* feat(protocol): add ss2022 support for iOS clients * 配合 sing-box 1.12 Hysteria 2 端口跳跃机制,移除单端口配置改为下发端口数组 * 实验性支持 Loon TF 的 REALITY 配置,为 Stash 添加独立的模板文件 * 删除了 Loon 不必要的注释、修复了 sing-box Hysteria 2 端口逻辑
1 parent 4dd8ce9 commit e9d2d25

File tree

4 files changed

+634
-16
lines changed

4 files changed

+634
-16
lines changed

app/Protocols/Loon.php

+14-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function handle()
2929
$uri .= self::buildShadowsocks($user['uuid'], $item);
3030
}elseif ($item['type'] === 'vmess') {
3131
$uri .= self::buildVmess($user['uuid'], $item);
32-
}elseif ($item['type'] === 'vless' && !$item['flow'] ) { // loon 不支持流控,需要过滤掉
32+
}elseif ($item['type'] === 'vless') {
3333
$uri .= self::buildVless($user['uuid'], $item);
3434
}elseif ($item['type'] === 'trojan') {
3535
$uri .= self::buildTrojan($user['uuid'], $item);
@@ -153,8 +153,19 @@ public static function buildVless($uuid, $server)
153153
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
154154
array_push($config, "tls-name={$tlsSettings['server_name']}");
155155
}
156-
}elseif($server['tls'] === 2){ // reality 暂不被 loon 支持
157-
return '';
156+
}elseif($server['tls'] === 2){
157+
array_push($config, "flow={$server['flow']}");
158+
if ($server['tls_settings']) {
159+
$tlsSettings = $server['tls_settings'];
160+
if (isset($tlsSettings['public_key']) && !empty($tlsSettings['public_key']))
161+
array_push($config, "public-key={$tlsSettings['public_key']}");
162+
if (isset($tlsSettings['short_id']) && !empty($tlsSettings['short_id']))
163+
array_push($config, "short-id={$tlsSettings['short_id']}");
164+
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
165+
array_push($config, "sni={$tlsSettings['server_name']}");
166+
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure']))
167+
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allow_insecure']? 'true' : 'false'));
168+
}
158169
}
159170
if ($server['network'] === 'ws') {
160171
array_push($config, 'transport=ws');

app/Protocols/Singbox.php

+19-7
Original file line numberDiff line numberDiff line change
@@ -265,19 +265,24 @@ protected function buildTrojan($password, $server)
265265

266266
protected function buildHysteria($password, $server, $user)
267267
{
268-
$parts = explode(",",$server['port']);
269-
$firstPart = $parts[0];
270-
if (strpos($firstPart, '-') !== false) {
271-
$range = explode('-', $firstPart);
272-
$firstPort = $range[0];
268+
$parts = array_map('trim', explode(',', $server['port']));
269+
$portConfig = [];
270+
271+
// 检查是否为单端口
272+
if (count($parts) === 1 && !str_contains($parts[0], '-')) {
273+
$port = (int)$parts[0];
273274
} else {
274-
$firstPort = $firstPart;
275+
// 处理多端口情况 舍弃单独的端口 只保留范围端口
276+
foreach ($parts as $part) {
277+
if (str_contains($part, '-')) {
278+
$portConfig[] = str_replace('-', ':', $part);
279+
}
280+
}
275281
}
276282

277283
$array = [
278284
'tag' => $server['name'],
279285
'server' => $server['host'],
280-
'server_port' => (int)$firstPort,
281286
'domain_resolver' => 'local',
282287
'tls' => [
283288
'enabled' => true,
@@ -286,6 +291,13 @@ protected function buildHysteria($password, $server, $user)
286291
]
287292
];
288293

294+
// 设置端口配置
295+
if (isset($port)) {
296+
$array['server_port'] = $port;
297+
} else {
298+
$array['server_ports'] = $portConfig;
299+
}
300+
289301
if (is_null($server['version']) || $server['version'] == 1) {
290302
$array['auth_str'] = $password;
291303
$array['type'] = 'hysteria';

app/Protocols/Stash.php

+5-6
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public function handle()
2525
header('profile-update-interval: 24');
2626
header("content-disposition: filename*=UTF-8''".rawurlencode($appName));
2727
// 暂时使用clash配置文件,后续根据Stash更新情况更新
28-
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
29-
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
28+
$defaultConfig = base_path() . '/resources/rules/default.stash.yaml';
29+
$customConfig = base_path() . '/resources/rules/custom.stash.yaml';
3030
if (\File::exists($customConfig)) {
3131
$config = Yaml::parseFile($customConfig);
3232
} else {
@@ -181,10 +181,7 @@ public static function buildVless($uuid, $server)
181181
$array['server'] = $server['host'];
182182
$array['port'] = $server['port'];
183183
$array['uuid'] = $uuid;
184-
$array['flow'] = (function($value){
185-
return in_array($value, [null, 'none', 'xtls-rprx-origin','xtls-rprx-direct','xtls-rprx-splice'], true) ? $value : null;
186-
})($server['flow'] ?? null);
187-
$array['client-fingerprint'] = 'chrome';
184+
$array['flow'] = $server['flow'] ?? null;
188185
$array['udp'] = true;
189186

190187
if ($server['tls']) {
@@ -198,6 +195,8 @@ public static function buildVless($uuid, $server)
198195
$array['reality-opts']['public-key'] = $tlsSettings['public_key'];
199196
$array['reality-opts']['short-id'] = $tlsSettings['short_id'];
200197
}
198+
$array['skip-cert-verify'] = $tlsSettings['allow_insecure'] ? true : false;
199+
$array['client-fingerprint'] = $tlsSettings['fingerprint'] ?? null;
201200
}
202201
}
203202

0 commit comments

Comments
 (0)