Selaa lähdekoodia

feat: Support both registry and api for windows sysproxy

MystiPanda 1 vuosi sitten
vanhempi
commit
1606adc0ab

+ 49 - 5
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"

+ 1 - 1
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]

+ 5 - 0
src-tauri/src/config/verge.rs

@@ -53,6 +53,9 @@ pub struct IVerge {
     /// set system proxy bypass
     pub system_proxy_bypass: Option<String>,
 
+    /// set system proxy method
+    pub system_proxy_registry_mode: Option<bool>,
+
     /// proxy guard duration
     pub proxy_guard_duration: Option<u64>,
 
@@ -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);

+ 64 - 8
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;

+ 32 - 1
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<DialogRef>((props, ref) => {
   const { t } = useTranslation();
 
@@ -31,12 +35,14 @@ export const SysproxyViewer = forwardRef<DialogRef>((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<DialogRef>((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<DialogRef>((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<DialogRef>((props, ref) => {
     <BaseDialog
       open={open}
       title={t("System Proxy Setting")}
-      contentSx={{ width: 450, maxHeight: 300 }}
+      contentSx={{ width: 450, maxHeight: 500 }}
       okBtn={t("Save")}
       cancelBtn={t("Cancel")}
       onClose={() => setOpen(false)}
@@ -134,6 +144,27 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
             }
           />
         </ListItem>
+        {OS === "windows" && (
+          <Tooltip
+            title={
+              enabled
+                ? t("Please disable the system proxy")
+                : t("Using the registry instead of Windows API")
+            }
+          >
+            <ListItem sx={{ padding: "5px 2px" }}>
+              <ListItemText primary={t("Use Registry")} />
+              <Switch
+                edge="end"
+                disabled={enabled}
+                checked={value.registryMode}
+                onChange={(_, e) =>
+                  setValue((v) => ({ ...v, registryMode: e }))
+                }
+              />
+            </ListItem>
+          </Tooltip>
+        )}
       </List>
 
       <Box sx={{ mt: 2.5 }}>

+ 4 - 1
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"
 }

+ 4 - 1
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"
 }

+ 4 - 1
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"
 }

+ 1 - 0
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?: {