Compare commits

...

6 Commits

11 changed files with 107 additions and 17 deletions

View File

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

View File

@@ -8,6 +8,7 @@ import {
isValidPortNumber,
isNotBlank,
ipAddress,
getRandomPort,
} from '@/utils';
import PROXY_PROCESSORS, { ApplyProcessor } from './processors';
import PROXY_PREPROCESSORS from './preprocessors';
@@ -220,6 +221,17 @@ function produce(proxies, targetPlatform, type, opts = {}) {
delete proxy['tls-fingerprint'];
}
}
// 处理 端口跳跃
if (proxy.ports) {
if (!['ClashMeta'].includes(targetPlatform)) {
proxy.ports = proxy.ports.replace(/\//g, ',');
}
if (!proxy.port) {
proxy.port = getRandomPort(proxy.ports);
}
}
return proxy;
});
@@ -274,6 +286,7 @@ export const ProxyUtils = {
process: processFn,
produce,
ipAddress,
getRandomPort,
isIPv4,
isIPv6,
isIP,

View File

@@ -351,6 +351,7 @@ function URI_VMess() {
transportPath = '/';
}
}
// 传输层应该有配置, 暂时不考虑兼容不给配置的节点
if (transportPath || transportHost) {
if (['grpc'].includes(proxy.network)) {
proxy[`${proxy.network}-opts`] = {

View File

@@ -54,31 +54,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs
$set(proxy, "plugin-opts.path", obfs.path);
}
}
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/vmess_alterId/fast_open/udp_relay/others)* {
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
proxy.alterId = proxy.alterId || 0;
handleTransport();
}
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "vless";
handleTransport();
}
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "trojan";
handleTransport();
}
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
proxy.type = "hysteria2";
}
https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* {
https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "http";
proxy.tls = true;
}
http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* {
proxy.type = "http";
}
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "socks5";
}
@@ -172,6 +172,8 @@ vmess_alterId = comma "alterId" equals alterId:$[0-9]+ { proxy.alterId = parseIn
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
tls_host = comma sni:("tls-name"/"sni") equals host:domain { proxy.sni = host; }
tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert-verify"] = flag; }
tls_cert_sha256 = comma "tls-cert-sha256" equals match:[^,]+ { proxy["tls-fingerprint"] = match.join("").replace(/^"(.*)"$/, '$1'); }
tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pubkey-sha256"] = match.join("").replace(/^"(.*)"$/, '$1'); }
fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; }
@@ -180,6 +182,7 @@ ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; }
download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); }
salamander_password = comma "salamander-password" equals match:[^,]+ { proxy['obfs-password'] = match.join(""); proxy.obfs = 'salamander'; }
tag = match:[^=,]* { proxy.name = match.join("").trim(); }
comma = _ "," _
equals = _ "=" _

View File

@@ -52,31 +52,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs
$set(proxy, "plugin-opts.path", obfs.path);
}
}
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/vmess_alterId/fast_open/udp_relay/others)* {
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
proxy.alterId = proxy.alterId || 0;
handleTransport();
}
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "vless";
handleTransport();
}
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "trojan";
handleTransport();
}
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
proxy.type = "hysteria2";
}
https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* {
https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "http";
proxy.tls = true;
}
http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* {
proxy.type = "http";
}
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
proxy.type = "socks5";
}
@@ -170,6 +170,8 @@ vmess_alterId = comma "alterId" equals alterId:$[0-9]+ { proxy.alterId = parseIn
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
tls_host = comma sni:("tls-name"/"sni") equals host:domain { proxy.sni = host; }
tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert-verify"] = flag; }
tls_cert_sha256 = comma "tls-cert-sha256" equals match:[^,]+ { proxy["tls-fingerprint"] = match.join("").replace(/^"(.*)"$/, '$1'); }
tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pubkey-sha256"] = match.join("").replace(/^"(.*)"$/, '$1'); }
fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; }

View File

@@ -153,6 +153,14 @@ function trojan(proxy) {
// sni
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
result.appendIfPresent(
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
'tls-fingerprint',
);
result.appendIfPresent(
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
'tls-pubkey-sha256',
);
// tfo
result.appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
@@ -215,6 +223,14 @@ function vmess(proxy) {
// sni
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
result.appendIfPresent(
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
'tls-fingerprint',
);
result.appendIfPresent(
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
'tls-pubkey-sha256',
);
// AEAD
if (isPresent(proxy, 'aead')) {
@@ -286,6 +302,14 @@ function vless(proxy) {
// sni
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
result.appendIfPresent(
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
'tls-fingerprint',
);
result.appendIfPresent(
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
'tls-pubkey-sha256',
);
// tfo
result.appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
@@ -418,6 +442,14 @@ function hysteria2(proxy) {
// sni
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
result.appendIfPresent(
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
'tls-fingerprint',
);
result.appendIfPresent(
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
'tls-pubkey-sha256',
);
result.appendIfPresent(
`,skip-cert-verify=${proxy['skip-cert-verify']}`,
'skip-cert-verify',

View File

@@ -1,12 +1,30 @@
/* eslint-disable no-case-declarations */
import { Base64 } from 'js-base64';
import URI_Producer from './uri';
import $ from '@/core/app';
const URI = URI_Producer();
export default function V2Ray_Producer() {
const type = 'ALL';
const produce = (proxies) =>
Base64.encode(proxies.map((proxy) => URI.produce(proxy)).join('\n'));
const produce = (proxies) => {
let result = [];
proxies.map((proxy) => {
try {
result.push(URI.produce(proxy));
} catch (err) {
$.error(
`Cannot produce proxy: ${JSON.stringify(
proxy,
null,
2,
)}\nReason: ${err}`,
);
}
});
return Base64.encode(result.join('\n'));
};
return { type, produce };
}

View File

@@ -293,7 +293,7 @@ export function getFlag(name) {
'沪俄',
'Moscow',
],
'🇸🇦': ['Saudi', '沙特阿拉伯', '沙特'],
'🇸🇦': ['Saudi', '沙特阿拉伯', '沙特', 'Riyadh', '利雅得'],
'🇸🇪': ['Sweden', '瑞典'],
'🇸🇬': [
'Singapore',

View File

@@ -94,6 +94,23 @@ function getPolicyDescriptor(str) {
// };
// })();
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomPort(portString) {
let portParts = portString.split(/,|\//);
let randomPart = portParts[Math.floor(Math.random() * portParts.length)];
if (randomPart.includes('-')) {
let [min, max] = randomPart.split('-').map(Number);
return getRandomInt(min, max);
} else {
return Number(randomPart);
}
}
export {
ipAddress,
isIPv4,
@@ -105,4 +122,5 @@ export {
getIfPresent,
// utf8ArrayToStr,
getPolicyDescriptor,
getRandomPort,
};

View File

@@ -28,7 +28,9 @@ export function getPlatformFromUserAgent({ ua, UA }) {
return 'Stash';
} else if (
ua === 'meta' ||
(ua.indexOf('clash') !== -1 && ua.indexOf('meta') !== -1)
(ua.indexOf('clash') !== -1 && ua.indexOf('meta') !== -1) ||
ua.indexOf('clash-verge') !== -1 ||
ua.indexOf('flclash') !== -1
) {
return 'ClashMeta';
} else if (ua.indexOf('clash') !== -1) {

View File

@@ -42,6 +42,7 @@ function operator(proxies = [], targetPlatform, context) {
// parse, // 订阅解析
// process, // 节点操作/文件操作
// produce, // 输出订阅
// getRandomPort, // 获取随机端口(参考 ports 端口跳跃的格式 443,8443,5000-6000)
// ipAddress, // https://github.com/beaugunderson/ip-address
// isIPv4,
// isIPv6,