mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a2a2297f6 | ||
|
|
07d5a913f0 | ||
|
|
421df8f0d4 | ||
|
|
e14944dd19 | ||
|
|
bf18c51f6a | ||
|
|
23e8fbd1b7 | ||
|
|
b94b3c366b | ||
|
|
afb5f7b880 | ||
|
|
74ec133a79 | ||
|
|
2a76eb6462 | ||
|
|
9ac5e136a6 | ||
|
|
38f5a97a20 | ||
|
|
14a3488ce2 | ||
|
|
6afec4f668 | ||
|
|
b1874e510d | ||
|
|
48aaaf5c99 |
@@ -26,9 +26,9 @@ Core functionalities:
|
|||||||
|
|
||||||
### Supported Input Formats
|
### Supported Input Formats
|
||||||
|
|
||||||
> ⚠️ Do not use `Shadowrocket` to export URI and then import it as input. It is not a standard URI.
|
> ⚠️ Do not use `Shadowrocket` or `NekoBox` to export URI and then import it as input. The URIs exported in this way may not be standard URIs.
|
||||||
|
|
||||||
- [x] Normal Proxy(`socks5`, `socks5+tls`, `http`, `https`(it's ok))
|
- [x] Proxy URI Scheme(`socks5`, `socks5+tls`, `http`, `https`(it's ok))
|
||||||
|
|
||||||
example: `socks5+tls://user:pass@ip:port#name`
|
example: `socks5+tls://user:pass@ip:port#name`
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* ╚════██║██║ ██║██╔══██╗╚════╝╚════██║ ██║ ██║ ██║██╔══██╗██╔══╝
|
* ╚════██║██║ ██║██╔══██╗╚════╝╚════██║ ██║ ██║ ██║██╔══██╗██╔══╝
|
||||||
* ███████║╚██████╔╝██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║███████╗
|
* ███████║╚██████╔╝██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║███████╗
|
||||||
* ╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
* ╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
||||||
* Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket!
|
* Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket!
|
||||||
* @updated: <%= updated %>
|
* @updated: <%= updated %>
|
||||||
* @version: <%= pkg.version %>
|
* @version: <%= pkg.version %>
|
||||||
* @author: Peng-YM
|
* @author: Peng-YM
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.16.18",
|
"version": "2.16.32",
|
||||||
"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": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import getSurgeParser from './peggy/surge';
|
|||||||
import getLoonParser from './peggy/loon';
|
import getLoonParser from './peggy/loon';
|
||||||
import getQXParser from './peggy/qx';
|
import getQXParser from './peggy/qx';
|
||||||
import getTrojanURIParser from './peggy/trojan-uri';
|
import getTrojanURIParser from './peggy/trojan-uri';
|
||||||
|
import $ from '@/core/app';
|
||||||
|
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
|
|
||||||
@@ -40,8 +41,21 @@ function URI_PROXY() {
|
|||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
let [__, type, tls, username, password, server, port, query, name] =
|
let [__, type, tls, username, password, server, port, query, name] =
|
||||||
line.match(
|
line.match(
|
||||||
/^(socks5|http|http)(\+tls|s)?:\/\/(?:(.*?):(.*?)@)?(.*?):(\d+?)(\?.*?)?(?:#(.*?))?$/,
|
/^(socks5|http|http)(\+tls|s)?:\/\/(?:(.*?):(.*?)@)?(.*?)(?::(\d+?))?(\?.*?)?(?:#(.*?))?$/,
|
||||||
);
|
);
|
||||||
|
if (port) {
|
||||||
|
port = parseInt(port, 10);
|
||||||
|
} else {
|
||||||
|
if (tls) {
|
||||||
|
port = 443;
|
||||||
|
} else if (type === 'http') {
|
||||||
|
port = 80;
|
||||||
|
} else {
|
||||||
|
$.error(`port is not present in line: ${line}`);
|
||||||
|
throw new Error(`port is not present in line: ${line}`);
|
||||||
|
}
|
||||||
|
$.info(`port is not present in line: ${line}, set to ${port}`);
|
||||||
|
}
|
||||||
|
|
||||||
const proxy = {
|
const proxy = {
|
||||||
name:
|
name:
|
||||||
@@ -132,11 +146,10 @@ function URI_SS() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// handle obfs
|
// handle obfs
|
||||||
const idx = content.indexOf('?plugin=');
|
const pluginMatch = content.match(/[?&]plugin=([^&]+)/);
|
||||||
if (idx !== -1) {
|
if (pluginMatch) {
|
||||||
const pluginInfo = (
|
const pluginInfo = (
|
||||||
'plugin=' +
|
'plugin=' + decodeURIComponent(pluginMatch[1])
|
||||||
decodeURIComponent(content.split('?plugin=')[1].split('&')[0])
|
|
||||||
).split(';');
|
).split(';');
|
||||||
const params = {};
|
const params = {};
|
||||||
for (const item of pluginInfo) {
|
for (const item of pluginInfo) {
|
||||||
@@ -161,6 +174,16 @@ function URI_SS() {
|
|||||||
tls: getIfPresent(params.tls),
|
tls: getIfPresent(params.tls),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'shadow-tls': {
|
||||||
|
proxy.plugin = 'shadow-tls';
|
||||||
|
const version = getIfNotBlank(params['version']);
|
||||||
|
proxy['plugin-opts'] = {
|
||||||
|
host: getIfNotBlank(params['host']),
|
||||||
|
password: getIfNotBlank(params['password']),
|
||||||
|
version: version ? parseInt(version, 10) : undefined,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unsupported plugin option: ${params.plugin}`,
|
`Unsupported plugin option: ${params.plugin}`,
|
||||||
@@ -529,6 +552,9 @@ function URI_VLESS() {
|
|||||||
if (params.sid) {
|
if (params.sid) {
|
||||||
opts['short-id'] = params.sid;
|
opts['short-id'] = params.sid;
|
||||||
}
|
}
|
||||||
|
if (params.spx) {
|
||||||
|
opts['_spider-x'] = params.spx;
|
||||||
|
}
|
||||||
if (Object.keys(opts).length > 0) {
|
if (Object.keys(opts).length > 0) {
|
||||||
// proxy[`${params.security}-opts`] = opts;
|
// proxy[`${params.security}-opts`] = opts;
|
||||||
proxy[`${params.security}-opts`] = opts;
|
proxy[`${params.security}-opts`] = opts;
|
||||||
@@ -596,6 +622,13 @@ function URI_VLESS() {
|
|||||||
// mKCP 的伪装头部类型。当前可选值有 none / srtp / utp / wechat-video / dtls / wireguard。省略时默认值为 none,即不使用伪装头部,但不可以为空字符串。
|
// mKCP 的伪装头部类型。当前可选值有 none / srtp / utp / wechat-video / dtls / wireguard。省略时默认值为 none,即不使用伪装头部,但不可以为空字符串。
|
||||||
proxy.headerType = params.headerType || 'none';
|
proxy.headerType = params.headerType || 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.mode) {
|
||||||
|
proxy._mode = params.mode;
|
||||||
|
}
|
||||||
|
if (params.extra) {
|
||||||
|
proxy._extra = params.extra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/udp_port/others)* {
|
shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/udp_port/others)* {
|
||||||
proxy.type = "ss";
|
proxy.type = "ss";
|
||||||
// handle obfs
|
// handle obfs
|
||||||
if (obfs.type == "http" || obfs.type === "tls") {
|
if (obfs.type == "http" || obfs.type === "tls") {
|
||||||
@@ -52,7 +52,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/
|
|||||||
}
|
}
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "vmess";
|
proxy.type = "vmess";
|
||||||
proxy.cipher = proxy.cipher || "none";
|
proxy.cipher = proxy.cipher || "none";
|
||||||
if (proxy.aead) {
|
if (proxy.aead) {
|
||||||
@@ -63,25 +63,25 @@ vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/
|
|||||||
handleWebsocket();
|
handleWebsocket();
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "trojan";
|
proxy.type = "trojan";
|
||||||
handleWebsocket();
|
handleWebsocket();
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "http";
|
proxy.type = "http";
|
||||||
proxy.tls = true;
|
proxy.tls = true;
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "http";
|
proxy.type = "http";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
ssh = tag equals "ssh" address (username password)? (usernamek passwordk)? (server_fingerprint/idle_timeout/private_key/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
ssh = tag equals "ssh" address (username password)? (usernamek passwordk)? (server_fingerprint/idle_timeout/private_key/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "ssh";
|
proxy.type = "ssh";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "snell";
|
proxy.type = "snell";
|
||||||
// handle obfs
|
// handle obfs
|
||||||
if (obfs.type == "http" || obfs.type === "tls") {
|
if (obfs.type == "http" || obfs.type === "tls") {
|
||||||
@@ -104,20 +104,20 @@ wireguard = tag equals "wireguard" (section_name/no_error_alert/ip_version/under
|
|||||||
proxy.type = "wireguard-surge";
|
proxy.type = "wireguard-surge";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/tls_verification/passwordk/tls_fingerprint/download_bandwidth/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/port_hopping_interval/others)* {
|
hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/fast_open/tfo/tls_verification/passwordk/tls_fingerprint/download_bandwidth/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/port_hopping_interval/others)* {
|
||||||
proxy.type = "hysteria2";
|
proxy.type = "hysteria2";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "socks5";
|
proxy.type = "socks5";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/tls_fingerprint/tls_verification/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/tls_fingerprint/tls_verification/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "socks5";
|
proxy.type = "socks5";
|
||||||
proxy.tls = true;
|
proxy.tls = true;
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
direct = tag equals "direct" (udp_relay/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/block_quic/others)* {
|
direct = tag equals "direct" (udp_relay/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/block_quic/others)* {
|
||||||
proxy.type = "direct";
|
proxy.type = "direct";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/udp_port/others)* {
|
shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/udp_port/others)* {
|
||||||
proxy.type = "ss";
|
proxy.type = "ss";
|
||||||
// handle obfs
|
// handle obfs
|
||||||
if (obfs.type == "http" || obfs.type === "tls") {
|
if (obfs.type == "http" || obfs.type === "tls") {
|
||||||
@@ -50,7 +50,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/
|
|||||||
}
|
}
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "vmess";
|
proxy.type = "vmess";
|
||||||
proxy.cipher = proxy.cipher || "none";
|
proxy.cipher = proxy.cipher || "none";
|
||||||
if (proxy.aead) {
|
if (proxy.aead) {
|
||||||
@@ -61,25 +61,25 @@ vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/
|
|||||||
handleWebsocket();
|
handleWebsocket();
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "trojan";
|
proxy.type = "trojan";
|
||||||
handleWebsocket();
|
handleWebsocket();
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "http";
|
proxy.type = "http";
|
||||||
proxy.tls = true;
|
proxy.tls = true;
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "http";
|
proxy.type = "http";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
ssh = tag equals "ssh" address (username password)? (usernamek passwordk)? (server_fingerprint/idle_timeout/private_key/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
ssh = tag equals "ssh" address (username password)? (usernamek passwordk)? (server_fingerprint/idle_timeout/private_key/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "ssh";
|
proxy.type = "ssh";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "snell";
|
proxy.type = "snell";
|
||||||
// handle obfs
|
// handle obfs
|
||||||
if (obfs.type == "http" || obfs.type === "tls") {
|
if (obfs.type == "http" || obfs.type === "tls") {
|
||||||
@@ -106,16 +106,16 @@ hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying
|
|||||||
proxy.type = "hysteria2";
|
proxy.type = "hysteria2";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "socks5";
|
proxy.type = "socks5";
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/tls_fingerprint/tls_verification/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (udp_relay/no_error_alert/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/sni/tls_fingerprint/tls_verification/fast_open/tfo/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* {
|
||||||
proxy.type = "socks5";
|
proxy.type = "socks5";
|
||||||
proxy.tls = true;
|
proxy.tls = true;
|
||||||
handleShadowTLS();
|
handleShadowTLS();
|
||||||
}
|
}
|
||||||
direct = tag equals "direct" (udp_relay/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/block_quic/others)* {
|
direct = tag equals "direct" (udp_relay/ip_version/underlying_proxy/tos/allow_other_interface/interface/test_url/test_udp/test_timeout/hybrid/no_error_alert/fast_open/tfo/block_quic/others)* {
|
||||||
proxy.type = "direct";
|
proxy.type = "direct";
|
||||||
}
|
}
|
||||||
address = comma server:server comma port:port {
|
address = comma server:server comma port:port {
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ port = digits:[0-9]+ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
params = "?" head:param tail:("&"@param)* {
|
params = "?" head:param tail:("&"@param)* {
|
||||||
|
for (const [key, value] of Object.entries(params)) {
|
||||||
|
params[key] = decodeURIComponent(value);
|
||||||
|
}
|
||||||
proxy["skip-cert-verify"] = toBool(params["allowInsecure"]);
|
proxy["skip-cert-verify"] = toBool(params["allowInsecure"]);
|
||||||
proxy.sni = params["sni"] || params["peer"];
|
proxy.sni = params["sni"] || params["peer"];
|
||||||
proxy['client-fingerprint'] = params.fp;
|
proxy['client-fingerprint'] = params.fp;
|
||||||
@@ -115,6 +118,27 @@ params = "?" head:param tail:("&"@param)* {
|
|||||||
$set(proxy, proxy.network+"-opts.v2ray-http-upgrade-fast-open", true);
|
$set(proxy, proxy.network+"-opts.v2ray-http-upgrade-fast-open", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (['reality'].includes(params.security)) {
|
||||||
|
const opts = {};
|
||||||
|
if (params.pbk) {
|
||||||
|
opts['public-key'] = params.pbk;
|
||||||
|
}
|
||||||
|
if (params.sid) {
|
||||||
|
opts['short-id'] = params.sid;
|
||||||
|
}
|
||||||
|
if (params.spx) {
|
||||||
|
opts['_spider-x'] = params.spx;
|
||||||
|
}
|
||||||
|
if (params.mode) {
|
||||||
|
proxy._mode = params.mode;
|
||||||
|
}
|
||||||
|
if (params.extra) {
|
||||||
|
proxy._extra = params.extra;
|
||||||
|
}
|
||||||
|
if (Object.keys(opts).length > 0) {
|
||||||
|
$set(proxy, params.security+"-opts", opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.udp = toBool(params["udp"]);
|
proxy.udp = toBool(params["udp"]);
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ port = digits:[0-9]+ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
params = "?" head:param tail:("&"@param)* {
|
params = "?" head:param tail:("&"@param)* {
|
||||||
|
for (const [key, value] of Object.entries(params)) {
|
||||||
|
params[key] = decodeURIComponent(value);
|
||||||
|
}
|
||||||
proxy["skip-cert-verify"] = toBool(params["allowInsecure"]);
|
proxy["skip-cert-verify"] = toBool(params["allowInsecure"]);
|
||||||
proxy.sni = params["sni"] || params["peer"];
|
proxy.sni = params["sni"] || params["peer"];
|
||||||
proxy['client-fingerprint'] = params.fp;
|
proxy['client-fingerprint'] = params.fp;
|
||||||
@@ -113,6 +116,27 @@ params = "?" head:param tail:("&"@param)* {
|
|||||||
$set(proxy, proxy.network+"-opts.v2ray-http-upgrade-fast-open", true);
|
$set(proxy, proxy.network+"-opts.v2ray-http-upgrade-fast-open", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (['reality'].includes(params.security)) {
|
||||||
|
const opts = {};
|
||||||
|
if (params.pbk) {
|
||||||
|
opts['public-key'] = params.pbk;
|
||||||
|
}
|
||||||
|
if (params.sid) {
|
||||||
|
opts['short-id'] = params.sid;
|
||||||
|
}
|
||||||
|
if (params.spx) {
|
||||||
|
opts['_spider-x'] = params.spx;
|
||||||
|
}
|
||||||
|
if (params.mode) {
|
||||||
|
proxy._mode = params.mode;
|
||||||
|
}
|
||||||
|
if (params.extra) {
|
||||||
|
proxy._extra = params.extra;
|
||||||
|
}
|
||||||
|
if (Object.keys(opts).length > 0) {
|
||||||
|
$set(proxy, params.security+"-opts", opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.udp = toBool(params["udp"]);
|
proxy.udp = toBool(params["udp"]);
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ export default function Clash_Producer() {
|
|||||||
proxy['preshared-key'] =
|
proxy['preshared-key'] =
|
||||||
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
||||||
proxy['pre-shared-key'] = proxy['preshared-key'];
|
proxy['pre-shared-key'] = proxy['preshared-key'];
|
||||||
|
} else if (proxy.type === 'snell' && proxy.version < 3) {
|
||||||
|
delete proxy.udp;
|
||||||
} else if (proxy.type === 'vless') {
|
} else if (proxy.type === 'vless') {
|
||||||
if (isPresent(proxy, 'sni')) {
|
if (isPresent(proxy, 'sni')) {
|
||||||
proxy.servername = proxy.sni;
|
proxy.servername = proxy.sni;
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ export default function ClashMeta_Producer() {
|
|||||||
isPresent(proxy, 'cipher') &&
|
isPresent(proxy, 'cipher') &&
|
||||||
![
|
![
|
||||||
'auto',
|
'auto',
|
||||||
|
'none',
|
||||||
|
'zero',
|
||||||
'aes-128-gcm',
|
'aes-128-gcm',
|
||||||
'chacha20-poly1305',
|
'chacha20-poly1305',
|
||||||
'none',
|
|
||||||
].includes(proxy.cipher)
|
].includes(proxy.cipher)
|
||||||
) {
|
) {
|
||||||
proxy.cipher = 'auto';
|
proxy.cipher = 'auto';
|
||||||
@@ -86,6 +87,8 @@ export default function ClashMeta_Producer() {
|
|||||||
proxy['preshared-key'] =
|
proxy['preshared-key'] =
|
||||||
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
||||||
proxy['pre-shared-key'] = proxy['preshared-key'];
|
proxy['pre-shared-key'] = proxy['preshared-key'];
|
||||||
|
} else if (proxy.type === 'snell' && proxy.version < 3) {
|
||||||
|
delete proxy.udp;
|
||||||
} else if (proxy.type === 'vless') {
|
} else if (proxy.type === 'vless') {
|
||||||
if (isPresent(proxy, 'sni')) {
|
if (isPresent(proxy, 'sni')) {
|
||||||
proxy.servername = proxy.sni;
|
proxy.servername = proxy.sni;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export default function Egern_Producer() {
|
|||||||
'hysteria2',
|
'hysteria2',
|
||||||
'vless',
|
'vless',
|
||||||
'vmess',
|
'vmess',
|
||||||
|
'tuic',
|
||||||
].includes(proxy.type) ||
|
].includes(proxy.type) ||
|
||||||
(proxy.type === 'ss' &&
|
(proxy.type === 'ss' &&
|
||||||
((proxy.plugin === 'obfs' &&
|
((proxy.plugin === 'obfs' &&
|
||||||
@@ -47,23 +48,12 @@ export default function Egern_Producer() {
|
|||||||
'salsa20',
|
'salsa20',
|
||||||
'chacha20',
|
'chacha20',
|
||||||
'chacha20-ietf',
|
'chacha20-ietf',
|
||||||
...(opts['include-unsupported-proxy']
|
'2022-blake3-aes-128-gcm',
|
||||||
? [
|
'2022-blake3-aes-256-gcm',
|
||||||
'2022-blake3-aes-128-gcm',
|
|
||||||
'2022-blake3-aes-256-gcm',
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
].includes(proxy.cipher))) ||
|
].includes(proxy.cipher))) ||
|
||||||
(proxy.type === 'vmess' &&
|
(proxy.type === 'vmess' &&
|
||||||
(![
|
!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||||
'auto',
|
proxy.network) ||
|
||||||
'aes-128-gcm',
|
|
||||||
'chacha20-poly1305',
|
|
||||||
'none',
|
|
||||||
'zero',
|
|
||||||
].includes(proxy.cipher) ||
|
|
||||||
(!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
|
||||||
proxy.network))) ||
|
|
||||||
(proxy.type === 'trojan' &&
|
(proxy.type === 'trojan' &&
|
||||||
!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||||
proxy.network) ||
|
proxy.network) ||
|
||||||
@@ -71,7 +61,10 @@ export default function Egern_Producer() {
|
|||||||
(typeof proxy.flow !== 'undefined' ||
|
(typeof proxy.flow !== 'undefined' ||
|
||||||
proxy['reality-opts'] ||
|
proxy['reality-opts'] ||
|
||||||
(!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
(!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||||
proxy.network)))
|
proxy.network))) ||
|
||||||
|
(proxy.type === 'tuic' &&
|
||||||
|
proxy.token &&
|
||||||
|
proxy.token.length !== 0)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -152,6 +145,23 @@ export default function Egern_Producer() {
|
|||||||
proxy.obfs = 'salamander';
|
proxy.obfs = 'salamander';
|
||||||
proxy.obfs_password = proxy['obfs-password'];
|
proxy.obfs_password = proxy['obfs-password'];
|
||||||
}
|
}
|
||||||
|
} else if (proxy.type === 'tuic') {
|
||||||
|
proxy = {
|
||||||
|
type: 'tuic',
|
||||||
|
name: proxy.name,
|
||||||
|
server: proxy.server,
|
||||||
|
port: proxy.port,
|
||||||
|
uuid: proxy.uuid,
|
||||||
|
password: proxy.password,
|
||||||
|
next_hop: proxy.next_hop,
|
||||||
|
sni: proxy.sni,
|
||||||
|
alpn: Array.isArray(proxy.alpn)
|
||||||
|
? proxy.alpn
|
||||||
|
: [proxy.alpn || 'h3'],
|
||||||
|
skip_tls_verify: proxy['skip-cert-verify'],
|
||||||
|
port_hopping: proxy.ports,
|
||||||
|
port_hopping_interval: proxy['hop-interval'],
|
||||||
|
};
|
||||||
} else if (proxy.type === 'trojan') {
|
} else if (proxy.type === 'trojan') {
|
||||||
if (proxy.network === 'ws') {
|
if (proxy.network === 'ws') {
|
||||||
proxy.websocket = {
|
proxy.websocket = {
|
||||||
@@ -174,6 +184,19 @@ export default function Egern_Producer() {
|
|||||||
websocket: proxy.websocket,
|
websocket: proxy.websocket,
|
||||||
};
|
};
|
||||||
} else if (proxy.type === 'vmess') {
|
} else if (proxy.type === 'vmess') {
|
||||||
|
let security = proxy.cipher;
|
||||||
|
if (
|
||||||
|
security &&
|
||||||
|
![
|
||||||
|
'auto',
|
||||||
|
'none',
|
||||||
|
'zero',
|
||||||
|
'aes-128-gcm',
|
||||||
|
'chacha20-poly1305',
|
||||||
|
].includes(security)
|
||||||
|
) {
|
||||||
|
security = 'auto';
|
||||||
|
}
|
||||||
if (proxy.network === 'ws') {
|
if (proxy.network === 'ws') {
|
||||||
proxy.transport = {
|
proxy.transport = {
|
||||||
[proxy.tls ? 'wss' : 'ws']: {
|
[proxy.tls ? 'wss' : 'ws']: {
|
||||||
@@ -218,7 +241,7 @@ export default function Egern_Producer() {
|
|||||||
server: proxy.server,
|
server: proxy.server,
|
||||||
port: proxy.port,
|
port: proxy.port,
|
||||||
user_id: proxy.uuid,
|
user_id: proxy.uuid,
|
||||||
security: proxy.cipher,
|
security,
|
||||||
tfo: proxy.tfo || proxy['fast-open'],
|
tfo: proxy.tfo || proxy['fast-open'],
|
||||||
legacy: proxy.legacy,
|
legacy: proxy.legacy,
|
||||||
udp_relay:
|
udp_relay:
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ export default function Loon_Producer() {
|
|||||||
const produce = (proxy, type, opts = {}) => {
|
const produce = (proxy, type, opts = {}) => {
|
||||||
switch (proxy.type) {
|
switch (proxy.type) {
|
||||||
case 'ss':
|
case 'ss':
|
||||||
return shadowsocks(proxy, opts['include-unsupported-proxy']);
|
return shadowsocks(proxy);
|
||||||
case 'ssr':
|
case 'ssr':
|
||||||
return shadowsocksr(proxy, opts['include-unsupported-proxy']);
|
return shadowsocksr(proxy);
|
||||||
case 'trojan':
|
case 'trojan':
|
||||||
return trojan(proxy);
|
return trojan(proxy);
|
||||||
case 'vmess':
|
case 'vmess':
|
||||||
@@ -40,7 +40,7 @@ export default function Loon_Producer() {
|
|||||||
return { produce };
|
return { produce };
|
||||||
}
|
}
|
||||||
|
|
||||||
function shadowsocks(proxy, includeUnsupportedProxy) {
|
function shadowsocks(proxy) {
|
||||||
const result = new Result(proxy);
|
const result = new Result(proxy);
|
||||||
if (
|
if (
|
||||||
![
|
![
|
||||||
@@ -74,8 +74,6 @@ function shadowsocks(proxy, includeUnsupportedProxy) {
|
|||||||
`${proxy.name}=shadowsocks,${proxy.server},${proxy.port},${proxy.cipher},"${proxy.password}"`,
|
`${proxy.name}=shadowsocks,${proxy.server},${proxy.port},${proxy.cipher},"${proxy.password}"`,
|
||||||
);
|
);
|
||||||
|
|
||||||
let isShadowTLS;
|
|
||||||
|
|
||||||
// obfs
|
// obfs
|
||||||
if (isPresent(proxy, 'plugin')) {
|
if (isPresent(proxy, 'plugin')) {
|
||||||
if (proxy.plugin === 'obfs') {
|
if (proxy.plugin === 'obfs') {
|
||||||
@@ -107,7 +105,6 @@ function shadowsocks(proxy, includeUnsupportedProxy) {
|
|||||||
);
|
);
|
||||||
// udp-port
|
// udp-port
|
||||||
result.appendIfPresent(`,udp-port=${proxy['udp-port']}`, 'udp-port');
|
result.appendIfPresent(`,udp-port=${proxy['udp-port']}`, 'udp-port');
|
||||||
isShadowTLS = true;
|
|
||||||
} else if (['shadow-tls'].includes(proxy.plugin) && proxy['plugin-opts']) {
|
} else if (['shadow-tls'].includes(proxy.plugin) && proxy['plugin-opts']) {
|
||||||
const password = proxy['plugin-opts'].password;
|
const password = proxy['plugin-opts'].password;
|
||||||
const host = proxy['plugin-opts'].host;
|
const host = proxy['plugin-opts'].host;
|
||||||
@@ -130,7 +127,6 @@ function shadowsocks(proxy, includeUnsupportedProxy) {
|
|||||||
`,udp-port=${proxy['udp-port']}`,
|
`,udp-port=${proxy['udp-port']}`,
|
||||||
'udp-port',
|
'udp-port',
|
||||||
);
|
);
|
||||||
isShadowTLS = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,11 +138,6 @@ function shadowsocks(proxy, includeUnsupportedProxy) {
|
|||||||
result.append(`,udp=true`);
|
result.append(`,udp=true`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!includeUnsupportedProxy && isShadowTLS) {
|
|
||||||
throw new Error(
|
|
||||||
`shadow-tls is not supported(请使用 includeUnsupportedProxy 参数)`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version'];
|
const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version'];
|
||||||
result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version');
|
result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version');
|
||||||
|
|
||||||
@@ -170,8 +161,6 @@ function shadowsocksr(proxy, includeUnsupportedProxy) {
|
|||||||
result.appendIfPresent(`,obfs=${proxy.obfs}`, 'obfs');
|
result.appendIfPresent(`,obfs=${proxy.obfs}`, 'obfs');
|
||||||
result.appendIfPresent(`,obfs-param=${proxy['obfs-param']}`, 'obfs-param');
|
result.appendIfPresent(`,obfs-param=${proxy['obfs-param']}`, 'obfs-param');
|
||||||
|
|
||||||
let isShadowTLS;
|
|
||||||
|
|
||||||
// shadow-tls
|
// shadow-tls
|
||||||
if (isPresent(proxy, 'shadow-tls-password')) {
|
if (isPresent(proxy, 'shadow-tls-password')) {
|
||||||
result.append(`,shadow-tls-password=${proxy['shadow-tls-password']}`);
|
result.append(`,shadow-tls-password=${proxy['shadow-tls-password']}`);
|
||||||
@@ -186,7 +175,6 @@ function shadowsocksr(proxy, includeUnsupportedProxy) {
|
|||||||
);
|
);
|
||||||
// udp-port
|
// udp-port
|
||||||
result.appendIfPresent(`,udp-port=${proxy['udp-port']}`, 'udp-port');
|
result.appendIfPresent(`,udp-port=${proxy['udp-port']}`, 'udp-port');
|
||||||
isShadowTLS = true;
|
|
||||||
} else if (['shadow-tls'].includes(proxy.plugin) && proxy['plugin-opts']) {
|
} else if (['shadow-tls'].includes(proxy.plugin) && proxy['plugin-opts']) {
|
||||||
const password = proxy['plugin-opts'].password;
|
const password = proxy['plugin-opts'].password;
|
||||||
const host = proxy['plugin-opts'].host;
|
const host = proxy['plugin-opts'].host;
|
||||||
@@ -209,7 +197,6 @@ function shadowsocksr(proxy, includeUnsupportedProxy) {
|
|||||||
`,udp-port=${proxy['udp-port']}`,
|
`,udp-port=${proxy['udp-port']}`,
|
||||||
'udp-port',
|
'udp-port',
|
||||||
);
|
);
|
||||||
isShadowTLS = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +208,6 @@ function shadowsocksr(proxy, includeUnsupportedProxy) {
|
|||||||
result.append(`,udp=true`);
|
result.append(`,udp=true`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!includeUnsupportedProxy && isShadowTLS) {
|
|
||||||
throw new Error(
|
|
||||||
`shadow-tls is not supported(请使用 includeUnsupportedProxy 参数)`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version'];
|
const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version'];
|
||||||
result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version');
|
result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { isPresent } from '@/core/proxy-utils/producers/utils';
|
import { isPresent } from '@/core/proxy-utils/producers/utils';
|
||||||
|
|
||||||
export default function ShadowRocket_Producer() {
|
export default function Shadowrocket_Producer() {
|
||||||
const type = 'ALL';
|
const type = 'ALL';
|
||||||
const produce = (proxies, type, opts = {}) => {
|
const produce = (proxies, type, opts = {}) => {
|
||||||
const list = proxies
|
const list = proxies
|
||||||
@@ -32,9 +32,10 @@ export default function ShadowRocket_Producer() {
|
|||||||
isPresent(proxy, 'cipher') &&
|
isPresent(proxy, 'cipher') &&
|
||||||
![
|
![
|
||||||
'auto',
|
'auto',
|
||||||
|
'none',
|
||||||
|
'zero',
|
||||||
'aes-128-gcm',
|
'aes-128-gcm',
|
||||||
'chacha20-poly1305',
|
'chacha20-poly1305',
|
||||||
'none',
|
|
||||||
].includes(proxy.cipher)
|
].includes(proxy.cipher)
|
||||||
) {
|
) {
|
||||||
proxy.cipher = 'auto';
|
proxy.cipher = 'auto';
|
||||||
@@ -102,6 +103,8 @@ export default function ShadowRocket_Producer() {
|
|||||||
proxy['preshared-key'] =
|
proxy['preshared-key'] =
|
||||||
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
||||||
proxy['pre-shared-key'] = proxy['preshared-key'];
|
proxy['pre-shared-key'] = proxy['preshared-key'];
|
||||||
|
} else if (proxy.type === 'snell' && proxy.version < 3) {
|
||||||
|
delete proxy.udp;
|
||||||
} else if (proxy.type === 'vless') {
|
} else if (proxy.type === 'vless') {
|
||||||
if (isPresent(proxy, 'sni')) {
|
if (isPresent(proxy, 'sni')) {
|
||||||
proxy.servername = proxy.sni;
|
proxy.servername = proxy.sni;
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ export default function Stash_Producer() {
|
|||||||
proxy['preshared-key'] =
|
proxy['preshared-key'] =
|
||||||
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
proxy['preshared-key'] ?? proxy['pre-shared-key'];
|
||||||
proxy['pre-shared-key'] = proxy['preshared-key'];
|
proxy['pre-shared-key'] = proxy['preshared-key'];
|
||||||
|
} else if (proxy.type === 'snell' && proxy.version < 3) {
|
||||||
|
delete proxy.udp;
|
||||||
} else if (proxy.type === 'vless') {
|
} else if (proxy.type === 'vless') {
|
||||||
if (isPresent(proxy, 'sni')) {
|
if (isPresent(proxy, 'sni')) {
|
||||||
proxy.servername = proxy.sni;
|
proxy.servername = proxy.sni;
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ export default function URI_Producer() {
|
|||||||
}${opts.tls ? ';tls' : ''}`,
|
}${opts.tls ? ';tls' : ''}`,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'shadow-tls':
|
||||||
|
result += encodeURIComponent(
|
||||||
|
`shadow-tls;host=${opts.host};password=${opts.password};version=${opts.version}`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unsupported plugin option: ${proxy.plugin}`,
|
`Unsupported plugin option: ${proxy.plugin}`,
|
||||||
@@ -149,6 +154,7 @@ export default function URI_Producer() {
|
|||||||
const isReality = proxy['reality-opts'];
|
const isReality = proxy['reality-opts'];
|
||||||
let sid = '';
|
let sid = '';
|
||||||
let pbk = '';
|
let pbk = '';
|
||||||
|
let spx = '';
|
||||||
if (isReality) {
|
if (isReality) {
|
||||||
security = 'reality';
|
security = 'reality';
|
||||||
const publicKey = proxy['reality-opts']?.['public-key'];
|
const publicKey = proxy['reality-opts']?.['public-key'];
|
||||||
@@ -159,6 +165,10 @@ export default function URI_Producer() {
|
|||||||
if (shortId) {
|
if (shortId) {
|
||||||
sid = `&sid=${encodeURIComponent(shortId)}`;
|
sid = `&sid=${encodeURIComponent(shortId)}`;
|
||||||
}
|
}
|
||||||
|
const spiderX = proxy['reality-opts']?.['_spider-x'];
|
||||||
|
if (spiderX) {
|
||||||
|
spx = `&spx=${encodeURIComponent(spiderX)}`;
|
||||||
|
}
|
||||||
} else if (proxy.tls) {
|
} else if (proxy.tls) {
|
||||||
security = 'tls';
|
security = 'tls';
|
||||||
}
|
}
|
||||||
@@ -188,6 +198,14 @@ export default function URI_Producer() {
|
|||||||
if (proxy.flow) {
|
if (proxy.flow) {
|
||||||
flow = `&flow=${encodeURIComponent(proxy.flow)}`;
|
flow = `&flow=${encodeURIComponent(proxy.flow)}`;
|
||||||
}
|
}
|
||||||
|
let extra = '';
|
||||||
|
if (proxy._extra) {
|
||||||
|
extra = `&extra=${encodeURIComponent(proxy._extra)}`;
|
||||||
|
}
|
||||||
|
let mode = '';
|
||||||
|
if (proxy._mode) {
|
||||||
|
mode = `&mode=${encodeURIComponent(proxy._mode)}`;
|
||||||
|
}
|
||||||
let vlessType = proxy.network;
|
let vlessType = proxy.network;
|
||||||
if (
|
if (
|
||||||
proxy.network === 'ws' &&
|
proxy.network === 'ws' &&
|
||||||
@@ -254,7 +272,7 @@ export default function URI_Producer() {
|
|||||||
proxy.port
|
proxy.port
|
||||||
}?security=${encodeURIComponent(
|
}?security=${encodeURIComponent(
|
||||||
security,
|
security,
|
||||||
)}${vlessTransport}${alpn}${allowInsecure}${sni}${fp}${flow}${sid}${pbk}#${encodeURIComponent(
|
)}${vlessTransport}${alpn}${allowInsecure}${sni}${fp}${flow}${sid}${spx}${pbk}${mode}${extra}#${encodeURIComponent(
|
||||||
proxy.name,
|
proxy.name,
|
||||||
)}`;
|
)}`;
|
||||||
break;
|
break;
|
||||||
@@ -324,11 +342,41 @@ export default function URI_Producer() {
|
|||||||
: proxy.alpn.join(','),
|
: proxy.alpn.join(','),
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
const trojanIsReality = proxy['reality-opts'];
|
||||||
|
let trojanSid = '';
|
||||||
|
let trojanPbk = '';
|
||||||
|
let trojanSpx = '';
|
||||||
|
let trojanSecurity = '';
|
||||||
|
let trojanMode = '';
|
||||||
|
let trojanExtra = '';
|
||||||
|
if (trojanIsReality) {
|
||||||
|
trojanSecurity = `&security=reality`;
|
||||||
|
const publicKey = proxy['reality-opts']?.['public-key'];
|
||||||
|
if (publicKey) {
|
||||||
|
trojanPbk = `&pbk=${encodeURIComponent(publicKey)}`;
|
||||||
|
}
|
||||||
|
const shortId = proxy['reality-opts']?.['short-id'];
|
||||||
|
if (shortId) {
|
||||||
|
trojanSid = `&sid=${encodeURIComponent(shortId)}`;
|
||||||
|
}
|
||||||
|
const spiderX = proxy['reality-opts']?.['_spider-x'];
|
||||||
|
if (spiderX) {
|
||||||
|
trojanSpx = `&spx=${encodeURIComponent(spiderX)}`;
|
||||||
|
}
|
||||||
|
if (proxy._extra) {
|
||||||
|
trojanExtra = `&extra=${encodeURIComponent(
|
||||||
|
proxy._extra,
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
if (proxy._mode) {
|
||||||
|
trojanMode = `&mode=${encodeURIComponent(proxy._mode)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
result = `trojan://${proxy.password}@${proxy.server}:${
|
result = `trojan://${proxy.password}@${proxy.server}:${
|
||||||
proxy.port
|
proxy.port
|
||||||
}?sni=${encodeURIComponent(proxy.sni || proxy.server)}${
|
}?sni=${encodeURIComponent(proxy.sni || proxy.server)}${
|
||||||
proxy['skip-cert-verify'] ? '&allowInsecure=1' : ''
|
proxy['skip-cert-verify'] ? '&allowInsecure=1' : ''
|
||||||
}${trojanTransport}${trojanAlpn}${trojanFp}#${encodeURIComponent(
|
}${trojanTransport}${trojanAlpn}${trojanFp}${trojanSecurity}${trojanSid}${trojanPbk}${trojanSpx}${trojanMode}${trojanExtra}#${encodeURIComponent(
|
||||||
proxy.name,
|
proxy.name,
|
||||||
)}`;
|
)}`;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ async function doSync() {
|
|||||||
const files = {};
|
const files = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const valid = [];
|
||||||
const invalid = [];
|
const invalid = [];
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
const allCols = $.read(COLLECTIONS_KEY);
|
const allCols = $.read(COLLECTIONS_KEY);
|
||||||
@@ -156,19 +157,26 @@ async function doSync() {
|
|||||||
files[encodeURIComponent(artifact.name)] = {
|
files[encodeURIComponent(artifact.name)] = {
|
||||||
content: output,
|
content: output,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
valid.push(artifact.name);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$.error(
|
$.error(
|
||||||
`同步配置 ${artifact.name} 发生错误: ${e.message ?? e}`,
|
`生成同步配置 ${artifact.name} 发生错误: ${
|
||||||
|
e.message ?? e
|
||||||
|
}`,
|
||||||
);
|
);
|
||||||
invalid.push(artifact.name);
|
invalid.push(artifact.name);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (invalid.length > 0) {
|
$.info(`${valid.length} 个同步配置生成成功: ${valid.join(', ')}`);
|
||||||
|
$.info(`${invalid.length} 个同步配置生成失败: ${invalid.join(', ')}`);
|
||||||
|
|
||||||
|
if (valid.length === 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`同步配置 ${invalid.join(', ')} 发生错误 详情请查看日志`,
|
`同步配置 ${invalid.join(', ')} 生成失败 详情请查看日志`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +192,11 @@ async function doSync() {
|
|||||||
$.info(JSON.stringify(body, null, 2));
|
$.info(JSON.stringify(body, null, 2));
|
||||||
|
|
||||||
for (const artifact of allArtifacts) {
|
for (const artifact of allArtifacts) {
|
||||||
if (artifact.sync) {
|
if (
|
||||||
|
artifact.sync &&
|
||||||
|
artifact.source &&
|
||||||
|
valid.includes(artifact.name)
|
||||||
|
) {
|
||||||
artifact.updated = new Date().getTime();
|
artifact.updated = new Date().getTime();
|
||||||
// extract real url from gist
|
// extract real url from gist
|
||||||
let files = body.files;
|
let files = body.files;
|
||||||
@@ -212,9 +224,18 @@ async function doSync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$.write(allArtifacts, ARTIFACTS_KEY);
|
$.write(allArtifacts, ARTIFACTS_KEY);
|
||||||
$.notify('🌍 Sub-Store', '全部订阅同步成功!');
|
$.info('上传配置成功');
|
||||||
|
|
||||||
|
if (invalid.length > 0) {
|
||||||
|
$.notify(
|
||||||
|
'🌍 Sub-Store',
|
||||||
|
`同步配置成功 ${valid.length} 个, 失败 ${invalid.length} 个, 详情请查看日志`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$.notify('🌍 Sub-Store', '同步配置完成');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$.notify('🌍 Sub-Store', '同步订阅失败', `原因:${e.message ?? e}`);
|
$.notify('🌍 Sub-Store', '同步配置失败', `原因:${e.message ?? e}`);
|
||||||
$.error(`无法同步订阅配置到 Gist,原因:${e}`);
|
$.error(`无法同步配置到 Gist,原因:${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,7 +293,10 @@ async function downloadSubscription(req, res) {
|
|||||||
}
|
}
|
||||||
res.set(
|
res.set(
|
||||||
'subscription-userinfo',
|
'subscription-userinfo',
|
||||||
[subUserInfo, flowInfo].filter((i) => i).join('; '),
|
[subUserInfo, flowInfo]
|
||||||
|
.filter((i) => i)
|
||||||
|
.join('; ')
|
||||||
|
.replace(/\s*;\s*;\s*/g, ';'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +554,10 @@ async function downloadCollection(req, res) {
|
|||||||
.filter((i) => i)
|
.filter((i) => i)
|
||||||
.join('; ');
|
.join('; ');
|
||||||
if (subUserInfo) {
|
if (subUserInfo) {
|
||||||
res.set('subscription-userinfo', subUserInfo);
|
res.set(
|
||||||
|
'subscription-userinfo',
|
||||||
|
subUserInfo.replace(/\s*;\s*;\s*/g, ';'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (platform === 'JSON') {
|
if (platform === 'JSON') {
|
||||||
if (resultFormat === 'nezha') {
|
if (resultFormat === 'nezha') {
|
||||||
|
|||||||
@@ -146,7 +146,10 @@ async function getFile(req, res) {
|
|||||||
proxy || file.proxy,
|
proxy || file.proxy,
|
||||||
);
|
);
|
||||||
if (flowInfo) {
|
if (flowInfo) {
|
||||||
res.set('subscription-userinfo', flowInfo);
|
res.set(
|
||||||
|
'subscription-userinfo',
|
||||||
|
flowInfo.replace(/\s*;\s*;\s*/g, ';'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -540,6 +540,7 @@ async function syncArtifacts() {
|
|||||||
const files = {};
|
const files = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const valid = [];
|
||||||
const invalid = [];
|
const invalid = [];
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
const allCols = $.read(COLLECTIONS_KEY);
|
const allCols = $.read(COLLECTIONS_KEY);
|
||||||
@@ -614,19 +615,26 @@ async function syncArtifacts() {
|
|||||||
files[encodeURIComponent(artifact.name)] = {
|
files[encodeURIComponent(artifact.name)] = {
|
||||||
content: output,
|
content: output,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
valid.push(artifact.name);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$.error(
|
$.error(
|
||||||
`同步配置 ${artifact.name} 发生错误: ${e.message ?? e}`,
|
`生成同步配置 ${artifact.name} 发生错误: ${
|
||||||
|
e.message ?? e
|
||||||
|
}`,
|
||||||
);
|
);
|
||||||
invalid.push(artifact.name);
|
invalid.push(artifact.name);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (invalid.length > 0) {
|
$.info(`${valid.length} 个同步配置生成成功: ${valid.join(', ')}`);
|
||||||
|
$.info(`${invalid.length} 个同步配置生成失败: ${invalid.join(', ')}`);
|
||||||
|
|
||||||
|
if (valid.length === 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`同步配置 ${invalid.join(', ')} 发生错误 详情请查看日志`,
|
`同步配置 ${invalid.join(', ')} 生成失败 详情请查看日志`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +651,11 @@ async function syncArtifacts() {
|
|||||||
$.info(JSON.stringify(body, null, 2));
|
$.info(JSON.stringify(body, null, 2));
|
||||||
|
|
||||||
for (const artifact of allArtifacts) {
|
for (const artifact of allArtifacts) {
|
||||||
if (artifact.sync) {
|
if (
|
||||||
|
artifact.sync &&
|
||||||
|
artifact.source &&
|
||||||
|
valid.includes(artifact.name)
|
||||||
|
) {
|
||||||
artifact.updated = new Date().getTime();
|
artifact.updated = new Date().getTime();
|
||||||
// extract real url from gist
|
// extract real url from gist
|
||||||
let files = body.files;
|
let files = body.files;
|
||||||
@@ -671,9 +683,17 @@ async function syncArtifacts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$.write(allArtifacts, ARTIFACTS_KEY);
|
$.write(allArtifacts, ARTIFACTS_KEY);
|
||||||
$.info('全部订阅同步成功!');
|
$.info('上传配置成功');
|
||||||
|
|
||||||
|
if (invalid.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`同步配置成功 ${valid.length} 个, 失败 ${invalid.length} 个, 详情请查看日志`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$.info(`同步配置成功 ${valid.length} 个`);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$.error(`同步订阅失败,原因:${e.message ?? e}`);
|
$.error(`同步配置失败,原因:${e.message ?? e}`);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,7 +703,7 @@ async function syncAllArtifacts(_, res) {
|
|||||||
await syncArtifacts();
|
await syncArtifacts();
|
||||||
success(res);
|
success(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$.error(`同步订阅失败,原因:${e.message ?? e}`);
|
$.error(`同步配置失败,原因:${e.message ?? e}`);
|
||||||
failed(
|
failed(
|
||||||
res,
|
res,
|
||||||
new InternalServerError(
|
new InternalServerError(
|
||||||
|
|||||||
@@ -62,11 +62,26 @@ export function getPlatformFromHeaders(headers) {
|
|||||||
}
|
}
|
||||||
export function shouldIncludeUnsupportedProxy(platform, ua) {
|
export function shouldIncludeUnsupportedProxy(platform, ua) {
|
||||||
try {
|
try {
|
||||||
|
const target = getPlatformFromUserAgent({
|
||||||
|
UA: ua,
|
||||||
|
ua: ua.toLowerCase(),
|
||||||
|
});
|
||||||
|
if (!['Stash', 'Egern'].includes(target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const version = coerce(ua).version;
|
const version = coerce(ua).version;
|
||||||
if (platform === 'Stash' && gte(version, '2.8.0')) {
|
if (
|
||||||
|
platform === 'Stash' &&
|
||||||
|
target === 'Stash' &&
|
||||||
|
gte(version, '2.8.0')
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (platform === 'Egern' && gte(version, '1.29.0')) {
|
if (
|
||||||
|
platform === 'Egern' &&
|
||||||
|
target === 'Egern' &&
|
||||||
|
gte(version, '1.29.0')
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user