mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-16 15:20:39 +08:00
feat: add GUI support for AnyTLS/Mieru/Sudoku and AnyTLS URI parsing
This commit is contained in:
parent
c80c659180
commit
772b87e733
@ -18,6 +18,7 @@
|
|||||||
- 支持收起导航栏(导航栏右键菜单 / 界面设置)
|
- 支持收起导航栏(导航栏右键菜单 / 界面设置)
|
||||||
- 允许将出站模式显示在托盘一级菜单
|
- 允许将出站模式显示在托盘一级菜单
|
||||||
- 允许禁用在托盘中显示代理组
|
- 允许禁用在托盘中显示代理组
|
||||||
|
- 支持在「编辑节点」中直接导入 AnyTLS URI 配置
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@ -31,5 +32,6 @@
|
|||||||
- 改进托盘和窗口操作频率限制实现
|
- 改进托盘和窗口操作频率限制实现
|
||||||
- 使用「编辑节点」添加节点时,自动将节点添加到第一个 `select` 类型的代理组的第一位
|
- 使用「编辑节点」添加节点时,自动将节点添加到第一个 `select` 类型的代理组的第一位
|
||||||
- 隐藏侧边导航栏和悬浮跳转导航的滚动条
|
- 隐藏侧边导航栏和悬浮跳转导航的滚动条
|
||||||
|
- 完善对 AnyTLS / Mieru / Sudoku 的 GUI 支持
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -130,7 +130,7 @@ importers:
|
|||||||
version: 2.3.8(react@19.2.3)
|
version: 2.3.8(react@19.2.3)
|
||||||
tauri-plugin-mihomo-api:
|
tauri-plugin-mihomo-api:
|
||||||
specifier: github:clash-verge-rev/tauri-plugin-mihomo#main
|
specifier: github:clash-verge-rev/tauri-plugin-mihomo#main
|
||||||
version: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/153f16f7b3f979aa130a2d3d7c39a52a39987288
|
version: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/a0e5095c1516229e8816096ae7017f950e6200dd
|
||||||
types-pac:
|
types-pac:
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
@ -3876,8 +3876,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==}
|
resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/153f16f7b3f979aa130a2d3d7c39a52a39987288:
|
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/a0e5095c1516229e8816096ae7017f950e6200dd:
|
||||||
resolution: {tarball: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/153f16f7b3f979aa130a2d3d7c39a52a39987288}
|
resolution: {tarball: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/a0e5095c1516229e8816096ae7017f950e6200dd}
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
|
|
||||||
terser@5.44.1:
|
terser@5.44.1:
|
||||||
@ -8398,7 +8398,7 @@ snapshots:
|
|||||||
minizlib: 3.1.0
|
minizlib: 3.1.0
|
||||||
yallist: 5.0.0
|
yallist: 5.0.0
|
||||||
|
|
||||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/153f16f7b3f979aa130a2d3d7c39a52a39987288:
|
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/a0e5095c1516229e8816096ae7017f950e6200dd:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.9.1
|
'@tauri-apps/api': 2.9.1
|
||||||
|
|
||||||
|
|||||||
@ -828,6 +828,9 @@ export const GroupsEditorViewer = (props: Props) => {
|
|||||||
"Hysteria2",
|
"Hysteria2",
|
||||||
"WireGuard",
|
"WireGuard",
|
||||||
"Tuic",
|
"Tuic",
|
||||||
|
"Mieru",
|
||||||
|
"AnyTLS",
|
||||||
|
"Sudoku",
|
||||||
"Relay",
|
"Relay",
|
||||||
"Selector",
|
"Selector",
|
||||||
"Fallback",
|
"Fallback",
|
||||||
|
|||||||
75
src/types/global.d.ts
vendored
75
src/types/global.d.ts
vendored
@ -429,6 +429,16 @@ type CipherType =
|
|||||||
| "aez-384"
|
| "aez-384"
|
||||||
| "deoxys-ii-256-128"
|
| "deoxys-ii-256-128"
|
||||||
| "rc4-md5";
|
| "rc4-md5";
|
||||||
|
type MieruTransport = "TCP" | "UDP";
|
||||||
|
type MieruMultiplexing =
|
||||||
|
| "MULTIPLEXING_OFF"
|
||||||
|
| "MULTIPLEXING_LOW"
|
||||||
|
| "MULTIPLEXING_MIDDLE"
|
||||||
|
| "MULTIPLEXING_HIGH";
|
||||||
|
type SudokuAeadMethod = "chacha20-poly1305" | "aes-128-gcm" | "none";
|
||||||
|
type SudokuTableType = "prefer_ascii" | "prefer_entropy";
|
||||||
|
type SudokuHttpMaskMode = "legacy" | "stream" | "poll" | "auto";
|
||||||
|
type SudokuHttpMaskStrategy = "random" | "post" | "websocket";
|
||||||
// base
|
// base
|
||||||
interface IProxyBaseConfig {
|
interface IProxyBaseConfig {
|
||||||
tfo?: boolean;
|
tfo?: boolean;
|
||||||
@ -513,6 +523,29 @@ interface IProxyTrojanConfig extends IProxyBaseConfig {
|
|||||||
};
|
};
|
||||||
"client-fingerprint"?: ClientFingerprint;
|
"client-fingerprint"?: ClientFingerprint;
|
||||||
}
|
}
|
||||||
|
// anytls
|
||||||
|
interface IProxyAnyTLSConfig extends IProxyBaseConfig {
|
||||||
|
name: string;
|
||||||
|
type: "anytls";
|
||||||
|
server?: string;
|
||||||
|
port?: number;
|
||||||
|
password?: string;
|
||||||
|
alpn?: string[];
|
||||||
|
sni?: string;
|
||||||
|
"client-fingerprint"?: ClientFingerprint;
|
||||||
|
"skip-cert-verify"?: boolean;
|
||||||
|
fingerprint?: string;
|
||||||
|
certificate?: string;
|
||||||
|
"private-key"?: string;
|
||||||
|
"ech-opts"?: {
|
||||||
|
enable?: boolean;
|
||||||
|
config?: string;
|
||||||
|
};
|
||||||
|
udp?: boolean;
|
||||||
|
"idle-session-check-interval"?: number;
|
||||||
|
"idle-session-timeout"?: number;
|
||||||
|
"min-idle-session"?: number;
|
||||||
|
}
|
||||||
// tuic
|
// tuic
|
||||||
interface IProxyTuicConfig extends IProxyBaseConfig {
|
interface IProxyTuicConfig extends IProxyBaseConfig {
|
||||||
name: string;
|
name: string;
|
||||||
@ -546,6 +579,20 @@ interface IProxyTuicConfig extends IProxyBaseConfig {
|
|||||||
"udp-over-stream"?: boolean;
|
"udp-over-stream"?: boolean;
|
||||||
"udp-over-stream-version"?: number;
|
"udp-over-stream-version"?: number;
|
||||||
}
|
}
|
||||||
|
// mieru
|
||||||
|
interface IProxyMieruConfig extends IProxyBaseConfig {
|
||||||
|
name: string;
|
||||||
|
type: "mieru";
|
||||||
|
server?: string;
|
||||||
|
port?: number;
|
||||||
|
"port-range"?: string;
|
||||||
|
transport?: MieruTransport;
|
||||||
|
udp?: boolean;
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
multiplexing?: MieruMultiplexing;
|
||||||
|
"handshake-mode"?: string;
|
||||||
|
}
|
||||||
// vless
|
// vless
|
||||||
interface IProxyVlessConfig extends IProxyBaseConfig {
|
interface IProxyVlessConfig extends IProxyBaseConfig {
|
||||||
name: string;
|
name: string;
|
||||||
@ -714,6 +761,26 @@ interface IProxyShadowsocksConfig extends IProxyBaseConfig {
|
|||||||
"client-fingerprint"?: ClientFingerprint;
|
"client-fingerprint"?: ClientFingerprint;
|
||||||
smux?: boolean;
|
smux?: boolean;
|
||||||
}
|
}
|
||||||
|
// sudoku
|
||||||
|
interface IProxySudokuConfig extends IProxyBaseConfig {
|
||||||
|
name: string;
|
||||||
|
type: "sudoku";
|
||||||
|
server?: string;
|
||||||
|
port?: number;
|
||||||
|
key?: string;
|
||||||
|
"aead-method"?: SudokuAeadMethod;
|
||||||
|
"padding-min"?: number;
|
||||||
|
"padding-max"?: number;
|
||||||
|
"table-type"?: SudokuTableType;
|
||||||
|
"enable-pure-downlink"?: boolean;
|
||||||
|
"http-mask"?: boolean;
|
||||||
|
"http-mask-mode"?: SudokuHttpMaskMode;
|
||||||
|
"http-mask-tls"?: boolean;
|
||||||
|
"http-mask-host"?: string;
|
||||||
|
"http-mask-strategy"?: SudokuHttpMaskStrategy;
|
||||||
|
"custom-table"?: string;
|
||||||
|
"custom-tables"?: string[];
|
||||||
|
}
|
||||||
// shadowsocksR
|
// shadowsocksR
|
||||||
interface IProxyshadowsocksRConfig extends IProxyBaseConfig {
|
interface IProxyshadowsocksRConfig extends IProxyBaseConfig {
|
||||||
name: string;
|
name: string;
|
||||||
@ -765,13 +832,16 @@ interface IProxyConfig
|
|||||||
IProxySocks5Config,
|
IProxySocks5Config,
|
||||||
IProxySshConfig,
|
IProxySshConfig,
|
||||||
IProxyTrojanConfig,
|
IProxyTrojanConfig,
|
||||||
|
IProxyAnyTLSConfig,
|
||||||
IProxyTuicConfig,
|
IProxyTuicConfig,
|
||||||
|
IProxyMieruConfig,
|
||||||
IProxyVlessConfig,
|
IProxyVlessConfig,
|
||||||
IProxyVmessConfig,
|
IProxyVmessConfig,
|
||||||
IProxyWireguardConfig,
|
IProxyWireguardConfig,
|
||||||
IProxyHysteriaConfig,
|
IProxyHysteriaConfig,
|
||||||
IProxyHysteria2Config,
|
IProxyHysteria2Config,
|
||||||
IProxyShadowsocksConfig,
|
IProxyShadowsocksConfig,
|
||||||
|
IProxySudokuConfig,
|
||||||
IProxyshadowsocksRConfig,
|
IProxyshadowsocksRConfig,
|
||||||
IProxySmuxConfig,
|
IProxySmuxConfig,
|
||||||
IProxySnellConfig {
|
IProxySnellConfig {
|
||||||
@ -783,6 +853,7 @@ interface IProxyConfig
|
|||||||
| "snell"
|
| "snell"
|
||||||
| "http"
|
| "http"
|
||||||
| "trojan"
|
| "trojan"
|
||||||
|
| "anytls"
|
||||||
| "hysteria"
|
| "hysteria"
|
||||||
| "hysteria2"
|
| "hysteria2"
|
||||||
| "tuic"
|
| "tuic"
|
||||||
@ -790,7 +861,9 @@ interface IProxyConfig
|
|||||||
| "ssh"
|
| "ssh"
|
||||||
| "socks5"
|
| "socks5"
|
||||||
| "vmess"
|
| "vmess"
|
||||||
| "vless";
|
| "vless"
|
||||||
|
| "mieru"
|
||||||
|
| "sudoku";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IVergeConfig {
|
interface IVergeConfig {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const URI_PARSERS: Record<string, UriParser> = {
|
|||||||
vmess: URI_VMESS,
|
vmess: URI_VMESS,
|
||||||
vless: URI_VLESS,
|
vless: URI_VLESS,
|
||||||
trojan: URI_Trojan,
|
trojan: URI_Trojan,
|
||||||
|
anytls: URI_AnyTLS,
|
||||||
hysteria2: URI_Hysteria2,
|
hysteria2: URI_Hysteria2,
|
||||||
hy2: URI_Hysteria2,
|
hy2: URI_Hysteria2,
|
||||||
hysteria: URI_Hysteria,
|
hysteria: URI_Hysteria,
|
||||||
@ -1071,6 +1072,89 @@ function URI_Trojan(line: string): IProxyTrojanConfig {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function URI_AnyTLS(line: string): IProxyAnyTLSConfig {
|
||||||
|
const afterScheme = stripUriScheme(line, "anytls", "Invalid anytls uri");
|
||||||
|
if (!afterScheme) {
|
||||||
|
throw new Error("Invalid anytls uri");
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
auth: authRaw,
|
||||||
|
host: server,
|
||||||
|
port,
|
||||||
|
query: addons,
|
||||||
|
fragment: nameRaw,
|
||||||
|
} = parseUrlLike(afterScheme, {
|
||||||
|
errorMessage: "Invalid anytls uri",
|
||||||
|
});
|
||||||
|
if (!server) {
|
||||||
|
throw new Error("Invalid anytls uri");
|
||||||
|
}
|
||||||
|
const portNum = parsePortOrDefault(port, 443);
|
||||||
|
const auth = safeDecodeURIComponent(authRaw) ?? authRaw;
|
||||||
|
const decodedName = decodeAndTrim(nameRaw);
|
||||||
|
const name = decodedName ?? `AnyTLS ${server}:${portNum}`;
|
||||||
|
const proxy: IProxyAnyTLSConfig = {
|
||||||
|
type: "anytls",
|
||||||
|
name,
|
||||||
|
server,
|
||||||
|
port: portNum,
|
||||||
|
udp: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auth) {
|
||||||
|
const [username, password] = splitOnce(auth, ":");
|
||||||
|
proxy.password = password ?? username;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = parseQueryStringNormalized(addons);
|
||||||
|
if (params.sni) {
|
||||||
|
proxy.sni = params.sni;
|
||||||
|
}
|
||||||
|
if (params.alpn) {
|
||||||
|
const alpn = params.alpn
|
||||||
|
.split(",")
|
||||||
|
.map((item) => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
if (alpn.length > 0) {
|
||||||
|
proxy.alpn = alpn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fingerprint = params.fingerprint ?? params.hpkp;
|
||||||
|
if (fingerprint) {
|
||||||
|
proxy.fingerprint = fingerprint;
|
||||||
|
}
|
||||||
|
const clientFingerprint = params["client-fingerprint"] ?? params.fp;
|
||||||
|
if (clientFingerprint) {
|
||||||
|
proxy["client-fingerprint"] = clientFingerprint as ClientFingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(params, "skip-cert-verify")) {
|
||||||
|
proxy["skip-cert-verify"] = parseBoolOrPresence(params["skip-cert-verify"]);
|
||||||
|
} else if (Object.prototype.hasOwnProperty.call(params, "insecure")) {
|
||||||
|
proxy["skip-cert-verify"] = parseBoolOrPresence(params.insecure);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(params, "udp")) {
|
||||||
|
proxy.udp = parseBoolOrPresence(params.udp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const idleCheck = parseInteger(params["idle-session-check-interval"]);
|
||||||
|
if (idleCheck !== undefined) {
|
||||||
|
proxy["idle-session-check-interval"] = idleCheck;
|
||||||
|
}
|
||||||
|
const idleTimeout = parseInteger(params["idle-session-timeout"]);
|
||||||
|
if (idleTimeout !== undefined) {
|
||||||
|
proxy["idle-session-timeout"] = idleTimeout;
|
||||||
|
}
|
||||||
|
const minIdle = parseInteger(params["min-idle-session"]);
|
||||||
|
if (minIdle !== undefined) {
|
||||||
|
proxy["min-idle-session"] = minIdle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
function URI_Hysteria2(line: string): IProxyHysteria2Config {
|
function URI_Hysteria2(line: string): IProxyHysteria2Config {
|
||||||
const afterScheme = stripUriScheme(
|
const afterScheme = stripUriScheme(
|
||||||
line,
|
line,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user