Reworked QX producer

This commit is contained in:
Peng-YM 2022-06-16 18:35:20 +08:00
parent 1e22243808
commit 4b73a1494b
12 changed files with 298 additions and 122 deletions

File diff suppressed because one or more lines are too long

View File

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

View File

@ -352,6 +352,15 @@ function QX_Http() {
return { name, test, parse };
}
function QX_Socks5() {
const name = 'QX Socks5 Parser';
const test = (line) => {
return /^socks5\s*=/.test(line.split(',')[0].trim());
};
const parse = (line) => getQXParser().parse(line);
return { name, test, parse };
}
function Loon_SS() {
const name = 'Loon SS Parser';
const test = (line) => {
@ -481,4 +490,5 @@ export default [
QX_VMess(),
QX_Trojan(),
QX_Http(),
QX_Socks5(),
];

View File

@ -56,6 +56,7 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_ss/obfs_ho
}
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)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleTransport();
}
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {

View File

@ -54,6 +54,7 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_ss/obfs_ho
}
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)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleTransport();
}
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {

View File

@ -29,8 +29,7 @@ const grammars = String.raw`
$set(proxy, "ws-opts.path", obfs.path);
$set(proxy, "ws-opts.headers.Host", obfs.host);
} else if (obfs.type === "over-tls") {
proxy.tls = true;
proxy.sni = proxy.sni || proxy.server;
throw new Error("over-tls is not supported");
} else if (obfs.type === "http") {
proxy.network = "http";
$set(proxy, "http-opts.path", obfs.path);
@ -83,6 +82,7 @@ shadowsocks = "shadowsocks" equals address
vmess = "vmess" equals address
(uuid/method/over_tls/tls_host/tls_verification/tag/obfs/obfs_host/obfs_uri/udp_relay/udp_over_tcp/fast_open/aead/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleObfs();
}
@ -145,9 +145,7 @@ fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
tls_host = comma "tls-host" equals sni:domain { proxy.sni = sni; }
tls_verification = comma "tls-verification" equals flag:bool {
if (!flag) {
proxy["skip-cert-verify"] = true;
}
proxy["skip-cert-verify"] = !flag;
}
obfs_ss = comma "obfs" equals type:("http"/"tls"/"wss"/"ws") { obfs.type = type; return type; }

View File

@ -27,8 +27,7 @@
$set(proxy, "ws-opts.path", obfs.path);
$set(proxy, "ws-opts.headers.Host", obfs.host);
} else if (obfs.type === "over-tls") {
proxy.tls = true;
proxy.sni = proxy.sni || proxy.server;
throw new Error("over-tls is not supported");
} else if (obfs.type === "http") {
proxy.network = "http";
$set(proxy, "http-opts.path", obfs.path);
@ -81,6 +80,7 @@ shadowsocks = "shadowsocks" equals address
vmess = "vmess" equals address
(uuid/method/over_tls/tls_host/tls_verification/tag/obfs/obfs_host/obfs_uri/udp_relay/udp_over_tcp/fast_open/aead/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleObfs();
}
@ -143,9 +143,7 @@ fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
tls_host = comma "tls-host" equals sni:domain { proxy.sni = sni; }
tls_verification = comma "tls-verification" equals flag:bool {
if (!flag) {
proxy["skip-cert-verify"] = true;
}
proxy["skip-cert-verify"] = !flag;
}
obfs_ss = comma "obfs" equals type:("http"/"tls"/"wss"/"ws") { obfs.type = type; return type; }

View File

@ -45,6 +45,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/
}
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/tls/sni/tls_verification/fast_open/udp_relay/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleWebsocket();
}
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_verification/fast_open/udp_relay/others)* {

View File

@ -43,6 +43,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/
}
vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/tls/sni/tls_verification/fast_open/udp_relay/others)* {
proxy.type = "vmess";
proxy.cipher = proxy.cipher || "none";
handleWebsocket();
}
trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_verification/fast_open/udp_relay/others)* {

View File

@ -1,115 +1,21 @@
/* eslint-disable no-case-declarations */
import { Result } from './utils';
const targetPlatform = 'QX';
export default function QX_Producer() {
const targetPlatform = 'QX';
const produce = (proxy) => {
let obfs_opts;
let tls_opts;
switch (proxy.type) {
case 'ss':
obfs_opts = '';
if (proxy.plugin === 'obfs') {
const { host, mode } = proxy['plugin-opts'];
obfs_opts = `,obfs=${mode}${
host ? ',obfs-host=' + host : ''
}`;
}
if (proxy.plugin === 'v2ray-plugin') {
const { tls, host, path } = proxy['plugin-opts'];
obfs_opts = `,obfs=${tls ? 'wss' : 'ws'}${
host ? ',obfs-host=' + host : ''
}${path ? ',obfs-uri=' + path : ''}`;
}
return `shadowsocks=${proxy.server}:${proxy.port},method=${
proxy.cipher
},password=${proxy.password}${obfs_opts}${
proxy.tfo ? ',fast-open=true' : ',fast-open=false'
}${proxy.udp ? ',udp-relay=true' : ',udp-relay=false'},tag=${
proxy.name
}`;
return shadowsocks(proxy);
case 'ssr':
return `shadowsocks=${proxy.server}:${proxy.port},method=${
proxy.cipher
},password=${proxy.password},ssr-protocol=${proxy.protocol}${
proxy['protocol-param']
? ',ssr-protocol-param=' + proxy['protocol-param']
: ''
}${proxy.obfs ? ',obfs=' + proxy.obfs : ''}${
proxy['obfs-param']
? ',obfs-host=' + proxy['obfs-param']
: ''
},fast-open=${proxy.tfo || false}${
proxy.udp ? ',udp-relay=true' : ',udp-relay=false'
},tag=${proxy.name}`;
case 'vmess':
obfs_opts = '';
if (proxy.network === 'ws') {
// websocket
if (proxy.tls) {
// ws-tls
obfs_opts = `,obfs=wss${
proxy.sni ? ',obfs-host=' + proxy.sni : ''
}${
proxy['ws-opts'].path
? ',obfs-uri=' + proxy['ws-opts'].path
: ''
},tls-verification=${
proxy['skip-cert-verify'] ? 'false' : 'true'
}`;
} else {
// ws
obfs_opts = `,obfs=ws${
proxy['ws-opts'].headers.Host
? ',obfs-host=' + proxy['ws-opts'].headers.Host
: ''
}${
proxy['ws-opts'].path
? ',obfs-uri=' + proxy['ws-opts'].path
: ''
}`;
}
} else {
// tcp
if (proxy.tls) {
obfs_opts = `,obfs=over-tls${
proxy.sni ? ',obfs-host=' + proxy.sni : ''
},tls-verification=${
proxy['skip-cert-verify'] ? 'false' : 'true'
}`;
}
}
let result = `vmess=${proxy.server}:${proxy.port},method=${
proxy.cipher === 'auto' ? 'none' : proxy.cipher
},password=${proxy.uuid}${obfs_opts},fast-open=${
proxy.tfo || false
}${proxy.udp ? ',udp-relay=true' : ',udp-relay=false'}`;
if (proxy.alterId === 0) proxy['vmess-aead'] = true;
if (typeof proxy['vmess-aead'] !== 'undefined') {
result += `,aead=${proxy['vmess-aead']}`;
}
result += `,tag=${proxy.name}`;
return result;
return shadowsocksr(proxy);
case 'trojan':
return `trojan=${proxy.server}:${proxy.port},password=${
proxy.password
}${
proxy.sni ? ',tls-host=' + proxy.sni : ''
},over-tls=true,tls-verification=${
proxy['skip-cert-verify'] ? 'false' : 'true'
},fast-open=${proxy.tfo || false}${
proxy.udp ? ',udp-relay=true' : ',udp-relay=false'
},tag=${proxy.name}`;
return trojan(proxy);
case 'vmess':
return vmess(proxy);
case 'http':
tls_opts = '';
if (proxy.tls) {
tls_opts = `,over-tls=true,tls-verification=${
proxy['skip-cert-verify'] ? 'false' : 'true'
}${proxy.sni ? ',tls-host=' + proxy.sni : ''}`;
}
return `http=${proxy.server}:${proxy.port},username=${
proxy.username
},password=${proxy.password}${tls_opts},fast-open=${
proxy.tfo || false
},tag=${proxy.name}`;
return http(proxy);
case 'socks5':
return socks5(proxy);
}
throw new Error(
`Platform ${targetPlatform} does not support proxy type: ${proxy.type}`,
@ -117,3 +23,241 @@ export default function QX_Producer() {
};
return { produce };
}
function shadowsocks(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`shadowsocks=${proxy.server}:${proxy.port}`);
append(`,method=${proxy.cipher}`);
append(`,password=${proxy.password}`);
// obfs
if (proxy.plugin) {
if (proxy.plugin === 'obfs') {
const opts = proxy['plugin-opts'];
append(`,obfs=${opts.mode}`);
} else if (
proxy.plugin === 'v2ray-plugin' &&
proxy['plugin-opts'].mode === 'websocket'
) {
const opts = proxy['plugin-opts'];
if (opts.tls) append(`,obfs=wss`);
else append(`,obfs=ws`);
}
appendIfPresent(
`,obfs-host=${proxy['plugin-opts'].host}`,
'plugin-opts.host',
);
appendIfPresent(
`,obfs-uri=${proxy['plugin-opts'].path}`,
'plugin-opts.path',
);
}
// tls verification
appendIfPresent(
`,tls-verification=${!proxy['skip-cert-verify']}`,
'skip-cert-verify',
);
appendIfPresent(`,tls-host=${proxy.sni}`, 'sni');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}
function shadowsocksr(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`shadowsocksr=${proxy.server}:${proxy.port}`);
append(`,method=${proxy.cipher}`);
append(`,password=${proxy.password}`);
// ssr protocol
append(`,ssr-protocol=${proxy.protocol}`);
appendIfPresent(
`,ssr-proctol-param=${proxy['proctol-param']}`,
'proctol-param',
);
// obfs
appendIfPresent(`,obfs=${proxy.obfs}`, 'obfs');
appendIfPresent(`,obfs-host=${proxy['obfs-param']}`, 'obfs-param');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}
function trojan(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`trojan=${proxy.server}:${proxy.port}`);
append(`,password=${proxy.password}`);
// obfs ws
if (proxy.network === 'ws') {
if (proxy.tls) append(`,obfs=wss`);
else append(`,obfs=ws`);
appendIfPresent(`,obfs-uri=${proxy['ws-opts'].path}`, 'ws-opts.path');
appendIfPresent(
`,obfs-host=${proxy['ws-opts'].headers.Host}`,
'ws-opts.headers.Host',
);
}
// tls
appendIfPresent(`,over-tls=${proxy.tls}`, 'tls');
// tls verification
appendIfPresent(
`,tls-verification=${!proxy['skip-cert-verify']}`,
'skip-cert-verify',
);
appendIfPresent(`,tls-host=${proxy.sni}`, 'sni');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}
function vmess(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`vmess=${proxy.server}:${proxy.port}`);
append(`,method=${proxy.cipher}`);
append(`,password=${proxy.uuid}`);
// obfs
if (proxy.network === 'ws') {
if (proxy.tls) append(`,obfs=wss`);
else append(`,obfs=ws`);
appendIfPresent(`,obfs-uri=${proxy['ws-opts'].path}`, 'ws-opts.path');
appendIfPresent(
`,obfs-host=${proxy['ws-opts'].headers.Host}`,
'ws-opts.headers.Host',
);
} else if (proxy.network === 'http') {
append(`,obfs=http`);
appendIfPresent(
`,obfs-uri=${proxy['http-opts'].path}`,
'http-opts.path',
);
appendIfPresent(
`,obfs-host=${proxy['http-opts'].headers.Host}`,
'http-opts.headers.Host',
);
}
// tls verification
appendIfPresent(
`,tls-verification=${!proxy['skip-cert-verify']}`,
'skip-cert-verify',
);
appendIfPresent(`,tls-host=${proxy.sni}`, 'sni');
// AEAD
appendIfPresent(`,aead=${proxy.alterId === 0}`, 'alterId');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}
function http(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`http=${proxy.server}:${proxy.port}`);
appendIfPresent(`,username=${proxy.username}`, 'username');
appendIfPresent(`,password=${proxy.password}`, 'password');
// tls
appendIfPresent(`,over-tls=${proxy.tls}`, 'tls');
// tls verification
appendIfPresent(
`,tls-verification=${!proxy['skip-cert-verify']}`,
'skip-cert-verify',
);
appendIfPresent(`,tls-host=${proxy.sni}`, 'sni');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}
function socks5(proxy) {
const result = new Result(proxy);
const append = result.append.bind(result);
const appendIfPresent = result.appendIfPresent.bind(result);
append(`socks5=${proxy.server}:${proxy.port}`);
appendIfPresent(`,username=${proxy.username}`, 'username');
appendIfPresent(`,password=${proxy.password}`, 'password');
// tls
appendIfPresent(`,over-tls=${proxy.tls}`, 'tls');
// tls verification
appendIfPresent(
`,tls-verification=${!proxy['skip-cert-verify']}`,
'skip-cert-verify',
);
appendIfPresent(`,tls-host=${proxy.sni}`, 'sni');
// tfo
appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
// udp
appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// tag
append(`,tag=${proxy.name}`);
return result.toString();
}

View File

@ -0,0 +1,22 @@
import _ from 'lodash';
export class Result {
constructor(proxy) {
this.proxy = proxy;
this.output = [];
}
append(data) {
this.output.push(data);
}
appendIfPresent(data, attr) {
if (typeof _.get(this.proxy, attr) !== 'undefined') {
this.append(data);
}
}
toString() {
return this.output.join('');
}
}

File diff suppressed because one or more lines are too long