mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-06-04 11:13:59 +08:00
feat: 支持 Egern 输出
This commit is contained in:
parent
7d8132d7cd
commit
fe3da254f4
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<p align="center" color="#6a737d">
|
||||
Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.
|
||||
Advanced Subscription Manager for QX, Loon, Surge, Stash, Egern and Shadowrocket.
|
||||
</p>
|
||||
|
||||
[](https://github.com/sub-store-org/Sub-Store/actions/workflows/main.yml)     
|
||||
@ -49,6 +49,7 @@ Core functionalities:
|
||||
- [x] Surge
|
||||
- [x] SurgeMac(Use mihomo to support protocols that are not supported by Surge itself)
|
||||
- [x] Loon
|
||||
- [x] Egern
|
||||
- [x] Shadowrocket
|
||||
- [x] QX
|
||||
- [x] sing-box
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sub-store",
|
||||
"version": "2.14.423",
|
||||
"version": "2.14.425",
|
||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
|
@ -340,6 +340,10 @@ function URI_VMess() {
|
||||
} else if (params.net === 'h2' || proxy.network === 'h2') {
|
||||
proxy.network = 'h2';
|
||||
}
|
||||
// 暂不支持 tcp + host + path
|
||||
// else if (params.net === 'tcp' || proxy.network === 'tcp') {
|
||||
// proxy.network = 'tcp';
|
||||
// }
|
||||
if (proxy.network) {
|
||||
let transportHost = params.host ?? params.obfsParam;
|
||||
try {
|
||||
|
298
backend/src/core/proxy-utils/producers/egern.js
Normal file
298
backend/src/core/proxy-utils/producers/egern.js
Normal file
@ -0,0 +1,298 @@
|
||||
export default function Egern_Producer() {
|
||||
const type = 'ALL';
|
||||
const produce = (proxies, type, opts = {}) => {
|
||||
// https://egernapp.com/zh-CN/docs/configuration/proxies
|
||||
const list = proxies
|
||||
.filter((proxy) => {
|
||||
if (opts['include-unsupported-proxy']) return true;
|
||||
if (
|
||||
![
|
||||
'http',
|
||||
'socks5',
|
||||
'ss',
|
||||
'trojan',
|
||||
'hysteria2',
|
||||
'vless',
|
||||
'vmess',
|
||||
].includes(proxy.type) ||
|
||||
(proxy.type === 'ss' &&
|
||||
((proxy.plugin === 'obfs' &&
|
||||
!['http', 'tls'].includes(
|
||||
proxy['plugin-opts']?.mode,
|
||||
)) ||
|
||||
![
|
||||
'chacha20-ietf-poly1305',
|
||||
'chacha20-poly1305',
|
||||
'aes-256-gcm',
|
||||
'aes-128-gcm',
|
||||
'none',
|
||||
'tbale',
|
||||
'rc4',
|
||||
'rc4-md5',
|
||||
'aes-128-cfb',
|
||||
'aes-192-cfb',
|
||||
'aes-256-cfb',
|
||||
'aes-128-ctr',
|
||||
'aes-192-ctr',
|
||||
'aes-256-ctr',
|
||||
'bf-cfb',
|
||||
'camellia-128-cfb',
|
||||
'camellia-192-cfb',
|
||||
'camellia-256-cfb',
|
||||
'cast5-cfb',
|
||||
'des-cfb',
|
||||
'idea-cfb',
|
||||
'rc2-cfb',
|
||||
'seed-cfb',
|
||||
'salsa20',
|
||||
'chacha20',
|
||||
'chacha20-ietf',
|
||||
].includes(proxy.cipher))) ||
|
||||
(proxy.type === 'vmess' &&
|
||||
(![
|
||||
'auto',
|
||||
'aes-128-gcm',
|
||||
'chacha20-poly1305',
|
||||
'none',
|
||||
'zero',
|
||||
].includes(proxy.cipher) ||
|
||||
(!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||
proxy.network))) ||
|
||||
(proxy.type === 'trojan' &&
|
||||
!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||
proxy.network) ||
|
||||
(proxy.type === 'vless' &&
|
||||
(typeof proxy.flow !== 'undefined' ||
|
||||
proxy['reality-opts'] ||
|
||||
(!['http', 'ws', 'tcp'].includes(proxy.network) &&
|
||||
proxy.network)))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((proxy) => {
|
||||
if (proxy.type === 'http') {
|
||||
proxy = {
|
||||
type: 'http',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
username: proxy.username,
|
||||
password: proxy.password,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
next_hop: proxy.next_hop,
|
||||
};
|
||||
} else if (proxy.type === 'socks5') {
|
||||
proxy = {
|
||||
type: 'socks5',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
username: proxy.username,
|
||||
password: proxy.password,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
};
|
||||
} else if (proxy.type === 'ss') {
|
||||
proxy = {
|
||||
type: 'shadowsocks',
|
||||
name: proxy.name,
|
||||
method:
|
||||
proxy.cipher === 'chacha20-ietf-poly1305'
|
||||
? 'chacha20-poly1305'
|
||||
: proxy.cipher,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
password: proxy.password,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
};
|
||||
if (proxy.plugin === 'obfs') {
|
||||
proxy.obfs = proxy['plugin-opts'].mode;
|
||||
proxy.obfs_host = proxy['plugin-opts'].host;
|
||||
proxy.obfs_uri = proxy['plugin-opts'].path;
|
||||
}
|
||||
} else if (proxy.type === 'hysteria2') {
|
||||
proxy = {
|
||||
type: 'hysteria2',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
auth: proxy.password,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
sni: proxy.sni,
|
||||
skip_tls_verify: proxy['skip-cert-verify'],
|
||||
};
|
||||
if (proxy['obfs-password'] && proxy.obfs == 'salamander') {
|
||||
proxy.obfs = 'salamander';
|
||||
proxy.obfs_password = proxy['obfs-password'];
|
||||
}
|
||||
} else if (proxy.type === 'trojan') {
|
||||
if (proxy.network === 'ws') {
|
||||
proxy.websocket = {
|
||||
path: proxy['ws-opts']?.path,
|
||||
host: proxy['ws-opts']?.headers?.Host,
|
||||
};
|
||||
}
|
||||
proxy = {
|
||||
type: 'trojan',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
password: proxy.password,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
sni: proxy.sni,
|
||||
skip_tls_verify: proxy['skip-cert-verify'],
|
||||
websocket: proxy.websocket,
|
||||
};
|
||||
} else if (proxy.type === 'vmess') {
|
||||
if (proxy.network === 'ws') {
|
||||
proxy.transport = {
|
||||
[proxy.tls ? 'wss' : 'ws']: {
|
||||
path: proxy['ws-opts']?.path,
|
||||
headers: {
|
||||
Host: proxy['ws-opts']?.headers?.Host,
|
||||
},
|
||||
sni: proxy.tls ? proxy.sni : undefined,
|
||||
skip_tls_verify: proxy.tls
|
||||
? proxy['skip-cert-verify']
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
} else if (proxy.network === 'http') {
|
||||
proxy.transport = {
|
||||
http: {
|
||||
method: proxy['http-opts']?.method,
|
||||
path: proxy['http-opts']?.path,
|
||||
headers: {
|
||||
Host: Array.isArray(
|
||||
proxy['http-opts']?.headers?.Host,
|
||||
)
|
||||
? proxy['http-opts']?.headers?.Host[0]
|
||||
: proxy['http-opts']?.headers?.Host,
|
||||
},
|
||||
skip_tls_verify: proxy['skip-cert-verify'],
|
||||
},
|
||||
};
|
||||
} else if (proxy.network === 'tcp' || !proxy.network) {
|
||||
proxy.transport = {
|
||||
[proxy.tls ? 'tls' : 'tcp']: {
|
||||
sni: proxy.tls ? proxy.sni : undefined,
|
||||
skip_tls_verify: proxy.tls
|
||||
? proxy['skip-cert-verify']
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
proxy = {
|
||||
type: 'vmess',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
user_id: proxy.uuid,
|
||||
security: proxy.cipher,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
legacy: proxy.legacy,
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
transport: proxy.transport,
|
||||
// sni: proxy.sni,
|
||||
// skip_tls_verify: proxy['skip-cert-verify'],
|
||||
};
|
||||
} else if (proxy.type === 'vless') {
|
||||
if (proxy.network === 'ws') {
|
||||
proxy.transport = {
|
||||
[proxy.tls ? 'wss' : 'ws']: {
|
||||
path: proxy['ws-opts']?.path,
|
||||
headers: {
|
||||
Host: proxy['ws-opts']?.headers?.Host,
|
||||
},
|
||||
sni: proxy.tls ? proxy.sni : undefined,
|
||||
skip_tls_verify: proxy.tls
|
||||
? proxy['skip-cert-verify']
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
} else if (proxy.network === 'http') {
|
||||
proxy.transport = {
|
||||
http: {
|
||||
method: proxy['http-opts']?.method,
|
||||
path: proxy['http-opts']?.path,
|
||||
headers: {
|
||||
Host: Array.isArray(
|
||||
proxy['http-opts']?.headers?.Host,
|
||||
)
|
||||
? proxy['http-opts']?.headers?.Host[0]
|
||||
: proxy['http-opts']?.headers?.Host,
|
||||
},
|
||||
skip_tls_verify: proxy['skip-cert-verify'],
|
||||
},
|
||||
};
|
||||
} else if (proxy.network === 'tcp' || !proxy.network) {
|
||||
proxy.transport = {
|
||||
[proxy.tls ? 'tls' : 'tcp']: {
|
||||
sni: proxy.tls ? proxy.sni : undefined,
|
||||
skip_tls_verify: proxy.tls
|
||||
? proxy['skip-cert-verify']
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
proxy = {
|
||||
type: 'vless',
|
||||
name: proxy.name,
|
||||
server: proxy.server,
|
||||
port: proxy.port,
|
||||
user_id: proxy.uuid,
|
||||
security: proxy.cipher,
|
||||
tfo: proxy.tfo || proxy['fast-open'],
|
||||
legacy: proxy.legacy,
|
||||
udp_relay:
|
||||
proxy.udp || proxy.udp_relay || proxy.udp_relay,
|
||||
next_hop: proxy.next_hop,
|
||||
transport: proxy.transport,
|
||||
// sni: proxy.sni,
|
||||
// skip_tls_verify: proxy['skip-cert-verify'],
|
||||
};
|
||||
}
|
||||
|
||||
delete proxy.subName;
|
||||
delete proxy.collectionName;
|
||||
delete proxy.id;
|
||||
delete proxy.resolved;
|
||||
delete proxy['no-resolve'];
|
||||
if (type !== 'internal') {
|
||||
for (const key in proxy) {
|
||||
if (proxy[key] == null || /^_/i.test(key)) {
|
||||
delete proxy[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
[proxy.type]: {
|
||||
...proxy,
|
||||
type: undefined,
|
||||
},
|
||||
};
|
||||
});
|
||||
return type === 'internal'
|
||||
? list
|
||||
: 'proxies:\n' +
|
||||
list
|
||||
.map((proxy) => ' - ' + JSON.stringify(proxy) + '\n')
|
||||
.join('');
|
||||
};
|
||||
return { type, produce };
|
||||
}
|
@ -10,6 +10,7 @@ import QX_Producer from './qx';
|
||||
import Shadowrocket_Producer from './shadowrocket';
|
||||
import Surfboard_Producer from './surfboard';
|
||||
import singbox_Producer from './sing-box';
|
||||
import Egern_Producer from './egern';
|
||||
|
||||
function JSON_Producer() {
|
||||
const type = 'ALL';
|
||||
@ -34,4 +35,5 @@ export default {
|
||||
ShadowRocket: Shadowrocket_Producer(),
|
||||
Surfboard: Surfboard_Producer(),
|
||||
'sing-box': singbox_Producer(),
|
||||
Egern: Egern_Producer(),
|
||||
};
|
||||
|
@ -18,6 +18,8 @@ export function getUserAgentFromHeaders(headers) {
|
||||
export function getPlatformFromUserAgent({ ua, UA, accept }) {
|
||||
if (UA.indexOf('Quantumult%20X') !== -1) {
|
||||
return 'QX';
|
||||
} else if (ua.indexOf('egern') !== -1) {
|
||||
return 'Egern';
|
||||
} else if (UA.indexOf('Surfboard') !== -1) {
|
||||
return 'Surfboard';
|
||||
} else if (UA.indexOf('Surge Mac') !== -1) {
|
||||
@ -39,7 +41,7 @@ export function getPlatformFromUserAgent({ ua, UA, accept }) {
|
||||
return 'ClashMeta';
|
||||
} else if (ua.indexOf('clash') !== -1) {
|
||||
return 'Clash';
|
||||
} else if (ua.indexOf('v2ray') !== -1 || ua.indexOf('egern') !== -1) {
|
||||
} else if (ua.indexOf('v2ray') !== -1) {
|
||||
return 'V2Ray';
|
||||
} else if (ua.indexOf('sing-box') !== -1) {
|
||||
return 'sing-box';
|
||||
|
Loading…
x
Reference in New Issue
Block a user