From 1606adc0abf4a74e19c5cc0f1fce056581d8d90e Mon Sep 17 00:00:00 2001 From: MystiPanda Date: Tue, 16 Jan 2024 15:11:53 +0800 Subject: [PATCH] feat: Support both registry and api for windows sysproxy --- src-tauri/Cargo.lock | 54 ++++++++++++-- src-tauri/Cargo.toml | 2 +- src-tauri/src/config/verge.rs | 5 ++ src-tauri/src/core/sysopt.rs | 72 ++++++++++++++++--- .../setting/mods/sysproxy-viewer.tsx | 33 ++++++++- src/locales/en.json | 5 +- src/locales/ru.json | 5 +- src/locales/zh.json | 5 +- src/services/types.d.ts | 1 + 9 files changed, 164 insertions(+), 18 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 60f8118..c7622a8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -28,6 +28,19 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "getrandom 0.2.11", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "0.6.10" @@ -1815,7 +1828,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.7", ] [[package]] @@ -2169,6 +2182,17 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "iptools" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03bfb870879ce6a141b644653d63b203d290ec5f3b6919cf7b30cba06a164a5" +dependencies = [ + "ahash 0.8.7", + "once_cell", + "regex 1.10.2", +] + [[package]] name = "is-docker" version = "0.2.0" @@ -4468,13 +4492,13 @@ dependencies = [ [[package]] name = "sysproxy" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9707a79d3b95683aa5a9521e698ffd878b8fb289727c25a69157fb85d529ffff" +source = "git+https://github.com/clash-verge-rev/sysproxy-rs?branch=main#79390614ede8252158bf775ffaabbec04d8a4359" dependencies = [ "interfaces", + "iptools", "thiserror", - "winapi", - "winreg 0.10.1", + "windows 0.52.0", + "winreg 0.52.0", ] [[package]] @@ -6318,6 +6342,26 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 36076ee..918cd05 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,7 +14,6 @@ tauri-build = { version = "1", features = [] } [dependencies] warp = "0.3" -sysproxy = "0.3.0" which = "5.0.0" anyhow = "1.0" dirs = "5.0" @@ -39,6 +38,7 @@ window-shadows = { version = "0.2" } tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json", "rustls-tls"] } +sysproxy = { git="https://github.com/clash-verge-rev/sysproxy-rs", branch = "main" } tauri = { version = "1.5", features = [ "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] } [target.'cfg(windows)'.dependencies] diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index 8fe7d1d..e2c45e3 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -53,6 +53,9 @@ pub struct IVerge { /// set system proxy bypass pub system_proxy_bypass: Option, + /// set system proxy method + pub system_proxy_registry_mode: Option, + /// proxy guard duration pub proxy_guard_duration: Option, @@ -141,6 +144,7 @@ impl IVerge { enable_auto_launch: Some(false), enable_silent_start: Some(false), enable_system_proxy: Some(false), + system_proxy_registry_mode: Some(false), enable_random_port: Some(false), verge_mixed_port: Some(7897), enable_proxy_guard: Some(false), @@ -186,6 +190,7 @@ impl IVerge { patch!(enable_system_proxy); patch!(enable_proxy_guard); patch!(system_proxy_bypass); + patch!(system_proxy_registry_mode); patch!(proxy_guard_duration); patch!(theme_setting); diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index 965552c..342d930 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -58,6 +58,12 @@ impl Sysopt { ) }; + let registry_mode = { + let verge = Config::verge(); + let verge = verge.latest(); + verge.system_proxy_registry_mode.unwrap_or(false) + }; + let current = Sysproxy { enable, host: String::from("127.0.0.1"), @@ -67,7 +73,15 @@ impl Sysopt { if enable { let old = Sysproxy::get_system_proxy().ok(); - current.set_system_proxy()?; + + if registry_mode { + #[cfg(windows)] + current.set_system_proxy_with_registry()?; + #[cfg(not(windows))] + current.set_system_proxy()?; + } else { + current.set_system_proxy()?; + } *self.old_sysproxy.lock() = old; *self.cur_sysproxy.lock() = Some(current); @@ -97,12 +111,26 @@ impl Sysopt { verge.system_proxy_bypass.clone(), ) }; + + let registry_mode = { + let verge = Config::verge(); + let verge = verge.latest(); + verge.system_proxy_registry_mode.unwrap_or(false) + }; + let mut sysproxy = cur_sysproxy.take().unwrap(); sysproxy.enable = enable; sysproxy.bypass = bypass.unwrap_or(DEFAULT_BYPASS.into()); - sysproxy.set_system_proxy()?; + if registry_mode { + #[cfg(windows)] + sysproxy.set_system_proxy_with_registry()?; + #[cfg(not(windows))] + sysproxy.set_system_proxy()?; + } else { + sysproxy.set_system_proxy()?; + } *cur_sysproxy = Some(sysproxy); Ok(()) @@ -112,7 +140,11 @@ impl Sysopt { pub fn reset_sysproxy(&self) -> Result<()> { let mut cur_sysproxy = self.cur_sysproxy.lock(); let mut old_sysproxy = self.old_sysproxy.lock(); - + let registry_mode = { + let verge = Config::verge(); + let verge = verge.latest(); + verge.system_proxy_registry_mode.unwrap_or(false) + }; let cur_sysproxy = cur_sysproxy.take(); if let Some(mut old) = old_sysproxy.take() { @@ -127,12 +159,26 @@ impl Sysopt { log::info!(target: "app", "reset proxy to the original proxy"); } - old.set_system_proxy()?; + if registry_mode { + #[cfg(windows)] + old.set_system_proxy_with_registry()?; + #[cfg(not(windows))] + old.set_system_proxy()?; + } else { + old.set_system_proxy()?; + } } else if let Some(mut cur @ Sysproxy { enable: true, .. }) = cur_sysproxy { // 没有原代理,就按现在的代理设置disable即可 log::info!(target: "app", "reset proxy by disabling the current proxy"); cur.enable = false; - cur.set_system_proxy()?; + if registry_mode { + #[cfg(windows)] + cur.set_system_proxy_with_registry()?; + #[cfg(not(windows))] + cur.set_system_proxy()?; + } else { + cur.set_system_proxy()?; + } } else { log::info!(target: "app", "reset proxy with no action"); } @@ -251,7 +297,11 @@ impl Sysopt { use tokio::time::{sleep, Duration}; let guard_state = self.guard_state.clone(); - + let registry_mode = { + let verge = Config::verge(); + let verge = verge.latest(); + verge.system_proxy_registry_mode.unwrap_or(false) + }; tauri::async_runtime::spawn(async move { // if it is running, exit let mut state = guard_state.lock().await; @@ -301,8 +351,14 @@ impl Sysopt { port, bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()), }; - - log_err!(sysproxy.set_system_proxy()); + if registry_mode { + #[cfg(windows)] + log_err!(sysproxy.set_system_proxy_with_registry()); + #[cfg(not(windows))] + log_err!(sysproxy.set_system_proxy()); + } else { + log_err!(sysproxy.set_system_proxy()); + } } let mut state = guard_state.lock().await; diff --git a/src/components/setting/mods/sysproxy-viewer.tsx b/src/components/setting/mods/sysproxy-viewer.tsx index 8e47d00..0cca2b4 100644 --- a/src/components/setting/mods/sysproxy-viewer.tsx +++ b/src/components/setting/mods/sysproxy-viewer.tsx @@ -11,11 +11,15 @@ import { Switch, TextField, Typography, + Tooltip, } from "@mui/material"; +import getSystem from "@/utils/get-system"; import { useVerge } from "@/hooks/use-verge"; import { getSystemProxy } from "@/services/cmds"; import { BaseDialog, DialogRef, Notice } from "@/components/base"; +const OS = getSystem(); + export const SysproxyViewer = forwardRef((props, ref) => { const { t } = useTranslation(); @@ -31,12 +35,14 @@ export const SysproxyViewer = forwardRef((props, ref) => { enable_proxy_guard, system_proxy_bypass, proxy_guard_duration, + system_proxy_registry_mode, } = verge ?? {}; const [value, setValue] = useState({ guard: enable_proxy_guard, bypass: system_proxy_bypass, duration: proxy_guard_duration ?? 10, + registryMode: system_proxy_registry_mode, }); useImperativeHandle(ref, () => ({ @@ -46,6 +52,7 @@ export const SysproxyViewer = forwardRef((props, ref) => { guard: enable_proxy_guard, bypass: system_proxy_bypass, duration: proxy_guard_duration ?? 10, + registryMode: system_proxy_registry_mode, }); getSystemProxy().then((p) => setSysproxy(p)); }, @@ -69,6 +76,9 @@ export const SysproxyViewer = forwardRef((props, ref) => { if (value.bypass !== system_proxy_bypass) { patch.system_proxy_bypass = value.bypass; } + if (value.registryMode !== system_proxy_registry_mode) { + patch.system_proxy_registry_mode = value.registryMode; + } try { await patchVerge(patch); @@ -82,7 +92,7 @@ export const SysproxyViewer = forwardRef((props, ref) => { setOpen(false)} @@ -134,6 +144,27 @@ export const SysproxyViewer = forwardRef((props, ref) => { } /> + {OS === "windows" && ( + + + + + setValue((v) => ({ ...v, registryMode: e })) + } + /> + + + )} diff --git a/src/locales/en.json b/src/locales/en.json index 33e0984..7ed7293 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -84,6 +84,7 @@ "Proxy Guard": "Proxy Guard", "Guard Duration": "Guard Duration", "Proxy Bypass": "Proxy Bypass", + "Use Registry": "Use Registry", "Enable status": "Enable status", "Server Addr": "Server Addr", "Bypass": "Bypass", @@ -146,5 +147,7 @@ "Retain 30 Days": "Retain 30 Days", "Retain 90 Days": "Retain 90 Days", - "Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it" + "Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it", + "Please disable the system proxy": "Please disable the system proxy", + "Using the registry instead of Windows API": "Using the registry instead of Windows API" } diff --git a/src/locales/ru.json b/src/locales/ru.json index bce1d61..570349e 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -78,6 +78,7 @@ "Proxy Guard": "Защита прокси", "Guard Duration": "Период защиты", "Proxy Bypass": "Игнорирование прокси", + "Use Registry": "Использование реестра", "Current System Proxy": "Текущий системный прокси", "Theme Mode": "Режим темы", "Tray Click Event": "Событие щелчка в лотке", @@ -116,5 +117,7 @@ "enable_tun_mode": "Включить режим туннеля", "disable_tun_mode": "Отключить режим туннеля", - "Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените вручную" + "Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените вручную", + "Please disable the system proxy": "Пожалуйста, отключите системный прокси", + "Using the registry instead of Windows API": "Использование реестра вместо Windows API" } diff --git a/src/locales/zh.json b/src/locales/zh.json index 1a40024..e1942ec 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -84,6 +84,7 @@ "Proxy Guard": "系统代理守卫", "Guard Duration": "代理守卫间隔", "Proxy Bypass": "代理绕过", + "Use Registry": "使用注册表", "Current System Proxy": "当前系统代理", "Enable status": "开启状态:", "Server Addr": "服务地址:", @@ -146,5 +147,7 @@ "Retain 30 Days": "保留30天", "Retain 90 Days": "保留90天", - "Portable Updater Error": "便携版不支持应用内更新,请手动下载替换" + "Portable Updater Error": "便携版不支持应用内更新,请手动下载替换", + "Please disable the system proxy": "请先关闭系统代理", + "Using the registry instead of Windows API": "使用注册表替代Windows API" } diff --git a/src/services/types.d.ts b/src/services/types.d.ts index d527bbb..5563f20 100644 --- a/src/services/types.d.ts +++ b/src/services/types.d.ts @@ -173,6 +173,7 @@ interface IVergeConfig { enable_proxy_guard?: boolean; proxy_guard_duration?: number; system_proxy_bypass?: string; + system_proxy_registry_mode?: boolean; web_ui_list?: string[]; hotkeys?: string[]; theme_setting?: {