Skip to content

Commit c8ccf45

Browse files
committed
feat: sing-box 支持 Shadowsocks/Snell/VMess/VLESS/Trojan 搭配 ShadowTLS
1 parent 1d5d25b commit c8ccf45

3 files changed

Lines changed: 417 additions & 10 deletions

File tree

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sub-store",
3-
"version": "2.36.12",
3+
"version": "2.36.13",
44
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
55
"main": "src/main.js",
66
"packageManager": "pnpm@11.0.9",

backend/src/core/proxy-utils/producers/sing-box.js

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,11 +1300,10 @@ export default function singbox_Producer() {
13001300
const type = 'ALL';
13011301
const produce = (proxies, type, opts = {}) => {
13021302
const list = [];
1303-
const originalSnellShadowTLS = new Map(
1303+
const originalShadowTLS = new Map(
13041304
proxies
13051305
.filter(
13061306
(proxy) =>
1307-
proxy?.type === 'snell' &&
13081307
proxy?.plugin === 'shadow-tls' &&
13091308
proxy?.['plugin-opts'],
13101309
)
@@ -1324,22 +1323,81 @@ export default function singbox_Producer() {
13241323
ClashMeta_Producer()
13251324
.produce(proxies, 'internal', { 'include-unsupported-proxy': true })
13261325
.map((proxy) => {
1326+
const listStart = list.length;
13271327
try {
1328-
const originalShadowTLS = originalSnellShadowTLS.get(proxy);
1329-
if (originalShadowTLS) {
1330-
proxy.plugin = originalShadowTLS.plugin;
1331-
proxy['plugin-opts'] = originalShadowTLS['plugin-opts'];
1332-
if (originalShadowTLS['obfs-opts']) {
1333-
proxy['obfs-opts'] = originalShadowTLS['obfs-opts'];
1328+
const shadowTLS = originalShadowTLS.get(proxy);
1329+
if (shadowTLS) {
1330+
proxy.plugin = shadowTLS.plugin;
1331+
proxy['plugin-opts'] = shadowTLS['plugin-opts'];
1332+
if (shadowTLS['obfs-opts']) {
1333+
proxy['obfs-opts'] = shadowTLS['obfs-opts'];
13341334
} else {
13351335
delete proxy['obfs-opts'];
13361336
}
13371337
}
1338+
const shadowTLSPluginOpts = getShadowTLSPluginOpts(proxy);
1339+
const shadowTLSEnabled = Boolean(
1340+
shadowTLSPluginOpts &&
1341+
(shadowTLSPluginOpts.password ||
1342+
(shadowTLSPluginOpts.version != null &&
1343+
Number(shadowTLSPluginOpts.version) !== 0)),
1344+
);
1345+
let streamShadowTLSOutbound;
1346+
if (
1347+
shadowTLSEnabled &&
1348+
['vmess', 'vless', 'trojan'].includes(proxy.type)
1349+
) {
1350+
if (proxy['reality-opts']) {
1351+
throw new Error(
1352+
`Platform sing-box cannot chain ShadowTLS with Reality for proxy ${proxy.name}`,
1353+
);
1354+
}
1355+
if (
1356+
['vmess', 'vless'].includes(proxy.type) &&
1357+
proxy.network === 'h2'
1358+
) {
1359+
throw new Error(
1360+
`Platform sing-box cannot chain ShadowTLS with network h2 for proxy ${proxy.name}`,
1361+
);
1362+
}
1363+
if (
1364+
proxy.type === 'vless' &&
1365+
proxy.flow === 'xtls-rprx-vision'
1366+
) {
1367+
throw new Error(
1368+
`Platform sing-box cannot chain ShadowTLS with flow xtls-rprx-vision for proxy ${proxy.name}`,
1369+
);
1370+
}
1371+
1372+
const rawVersion = shadowTLSPluginOpts.version;
1373+
const parsedVersion =
1374+
typeof rawVersion === 'string' &&
1375+
rawVersion.trim() === ''
1376+
? NaN
1377+
: Number(rawVersion ?? 0);
1378+
const version = parsedVersion === 0 ? 2 : parsedVersion;
1379+
if (
1380+
!Number.isInteger(version) ||
1381+
![1, 2, 3].includes(version)
1382+
) {
1383+
throw new Error(
1384+
`Platform sing-box does not support shadow-tls version ${rawVersion} for proxy ${proxy.name}`,
1385+
);
1386+
}
1387+
streamShadowTLSOutbound = shadowTLSOutboundParser(
1388+
proxy,
1389+
{ ...shadowTLSPluginOpts, version },
1390+
);
1391+
}
1392+
if (proxy.type === 'anytls' && shadowTLSEnabled) {
1393+
throw new Error(
1394+
'Platform sing-box cannot replace AnyTLS TLS with ShadowTLS',
1395+
);
1396+
}
13381397
if (['xhttp'].includes(proxy.network))
13391398
throw new Error(
13401399
`Platform sing-box does not support network: ${proxy.network}`,
13411400
);
1342-
const listStart = list.length;
13431401
switch (proxy.type) {
13441402
case 'ssh':
13451403
list.push(sshParser(proxy));
@@ -1503,6 +1561,12 @@ export default function singbox_Producer() {
15031561
`Platform sing-box does not support proxy type: ${proxy.type}`,
15041562
);
15051563
}
1564+
if (streamShadowTLSOutbound) {
1565+
const outbound = list[listStart];
1566+
outbound.detour = getShadowTLSTag(proxy);
1567+
delete outbound.tls;
1568+
list.push(streamShadowTLSOutbound);
1569+
}
15061570
if (
15071571
opts['include-unsupported-proxy'] &&
15081572
proxy['name-cert-verify']
@@ -1516,6 +1580,7 @@ export default function singbox_Producer() {
15161580
}
15171581
} catch (e) {
15181582
// console.log(e);
1583+
list.length = listStart;
15191584
$.error(e.message ?? e);
15201585
}
15211586
});

0 commit comments

Comments
 (0)