Skip to content

Commit

Permalink
feat: producers adjustments, VMess URI formats
Browse files Browse the repository at this point in the history
  • Loading branch information
xream committed Aug 24, 2023
1 parent afb9296 commit 3ffa6f7
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 31 deletions.
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sub-store",
"version": "2.14.25",
"version": "2.14.26",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js",
"scripts": {
Expand Down
11 changes: 7 additions & 4 deletions backend/src/core/proxy-utils/parsers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,7 @@ function URI_VMess() {
params[key] = value.split(',');
}
}
console.log(`content`, content);
console.log(`params`, params);

let [__, cipher, uuid, server, port] =

Check failure on line 234 in backend/src/core/proxy-utils/parsers/index.js

View workflow job for this annotation

GitHub Actions / build

'__' is assigned a value but never used
/(^[^:]+?):([^:]+?)@(.*):(\d+)$/.exec(content);

Expand Down Expand Up @@ -263,7 +262,10 @@ function URI_VMess() {
// handle obfs
if (params.net === 'ws' || params.obfs === 'websocket') {
proxy.network = 'ws';
} else if (params.net === 'tcp' || params.obfs === 'http') {
} else if (
['tcp', 'http'].includes(params.net) ||
params.obfs === 'http'
) {
proxy.network = 'http';
}
if (proxy.network) {
Expand Down Expand Up @@ -340,6 +342,7 @@ function Clash_All() {
'snell',
'trojan',
'tuic',
'vless',
].includes(proxy.type)
) {
throw new Error(
Expand All @@ -348,7 +351,7 @@ function Clash_All() {
}

// handle vmess sni
if (proxy.type === 'vmess') {
if (['vmess', 'vless'].includes(proxy.type)) {
proxy.sni = proxy.servername;
delete proxy.servername;
if (proxy.tls && !proxy.sni) {
Expand Down
2 changes: 2 additions & 0 deletions backend/src/core/proxy-utils/producers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Loon_Producer from './loon';
import URI_Producer from './uri';
import V2Ray_Producer from './v2ray';
import QX_Producer from './qx';
import ShadowRocket_Producer from './shadowrocket';

function JSON_Producer() {
const type = 'ALL';
Expand All @@ -21,4 +22,5 @@ export default {
V2Ray: V2Ray_Producer(),
JSON: JSON_Producer(),
Stash: Stash_Producer(),
ShadowRocket: ShadowRocket_Producer(),
};
3 changes: 3 additions & 0 deletions backend/src/core/proxy-utils/producers/loon.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ function vmess(proxy) {
}

function vless(proxy) {
if (proxy['reality-opts']) {
throw new Error(`reality is unsupported`);
}
const result = new Result(proxy);
result.append(
`${proxy.name}=vless,${proxy.server},${proxy.port},"${proxy.uuid}"`,
Expand Down
88 changes: 88 additions & 0 deletions backend/src/core/proxy-utils/producers/shadowrocket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { isPresent } from '@/core/proxy-utils/producers/utils';

export default function Stash_Producer() {
const type = 'ALL';
const produce = (proxies) => {
return (
'proxies:\n' +
proxies
.filter((proxy) => {
if (
proxy.type === 'snell' &&
String(proxy.version) === '4'
) {
return false;
}
return true;
})
.map((proxy) => {
if (proxy.type === 'vmess') {
// handle vmess aead
if (isPresent(proxy, 'aead')) {
if (proxy.aead) {
proxy.alterId = 0;
}
delete proxy.aead;
}
if (isPresent(proxy, 'sni')) {
proxy.servername = proxy.sni;
delete proxy.sni;
}
// https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/docs/config.yaml#L400
// https://stash.wiki/proxy-protocols/proxy-types#vmess
if (
isPresent(proxy, 'cipher') &&
![
'auto',
'aes-128-gcm',
'chacha20-poly1305',
'none',
].includes(proxy.cipher)
) {
proxy.cipher = 'auto';
}
} else if (proxy.type === 'tuic') {
if (isPresent(proxy, 'alpn')) {
proxy.alpn = Array.isArray(proxy.alpn)
? proxy.alpn
: [proxy.alpn];
} else {
proxy.alpn = ['h3'];
}
// https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/adapter/outbound/tuic.go#L197
if (
(!proxy.token || proxy.token.length === 0) &&
!isPresent(proxy, 'version')
) {
proxy.version = 5;
}
}

if (
['vmess', 'vless'].includes(proxy.type) &&
proxy.network === 'http'
) {
let httpPath = proxy['http-opts']?.path;
if (
isPresent(proxy, 'http-opts.path') &&
!Array.isArray(httpPath)
) {
proxy['http-opts'].path = [httpPath];
}
let httpHost = proxy['http-opts']?.headers?.Host;
if (
isPresent(proxy, 'http-opts.headers.Host') &&
!Array.isArray(httpHost)
) {
proxy['http-opts'].headers.Host = [httpHost];
}
}

delete proxy['tls-fingerprint'];
return ' - ' + JSON.stringify(proxy) + '\n';
})
.join('')
);
};
return { type, produce };
}
16 changes: 14 additions & 2 deletions backend/src/core/proxy-utils/producers/stash.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ export default function Stash_Producer() {
proxies
.filter((proxy) => {
if (
proxy.type === 'snell' &&
String(proxy.version) === '4'
![
'ss',
'ssr',
'vmess',
'socks',
'http',
'snell',
'trojan',
'tuic',
'vless',
].includes(proxy.type) ||
(proxy.type === 'snell' &&
String(proxy.version) === '4') ||
(proxy.type === 'vless' && proxy['reality-opts'])
) {
return false;
}
Expand Down
60 changes: 39 additions & 21 deletions backend/src/core/proxy-utils/producers/uri.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,55 +55,73 @@ export default function URI_Producer() {
break;
case 'vmess':
// V2RayN URI format
let type = '';
let net = proxy.network || 'tcp';
if (proxy.network === 'http') {
net = 'tcp';
type = 'http';
}
result = {
v: '2',
ps: proxy.name,
add: proxy.server,
port: proxy.port,
id: proxy.uuid,
type: '',
type,
aid: 0,
net: proxy.network || 'tcp',
net,
tls: proxy.tls ? 'tls' : '',
};
if (proxy.tls && proxy.sni) {
result.sni = proxy.sni;
}
// obfs
if (proxy.network === 'ws') {
result.path = proxy['ws-opts'].path || '/';
if (proxy['ws-opts'].headers.Host) {
result.host = proxy['ws-opts'].headers.Host;
if (proxy.network) {
let vmessTransportPath =
proxy[`${proxy.network}-opts`]?.path;
let vmessTransportHost =
proxy[`${proxy.network}-opts`]?.headers?.Host;
if (vmessTransportPath) {
result.path = Array.isArray(vmessTransportPath)
? vmessTransportPath[0]
: vmessTransportPath;
}
if (vmessTransportHost) {
result.host = Array.isArray(vmessTransportHost)
? vmessTransportHost[0]
: vmessTransportHost;
}
}
result = 'vmess://' + Base64.encode(JSON.stringify(result));
break;
case 'trojan':
let transport = '';
let trojanTransport = '';
if (proxy.network) {
transport = `&type=${proxy.network}`;
let transportPath = proxy[`${proxy.network}-opts`]?.path;
let transportHost =
trojanTransport = `&type=${proxy.network}`;
let trojanTransportPath =
proxy[`${proxy.network}-opts`]?.path;
let trojanTransportHost =
proxy[`${proxy.network}-opts`]?.headers?.Host;
if (transportPath) {
transport += `&path=${encodeURIComponent(
Array.isArray(transportPath)
? transportPath[0]
: transportPath,
if (trojanTransportPath) {
trojanTransport += `&path=${encodeURIComponent(
Array.isArray(trojanTransportPath)
? trojanTransportPath[0]
: trojanTransportPath,
)}`;
}
if (transportHost) {
transport += `&host=${encodeURIComponent(
Array.isArray(transportHost)
? transportHost[0]
: transportHost,
if (trojanTransportHost) {
trojanTransport += `&host=${encodeURIComponent(
Array.isArray(trojanTransportHost)
? trojanTransportHost[0]
: trojanTransportHost,
)}`;
}
}
result = `trojan://${proxy.password}@${proxy.server}:${
proxy.port
}?sni=${encodeURIComponent(proxy.sni || proxy.server)}${
proxy['skip-cert-verify'] ? '&allowInsecure=1' : ''
}${transport}#${encodeURIComponent(proxy.name)}`;
}${trojanTransport}#${encodeURIComponent(proxy.name)}`;
break;
}
return result;
Expand Down
3 changes: 0 additions & 3 deletions backend/src/restful/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ export default function register($app) {
async function produceArtifact({ type, name, platform }) {
platform = platform || 'JSON';

// produce Clash node format for ShadowRocket
if (platform === 'ShadowRocket') platform = 'Clash';

if (type === 'subscription') {
const allSubs = $.read(SUBS_KEY);
const sub = findByName(allSubs, name);
Expand Down

0 comments on commit 3ffa6f7

Please sign in to comment.