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>
|
</div>
|
||||||
|
|
||||||
<p align="center" color="#6a737d">
|
<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>
|
</p>
|
||||||
|
|
||||||
[](https://github.com/sub-store-org/Sub-Store/actions/workflows/main.yml)     
|
[](https://github.com/sub-store-org/Sub-Store/actions/workflows/main.yml)     
|
||||||
@ -49,6 +49,7 @@ Core functionalities:
|
|||||||
- [x] Surge
|
- [x] Surge
|
||||||
- [x] SurgeMac(Use mihomo to support protocols that are not supported by Surge itself)
|
- [x] SurgeMac(Use mihomo to support protocols that are not supported by Surge itself)
|
||||||
- [x] Loon
|
- [x] Loon
|
||||||
|
- [x] Egern
|
||||||
- [x] Shadowrocket
|
- [x] Shadowrocket
|
||||||
- [x] QX
|
- [x] QX
|
||||||
- [x] sing-box
|
- [x] sing-box
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.14.423",
|
"version": "2.14.425",
|
||||||
"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": {
|
||||||
|
@ -340,6 +340,10 @@ function URI_VMess() {
|
|||||||
} else if (params.net === 'h2' || proxy.network === 'h2') {
|
} else if (params.net === 'h2' || proxy.network === 'h2') {
|
||||||
proxy.network = 'h2';
|
proxy.network = 'h2';
|
||||||
}
|
}
|
||||||
|
// 暂不支持 tcp + host + path
|
||||||
|
// else if (params.net === 'tcp' || proxy.network === 'tcp') {
|
||||||
|
// proxy.network = 'tcp';
|
||||||
|
// }
|
||||||
if (proxy.network) {
|
if (proxy.network) {
|
||||||
let transportHost = params.host ?? params.obfsParam;
|
let transportHost = params.host ?? params.obfsParam;
|
||||||
try {
|
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 Shadowrocket_Producer from './shadowrocket';
|
||||||
import Surfboard_Producer from './surfboard';
|
import Surfboard_Producer from './surfboard';
|
||||||
import singbox_Producer from './sing-box';
|
import singbox_Producer from './sing-box';
|
||||||
|
import Egern_Producer from './egern';
|
||||||
|
|
||||||
function JSON_Producer() {
|
function JSON_Producer() {
|
||||||
const type = 'ALL';
|
const type = 'ALL';
|
||||||
@ -34,4 +35,5 @@ export default {
|
|||||||
ShadowRocket: Shadowrocket_Producer(),
|
ShadowRocket: Shadowrocket_Producer(),
|
||||||
Surfboard: Surfboard_Producer(),
|
Surfboard: Surfboard_Producer(),
|
||||||
'sing-box': singbox_Producer(),
|
'sing-box': singbox_Producer(),
|
||||||
|
Egern: Egern_Producer(),
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,8 @@ export function getUserAgentFromHeaders(headers) {
|
|||||||
export function getPlatformFromUserAgent({ ua, UA, accept }) {
|
export function getPlatformFromUserAgent({ ua, UA, accept }) {
|
||||||
if (UA.indexOf('Quantumult%20X') !== -1) {
|
if (UA.indexOf('Quantumult%20X') !== -1) {
|
||||||
return 'QX';
|
return 'QX';
|
||||||
|
} else if (ua.indexOf('egern') !== -1) {
|
||||||
|
return 'Egern';
|
||||||
} else if (UA.indexOf('Surfboard') !== -1) {
|
} else if (UA.indexOf('Surfboard') !== -1) {
|
||||||
return 'Surfboard';
|
return 'Surfboard';
|
||||||
} else if (UA.indexOf('Surge Mac') !== -1) {
|
} else if (UA.indexOf('Surge Mac') !== -1) {
|
||||||
@ -39,7 +41,7 @@ export function getPlatformFromUserAgent({ ua, UA, accept }) {
|
|||||||
return 'ClashMeta';
|
return 'ClashMeta';
|
||||||
} else if (ua.indexOf('clash') !== -1) {
|
} else if (ua.indexOf('clash') !== -1) {
|
||||||
return 'Clash';
|
return 'Clash';
|
||||||
} else if (ua.indexOf('v2ray') !== -1 || ua.indexOf('egern') !== -1) {
|
} else if (ua.indexOf('v2ray') !== -1) {
|
||||||
return 'V2Ray';
|
return 'V2Ray';
|
||||||
} else if (ua.indexOf('sing-box') !== -1) {
|
} else if (ua.indexOf('sing-box') !== -1) {
|
||||||
return 'sing-box';
|
return 'sing-box';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user