feat: 支持更多不规范的 SS URI; 去除 Surfboard 节点名中的等号; 支持 Mihomo shadowsocks shadow-tls

This commit is contained in:
xream 2024-01-30 00:49:41 +08:00
parent 64117c50c7
commit 8a2087c53a
No known key found for this signature in database
GPG Key ID: 1D2C5225471789F9
10 changed files with 131 additions and 8 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "sub-store", "name": "sub-store",
"version": "2.14.190", "version": "2.14.191",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.", "description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js", "main": "src/main.js",
"scripts": { "scripts": {

View File

@ -237,6 +237,7 @@ function lastParse(proxy) {
delete proxy['ws-path']; delete proxy['ws-path'];
delete proxy['ws-headers']; delete proxy['ws-headers'];
} }
if (proxy.type === 'trojan') { if (proxy.type === 'trojan') {
if (proxy.network === 'tcp') { if (proxy.network === 'tcp') {
delete proxy.network; delete proxy.network;
@ -253,11 +254,22 @@ function lastParse(proxy) {
if (proxy.network) { if (proxy.network) {
let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host; let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host;
let transporthost = proxy[`${proxy.network}-opts`]?.headers?.host; let transporthost = proxy[`${proxy.network}-opts`]?.headers?.host;
if (transporthost && !transportHost) { if (proxy.network === 'h2') {
if (!transporthost && transportHost) {
proxy[`${proxy.network}-opts`].headers.host = transportHost;
delete proxy[`${proxy.network}-opts`].headers.Host;
}
} else if (transporthost && !transportHost) {
proxy[`${proxy.network}-opts`].headers.Host = transporthost; proxy[`${proxy.network}-opts`].headers.Host = transporthost;
delete proxy[`${proxy.network}-opts`].headers.host; delete proxy[`${proxy.network}-opts`].headers.host;
} }
} }
if (proxy.network === 'h2') {
const host = proxy['h2-opts']?.headers?.host;
if (host && !Array.isArray(host)) {
proxy['h2-opts'].headers.host = [host];
}
}
if (proxy.tls && !proxy.sni) { if (proxy.tls && !proxy.sni) {
if (proxy.network) { if (proxy.network) {
let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host; let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host;

View File

@ -34,14 +34,24 @@ function URI_SS() {
let userInfoStr = Base64.decode(content.split('@')[0]); let userInfoStr = Base64.decode(content.split('@')[0]);
let query = ''; let query = '';
if (!serverAndPortArray) { if (!serverAndPortArray) {
// 暂时先这样处理 目前够用 if (content.includes('?')) {
if (content.includes('?plugin=')) { const parsed = content.match(/^(.*)(\?.*)$/);
const parsed = content.match(/^(.*)(\?plugin=.*)$/);
content = parsed[1]; content = parsed[1];
query = parsed[2]; query = parsed[2];
} }
content = Base64.decode(content); content = Base64.decode(content);
if (query) { if (query) {
console.log(query);
if (/(&|\?)v2ray-plugin=/.test(query)) {
const parsed = query.match(/(&|\?)v2ray-plugin=(.*?)(&|$)/);
let v2rayPlugin = parsed[2];
if (v2rayPlugin) {
proxy.obfs = 'v2ray-plugin';
proxy['plugin-opts'] = JSON.parse(
Base64.decode(v2rayPlugin),
);
}
}
content = `${content}${query}`; content = `${content}${query}`;
} }
userInfoStr = content.split('@')[0]; userInfoStr = content.split('@')[0];
@ -57,6 +67,7 @@ function URI_SS() {
const userInfo = userInfoStr.split(':'); const userInfo = userInfoStr.split(':');
proxy.cipher = userInfo[0]; proxy.cipher = userInfo[0];
proxy.password = userInfo[1]; proxy.password = userInfo[1];
// handle obfs // handle obfs
const idx = content.indexOf('?plugin='); const idx = content.indexOf('?plugin=');
if (idx !== -1) { if (idx !== -1) {
@ -96,6 +107,9 @@ function URI_SS() {
if (/(&|\?)uot=(1|true)/i.test(query)) { if (/(&|\?)uot=(1|true)/i.test(query)) {
proxy['udp-over-tcp'] = true; proxy['udp-over-tcp'] = true;
} }
if (/(&|\?)tfo=(1|true)/i.test(query)) {
proxy.tfo = true;
}
return proxy; return proxy;
}; };
return { name, test, parse }; return { name, test, parse };
@ -449,7 +463,7 @@ function URI_VLESS() {
if (params.serviceName) { if (params.serviceName) {
opts[`${proxy.network}-service-name`] = params.serviceName; opts[`${proxy.network}-service-name`] = params.serviceName;
} else if (isShadowrocket && params.path) { } else if (isShadowrocket && params.path) {
if (!['ws', 'http'].includes(proxy.network)) { if (!['ws', 'http', 'h2'].includes(proxy.network)) {
opts[`${proxy.network}-service-name`] = params.path; opts[`${proxy.network}-service-name`] = params.path;
delete params.path; delete params.path;
} }

View File

@ -107,6 +107,25 @@ export default function Clash_Producer() {
proxy['http-opts'].headers.Host = [httpHost]; proxy['http-opts'].headers.Host = [httpHost];
} }
} }
if (
['vmess', 'vless'].includes(proxy.type) &&
proxy.network === 'h2'
) {
let path = proxy['h2-opts']?.path;
if (
isPresent(proxy, 'h2-opts.path') &&
Array.isArray(path)
) {
proxy['h2-opts'].path = path[0];
}
let host = proxy['h2-opts']?.headers?.host;
if (
isPresent(proxy, 'h2-opts.headers.Host') &&
!Array.isArray(host)
) {
proxy['h2-opts'].headers.host = [host];
}
}
if ( if (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type, proxy.type,

View File

@ -110,7 +110,25 @@ export default function ClashMeta_Producer() {
proxy['http-opts'].headers.Host = [httpHost]; proxy['http-opts'].headers.Host = [httpHost];
} }
} }
if (
['vmess', 'vless'].includes(proxy.type) &&
proxy.network === 'h2'
) {
let path = proxy['h2-opts']?.path;
if (
isPresent(proxy, 'h2-opts.path') &&
Array.isArray(path)
) {
proxy['h2-opts'].path = path[0];
}
let host = proxy['h2-opts']?.headers?.host;
if (
isPresent(proxy, 'h2-opts.headers.Host') &&
!Array.isArray(host)
) {
proxy['h2-opts'].headers.host = [host];
}
}
if ( if (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type, proxy.type,

View File

@ -126,6 +126,25 @@ export default function ShadowRocket_Producer() {
proxy['http-opts'].headers.Host = [httpHost]; proxy['http-opts'].headers.Host = [httpHost];
} }
} }
if (
['vmess', 'vless'].includes(proxy.type) &&
proxy.network === 'h2'
) {
let path = proxy['h2-opts']?.path;
if (
isPresent(proxy, 'h2-opts.path') &&
Array.isArray(path)
) {
proxy['h2-opts'].path = path[0];
}
let host = proxy['h2-opts']?.headers?.host;
if (
isPresent(proxy, 'h2-opts.headers.Host') &&
!Array.isArray(host)
) {
proxy['h2-opts'].headers.host = [host];
}
}
if ( if (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(

View File

@ -206,6 +206,25 @@ export default function Stash_Producer() {
proxy['http-opts'].headers.Host = [httpHost]; proxy['http-opts'].headers.Host = [httpHost];
} }
} }
if (
['vmess', 'vless'].includes(proxy.type) &&
proxy.network === 'h2'
) {
let path = proxy['h2-opts']?.path;
if (
isPresent(proxy, 'h2-opts.path') &&
Array.isArray(path)
) {
proxy['h2-opts'].path = path[0];
}
let host = proxy['h2-opts']?.headers?.host;
if (
isPresent(proxy, 'h2-opts.headers.Host') &&
!Array.isArray(host)
) {
proxy['h2-opts'].headers.host = [host];
}
}
if ( if (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type, proxy.type,

View File

@ -6,6 +6,7 @@ const targetPlatform = 'Surfboard';
export default function Surfboard_Producer() { export default function Surfboard_Producer() {
const produce = (proxy) => { const produce = (proxy) => {
proxy.name = proxy.name.replace(/=/g, '');
switch (proxy.type) { switch (proxy.type) {
case 'ss': case 'ss':
return shadowsocks(proxy); return shadowsocks(proxy);

View File

@ -69,7 +69,7 @@ function shadowsocks(proxy) {
`,obfs-uri=${proxy['plugin-opts'].path}`, `,obfs-uri=${proxy['plugin-opts'].path}`,
'plugin-opts.path', 'plugin-opts.path',
); );
} else { } else if (!['shadow-tls'].includes(proxy.plugin)) {
throw new Error(`plugin ${proxy.plugin} is not supported`); throw new Error(`plugin ${proxy.plugin} is not supported`);
} }
} }
@ -95,6 +95,24 @@ function shadowsocks(proxy) {
`,shadow-tls-sni=${proxy['shadow-tls-sni']}`, `,shadow-tls-sni=${proxy['shadow-tls-sni']}`,
'shadow-tls-sni', 'shadow-tls-sni',
); );
} else if (['shadow-tls'].includes(proxy.plugin) && proxy['plugin-opts']) {
const password = proxy['plugin-opts'].password;
const host = proxy['plugin-opts'].host;
const version = proxy['plugin-opts'].version;
if (password) {
result.append(`,shadow-tls-password=${password}`);
if (host) {
result.append(`,shadow-tls-sni=${host}`);
}
if (version) {
if (version < 2) {
throw new Error(
`shadow-tls version ${version} is not supported`,
);
}
result.append(`,shadow-tls-version=${version}`);
}
}
} }
// block-quic // block-quic

View File

@ -42,6 +42,9 @@ export default function URI_Producer() {
if (proxy['udp-over-tcp']) { if (proxy['udp-over-tcp']) {
result = `${result}${proxy.plugin ? '&' : '?'}uot=1`; result = `${result}${proxy.plugin ? '&' : '?'}uot=1`;
} }
if (proxy.tfo) {
result = `${result}${proxy.plugin ? '&' : '?'}tfo=1`;
}
result += `#${encodeURIComponent(proxy.name)}`; result += `#${encodeURIComponent(proxy.name)}`;
break; break;
case 'ssr': case 'ssr':