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",
"version": "2.14.190",
"version": "2.14.191",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js",
"scripts": {

View File

@ -237,6 +237,7 @@ function lastParse(proxy) {
delete proxy['ws-path'];
delete proxy['ws-headers'];
}
if (proxy.type === 'trojan') {
if (proxy.network === 'tcp') {
delete proxy.network;
@ -253,11 +254,22 @@ function lastParse(proxy) {
if (proxy.network) {
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;
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.network) {
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 query = '';
if (!serverAndPortArray) {
// 暂时先这样处理 目前够用
if (content.includes('?plugin=')) {
const parsed = content.match(/^(.*)(\?plugin=.*)$/);
if (content.includes('?')) {
const parsed = content.match(/^(.*)(\?.*)$/);
content = parsed[1];
query = parsed[2];
}
content = Base64.decode(content);
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}`;
}
userInfoStr = content.split('@')[0];
@ -57,6 +67,7 @@ function URI_SS() {
const userInfo = userInfoStr.split(':');
proxy.cipher = userInfo[0];
proxy.password = userInfo[1];
// handle obfs
const idx = content.indexOf('?plugin=');
if (idx !== -1) {
@ -96,6 +107,9 @@ function URI_SS() {
if (/(&|\?)uot=(1|true)/i.test(query)) {
proxy['udp-over-tcp'] = true;
}
if (/(&|\?)tfo=(1|true)/i.test(query)) {
proxy.tfo = true;
}
return proxy;
};
return { name, test, parse };
@ -449,7 +463,7 @@ function URI_VLESS() {
if (params.serviceName) {
opts[`${proxy.network}-service-name`] = params.serviceName;
} 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;
delete params.path;
}

View File

@ -107,6 +107,25 @@ export default function Clash_Producer() {
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 (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type,

View File

@ -110,7 +110,25 @@ export default function ClashMeta_Producer() {
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 (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type,

View File

@ -126,6 +126,25 @@ export default function ShadowRocket_Producer() {
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 (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(

View File

@ -206,6 +206,25 @@ export default function Stash_Producer() {
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 (
['trojan', 'tuic', 'hysteria', 'hysteria2'].includes(
proxy.type,

View File

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

View File

@ -69,7 +69,7 @@ function shadowsocks(proxy) {
`,obfs-uri=${proxy['plugin-opts'].path}`,
'plugin-opts.path',
);
} else {
} else if (!['shadow-tls'].includes(proxy.plugin)) {
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',
);
} 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

View File

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