mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 03:03:46 +08:00
添加代理主机的设置,允许代理设置为其他IP(非127.0.0.1) (#2963)
允许下拉选择ip地址(支持IPv6)、localhost、以及当前系统的主机名,同时兼容手工输入
This commit is contained in:
parent
224096abce
commit
d0836781d1
13
src-tauri/Cargo.lock
generated
13
src-tauri/Cargo.lock
generated
@ -1056,6 +1056,7 @@ dependencies = [
|
|||||||
"dirs 6.0.0",
|
"dirs 6.0.0",
|
||||||
"dunce",
|
"dunce",
|
||||||
"futures",
|
"futures",
|
||||||
|
"gethostname 1.0.1",
|
||||||
"getrandom 0.3.2",
|
"getrandom 0.3.2",
|
||||||
"image",
|
"image",
|
||||||
"imageproc",
|
"imageproc",
|
||||||
@ -2416,6 +2417,16 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed7131e57abbde63513e0e6636f76668a1ca9798dcae2df4e283cae9ee83859e"
|
||||||
|
dependencies = [
|
||||||
|
"rustix 1.0.3",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -9319,7 +9330,7 @@ version = "0.13.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
|
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gethostname",
|
"gethostname 0.4.3",
|
||||||
"rustix 0.38.44",
|
"rustix 0.38.44",
|
||||||
"x11rb-protocol",
|
"x11rb-protocol",
|
||||||
]
|
]
|
||||||
|
@ -75,6 +75,7 @@ mihomo_api = { path = "src_crates/crate_mihomo_api" }
|
|||||||
ab_glyph = "0.2.29"
|
ab_glyph = "0.2.29"
|
||||||
tungstenite = "0.26.2"
|
tungstenite = "0.26.2"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
gethostname = "1.0.1"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
runas = "=1.2.0"
|
runas = "=1.2.0"
|
||||||
|
@ -31,6 +31,25 @@ pub fn get_auto_proxy() -> CmdResult<Mapping> {
|
|||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取系统主机名
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_system_hostname() -> CmdResult<String> {
|
||||||
|
use gethostname::gethostname;
|
||||||
|
|
||||||
|
// 获取系统主机名,处理可能的非UTF-8字符
|
||||||
|
let hostname = match gethostname().into_string() {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(os_string) => {
|
||||||
|
// 对于包含非UTF-8的主机名,使用调试格式化
|
||||||
|
let fallback = format!("{:?}", os_string);
|
||||||
|
// 去掉可能存在的引号
|
||||||
|
fallback.trim_matches('"').to_string()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(hostname)
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取网络接口列表
|
/// 获取网络接口列表
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_network_interfaces() -> Vec<String> {
|
pub fn get_network_interfaces() -> Vec<String> {
|
||||||
|
@ -88,6 +88,9 @@ pub struct IVerge {
|
|||||||
/// pac script content
|
/// pac script content
|
||||||
pub pac_file_content: Option<String>,
|
pub pac_file_content: Option<String>,
|
||||||
|
|
||||||
|
/// proxy host address
|
||||||
|
pub proxy_host: Option<String>,
|
||||||
|
|
||||||
/// theme setting
|
/// theme setting
|
||||||
pub theme_setting: Option<IVergeTheme>,
|
pub theme_setting: Option<IVergeTheme>,
|
||||||
|
|
||||||
@ -275,6 +278,7 @@ impl IVerge {
|
|||||||
enable_system_proxy: Some(false),
|
enable_system_proxy: Some(false),
|
||||||
proxy_auto_config: Some(false),
|
proxy_auto_config: Some(false),
|
||||||
pac_file_content: Some(DEFAULT_PAC.into()),
|
pac_file_content: Some(DEFAULT_PAC.into()),
|
||||||
|
proxy_host: Some("127.0.0.1".into()),
|
||||||
enable_random_port: Some(false),
|
enable_random_port: Some(false),
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
verge_redir_port: Some(7895),
|
verge_redir_port: Some(7895),
|
||||||
@ -368,7 +372,7 @@ impl IVerge {
|
|||||||
patch!(proxy_guard_duration);
|
patch!(proxy_guard_duration);
|
||||||
patch!(proxy_auto_config);
|
patch!(proxy_auto_config);
|
||||||
patch!(pac_file_content);
|
patch!(pac_file_content);
|
||||||
|
patch!(proxy_host);
|
||||||
patch!(theme_setting);
|
patch!(theme_setting);
|
||||||
patch!(web_ui_list);
|
patch!(web_ui_list);
|
||||||
patch!(clash_core);
|
patch!(clash_core);
|
||||||
@ -452,6 +456,7 @@ pub struct IVergeResponse {
|
|||||||
pub proxy_guard_duration: Option<u64>,
|
pub proxy_guard_duration: Option<u64>,
|
||||||
pub proxy_auto_config: Option<bool>,
|
pub proxy_auto_config: Option<bool>,
|
||||||
pub pac_file_content: Option<String>,
|
pub pac_file_content: Option<String>,
|
||||||
|
pub proxy_host: Option<String>,
|
||||||
pub theme_setting: Option<IVergeTheme>,
|
pub theme_setting: Option<IVergeTheme>,
|
||||||
pub web_ui_list: Option<Vec<String>>,
|
pub web_ui_list: Option<Vec<String>>,
|
||||||
pub clash_core: Option<String>,
|
pub clash_core: Option<String>,
|
||||||
@ -520,6 +525,7 @@ impl From<IVerge> for IVergeResponse {
|
|||||||
proxy_guard_duration: verge.proxy_guard_duration,
|
proxy_guard_duration: verge.proxy_guard_duration,
|
||||||
proxy_auto_config: verge.proxy_auto_config,
|
proxy_auto_config: verge.proxy_auto_config,
|
||||||
pac_file_content: verge.pac_file_content,
|
pac_file_content: verge.pac_file_content,
|
||||||
|
proxy_host: verge.proxy_host,
|
||||||
theme_setting: verge.theme_setting,
|
theme_setting: verge.theme_setting,
|
||||||
web_ui_list: verge.web_ui_list,
|
web_ui_list: verge.web_ui_list,
|
||||||
clash_core: verge.clash_core,
|
clash_core: verge.clash_core,
|
||||||
|
@ -76,12 +76,13 @@ impl Sysopt {
|
|||||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
let pac_port = IVerge::get_singleton_port();
|
let pac_port = IVerge::get_singleton_port();
|
||||||
|
|
||||||
let (sys_enable, pac_enable) = {
|
let (sys_enable, pac_enable, proxy_host) = {
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
verge.enable_system_proxy.unwrap_or(false),
|
verge.enable_system_proxy.unwrap_or(false),
|
||||||
verge.proxy_auto_config.unwrap_or(false),
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
|
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,13 +90,13 @@ impl Sysopt {
|
|||||||
{
|
{
|
||||||
let mut sys = Sysproxy {
|
let mut sys = Sysproxy {
|
||||||
enable: false,
|
enable: false,
|
||||||
host: String::from("127.0.0.1"),
|
host: proxy_host.clone(),
|
||||||
port,
|
port,
|
||||||
bypass: get_bypass(),
|
bypass: get_bypass(),
|
||||||
};
|
};
|
||||||
let mut auto = Autoproxy {
|
let mut auto = Autoproxy {
|
||||||
enable: false,
|
enable: false,
|
||||||
url: format!("http://127.0.0.1:{pac_port}/commands/pac"),
|
url: format!("http://{}:{}/commands/pac", proxy_host, pac_port),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !sys_enable {
|
if !sys_enable {
|
||||||
@ -139,7 +140,7 @@ impl Sysopt {
|
|||||||
|
|
||||||
let shell = app_handle.shell();
|
let shell = app_handle.shell();
|
||||||
let output = if pac_enable {
|
let output = if pac_enable {
|
||||||
let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port);
|
let address = format!("http://{}:{}/commands/pac", proxy_host, pac_port);
|
||||||
let output = shell
|
let output = shell
|
||||||
.command(sysproxy_exe.as_path().to_str().unwrap())
|
.command(sysproxy_exe.as_path().to_str().unwrap())
|
||||||
.args(["pac", address.as_str()])
|
.args(["pac", address.as_str()])
|
||||||
@ -148,7 +149,7 @@ impl Sysopt {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
output
|
output
|
||||||
} else {
|
} else {
|
||||||
let address = format!("{}:{}", "127.0.0.1", port);
|
let address = format!("{}:{}", proxy_host, port);
|
||||||
let bypass = get_bypass();
|
let bypass = get_bypass();
|
||||||
let output = shell
|
let output = shell
|
||||||
.command(sysproxy_exe.as_path().to_str().unwrap())
|
.command(sysproxy_exe.as_path().to_str().unwrap())
|
||||||
@ -256,7 +257,7 @@ impl Sysopt {
|
|||||||
loop {
|
loop {
|
||||||
sleep(Duration::from_secs(wait_secs)).await;
|
sleep(Duration::from_secs(wait_secs)).await;
|
||||||
|
|
||||||
let (enable, guard, guard_duration, pac) = {
|
let (enable, guard, guard_duration, pac, proxy_host) = {
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
@ -264,6 +265,7 @@ impl Sysopt {
|
|||||||
verge.enable_proxy_guard.unwrap_or(false),
|
verge.enable_proxy_guard.unwrap_or(false),
|
||||||
verge.proxy_guard_duration.unwrap_or(10),
|
verge.proxy_guard_duration.unwrap_or(10),
|
||||||
verge.proxy_auto_config.unwrap_or(false),
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
|
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -303,13 +305,13 @@ impl Sysopt {
|
|||||||
if pac {
|
if pac {
|
||||||
let autoproxy = Autoproxy {
|
let autoproxy = Autoproxy {
|
||||||
enable: true,
|
enable: true,
|
||||||
url: format!("http://127.0.0.1:{pac_port}/commands/pac"),
|
url: format!("http://{}:{}/commands/pac", proxy_host, pac_port),
|
||||||
};
|
};
|
||||||
logging_error!(Type::System, true, autoproxy.set_auto_proxy());
|
logging_error!(Type::System, true, autoproxy.set_auto_proxy());
|
||||||
} else {
|
} else {
|
||||||
let sysproxy = Sysproxy {
|
let sysproxy = Sysproxy {
|
||||||
enable: true,
|
enable: true,
|
||||||
host: "127.0.0.1".into(),
|
host: proxy_host.into(),
|
||||||
port,
|
port,
|
||||||
bypass: get_bypass(),
|
bypass: get_bypass(),
|
||||||
};
|
};
|
||||||
@ -333,7 +335,7 @@ impl Sysopt {
|
|||||||
|
|
||||||
let shell = app_handle.shell();
|
let shell = app_handle.shell();
|
||||||
let output = if pac {
|
let output = if pac {
|
||||||
let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port);
|
let address = format!("http://{}:{}/commands/pac", proxy_host, pac_port);
|
||||||
|
|
||||||
shell
|
shell
|
||||||
.command(sysproxy_exe.as_path().to_str().unwrap())
|
.command(sysproxy_exe.as_path().to_str().unwrap())
|
||||||
@ -342,7 +344,7 @@ impl Sysopt {
|
|||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
let address = format!("{}:{}", "127.0.0.1", port);
|
let address = format!("{}:{}", proxy_host, port);
|
||||||
let bypass = get_bypass();
|
let bypass = get_bypass();
|
||||||
|
|
||||||
shell
|
shell
|
||||||
|
@ -63,9 +63,14 @@ pub fn toggle_tun_mode(not_save_file: Option<bool>) {
|
|||||||
|
|
||||||
/// Copy proxy environment variables to clipboard
|
/// Copy proxy environment variables to clipboard
|
||||||
pub fn copy_clash_env() {
|
pub fn copy_clash_env() {
|
||||||
// 从环境变量获取IP地址,默认127.0.0.1
|
// 从环境变量获取IP地址,如果没有则从配置中获取 proxy_host,默认为 127.0.0.1
|
||||||
let clash_verge_rev_ip =
|
let clash_verge_rev_ip = env::var("CLASH_VERGE_REV_IP").unwrap_or_else(|_| {
|
||||||
env::var("CLASH_VERGE_REV_IP").unwrap_or_else(|_| "127.0.0.1".to_string());
|
Config::verge()
|
||||||
|
.latest()
|
||||||
|
.proxy_host
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "127.0.0.1".to_string())
|
||||||
|
});
|
||||||
|
|
||||||
let app_handle = handle::Handle::global().app_handle().unwrap();
|
let app_handle = handle::Handle::global().app_handle().unwrap();
|
||||||
let port = { Config::verge().latest().verge_mixed_port.unwrap_or(7897) };
|
let port = { Config::verge().latest().verge_mixed_port.unwrap_or(7897) };
|
||||||
|
@ -156,6 +156,7 @@ pub fn run() {
|
|||||||
cmd::open_core_dir,
|
cmd::open_core_dir,
|
||||||
cmd::get_portable_flag,
|
cmd::get_portable_flag,
|
||||||
cmd::get_network_interfaces,
|
cmd::get_network_interfaces,
|
||||||
|
cmd::get_system_hostname,
|
||||||
cmd::restart_core,
|
cmd::restart_core,
|
||||||
cmd::restart_app,
|
cmd::restart_app,
|
||||||
// 添加新的命令
|
// 添加新的命令
|
||||||
|
@ -3,10 +3,17 @@ import { BaseFieldset } from "@/components/base/base-fieldset";
|
|||||||
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
|
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
|
||||||
import { EditorViewer } from "@/components/profile/editor-viewer";
|
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
import { getAutotemProxy, getSystemProxy } from "@/services/cmds";
|
import {
|
||||||
|
getAutotemProxy,
|
||||||
|
getNetworkInterfaces,
|
||||||
|
getNetworkInterfacesInfo,
|
||||||
|
getSystemHostname,
|
||||||
|
getSystemProxy,
|
||||||
|
} from "@/services/cmds";
|
||||||
import getSystem from "@/utils/get-system";
|
import getSystem from "@/utils/get-system";
|
||||||
import { EditRounded } from "@mui/icons-material";
|
import { EditRounded } from "@mui/icons-material";
|
||||||
import {
|
import {
|
||||||
|
Autocomplete,
|
||||||
Button,
|
Button,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
List,
|
List,
|
||||||
@ -17,10 +24,16 @@ import {
|
|||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
import { forwardRef, useImperativeHandle, useMemo, useState } from "react";
|
import {
|
||||||
|
forwardRef,
|
||||||
|
useImperativeHandle,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
const DEFAULT_PAC = `function FindProxyForURL(url, host) {
|
const DEFAULT_PAC = `function FindProxyForURL(url, host) {
|
||||||
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
return "PROXY %proxy_host%:%mixed-port%; SOCKS5 %proxy_host%:%mixed-port%; DIRECT;";
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
/** NO_PROXY validation */
|
/** NO_PROXY validation */
|
||||||
@ -64,6 +77,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [editorOpen, setEditorOpen] = useState(false);
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
const { verge, patchVerge } = useVerge();
|
const { verge, patchVerge } = useVerge();
|
||||||
|
const [hostOptions, setHostOptions] = useState<string[]>([]);
|
||||||
|
|
||||||
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
||||||
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
||||||
@ -79,6 +93,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
use_default_bypass,
|
use_default_bypass,
|
||||||
system_proxy_bypass,
|
system_proxy_bypass,
|
||||||
proxy_guard_duration,
|
proxy_guard_duration,
|
||||||
|
proxy_host,
|
||||||
} = verge ?? {};
|
} = verge ?? {};
|
||||||
|
|
||||||
const [value, setValue] = useState({
|
const [value, setValue] = useState({
|
||||||
@ -88,6 +103,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
use_default: use_default_bypass ?? true,
|
use_default: use_default_bypass ?? true,
|
||||||
pac: proxy_auto_config,
|
pac: proxy_auto_config,
|
||||||
pac_content: pac_file_content ?? DEFAULT_PAC,
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
|
proxy_host: proxy_host ?? "127.0.0.1",
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultBypass = () => {
|
const defaultBypass = () => {
|
||||||
@ -110,13 +126,74 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
use_default: use_default_bypass ?? true,
|
use_default: use_default_bypass ?? true,
|
||||||
pac: proxy_auto_config,
|
pac: proxy_auto_config,
|
||||||
pac_content: pac_file_content ?? DEFAULT_PAC,
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
|
proxy_host: proxy_host ?? "127.0.0.1",
|
||||||
});
|
});
|
||||||
getSystemProxy().then((p) => setSysproxy(p));
|
getSystemProxy().then((p) => setSysproxy(p));
|
||||||
getAutotemProxy().then((p) => setAutoproxy(p));
|
getAutotemProxy().then((p) => setAutoproxy(p));
|
||||||
|
fetchNetworkInterfaces();
|
||||||
},
|
},
|
||||||
close: () => setOpen(false),
|
close: () => setOpen(false),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// 获取网络接口和主机名
|
||||||
|
const fetchNetworkInterfaces = async () => {
|
||||||
|
try {
|
||||||
|
// 获取系统网络接口信息
|
||||||
|
const interfaces = await getNetworkInterfacesInfo();
|
||||||
|
const ipAddresses: string[] = [];
|
||||||
|
|
||||||
|
// 从interfaces中提取IPv4和IPv6地址
|
||||||
|
interfaces.forEach((iface) => {
|
||||||
|
iface.addr.forEach((address) => {
|
||||||
|
if (address.V4 && address.V4.ip) {
|
||||||
|
ipAddresses.push(address.V4.ip);
|
||||||
|
}
|
||||||
|
if (address.V6 && address.V6.ip) {
|
||||||
|
ipAddresses.push(address.V6.ip);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取当前系统的主机名
|
||||||
|
let hostname = "";
|
||||||
|
try {
|
||||||
|
hostname = await getSystemHostname();
|
||||||
|
console.log("获取到主机名:", hostname);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("获取主机名失败:", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建选项列表
|
||||||
|
const options = ["127.0.0.1", "localhost"];
|
||||||
|
|
||||||
|
// 确保主机名添加到列表,即使它是空字符串也记录下来
|
||||||
|
if (hostname) {
|
||||||
|
// 如果主机名不是localhost或127.0.0.1,则添加它
|
||||||
|
if (hostname !== "localhost" && hostname !== "127.0.0.1") {
|
||||||
|
hostname = hostname + ".local";
|
||||||
|
options.push(hostname);
|
||||||
|
console.log("主机名已添加到选项中:", hostname);
|
||||||
|
} else {
|
||||||
|
console.log("主机名与已有选项重复:", hostname);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("主机名为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加IP地址
|
||||||
|
options.push(...ipAddresses);
|
||||||
|
|
||||||
|
// 去重
|
||||||
|
const uniqueOptions = Array.from(new Set(options));
|
||||||
|
console.log("最终选项列表:", uniqueOptions);
|
||||||
|
setHostOptions(uniqueOptions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取网络接口失败:", error);
|
||||||
|
// 失败时至少提供基本选项
|
||||||
|
setHostOptions(["127.0.0.1", "localhost"]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onSave = useLockFn(async () => {
|
const onSave = useLockFn(async () => {
|
||||||
if (value.duration < 1) {
|
if (value.duration < 1) {
|
||||||
Notice.error(t("Proxy Daemon Duration Cannot be Less than 1 Second"));
|
Notice.error(t("Proxy Daemon Duration Cannot be Less than 1 Second"));
|
||||||
@ -127,6 +204,23 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改验证规则,允许IP和主机名
|
||||||
|
const ipv4Regex =
|
||||||
|
/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||||
|
const ipv6Regex =
|
||||||
|
/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
||||||
|
const hostnameRegex =
|
||||||
|
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!ipv4Regex.test(value.proxy_host) &&
|
||||||
|
!ipv6Regex.test(value.proxy_host) &&
|
||||||
|
!hostnameRegex.test(value.proxy_host)
|
||||||
|
) {
|
||||||
|
Notice.error(t("Invalid Proxy Host Format"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const patch: Partial<IVergeConfig> = {};
|
const patch: Partial<IVergeConfig> = {};
|
||||||
|
|
||||||
if (value.guard !== enable_proxy_guard) {
|
if (value.guard !== enable_proxy_guard) {
|
||||||
@ -138,15 +232,34 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
if (value.bypass !== system_proxy_bypass) {
|
if (value.bypass !== system_proxy_bypass) {
|
||||||
patch.system_proxy_bypass = value.bypass;
|
patch.system_proxy_bypass = value.bypass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.pac !== proxy_auto_config) {
|
if (value.pac !== proxy_auto_config) {
|
||||||
patch.proxy_auto_config = value.pac;
|
patch.proxy_auto_config = value.pac;
|
||||||
}
|
}
|
||||||
if (value.use_default !== use_default_bypass) {
|
if (value.use_default !== use_default_bypass) {
|
||||||
patch.use_default_bypass = value.use_default;
|
patch.use_default_bypass = value.use_default;
|
||||||
}
|
}
|
||||||
if (value.pac_content !== pac_file_content) {
|
|
||||||
patch.pac_file_content = value.pac_content;
|
let pacContent = value.pac_content;
|
||||||
|
if (pacContent) {
|
||||||
|
pacContent = pacContent.replace(/%proxy_host%/g, value.proxy_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pacContent !== pac_file_content) {
|
||||||
|
patch.pac_file_content = pacContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理IPv6地址,如果是IPv6地址但没有被方括号包围,则添加方括号
|
||||||
|
let proxyHost = value.proxy_host;
|
||||||
|
if (
|
||||||
|
ipv6Regex.test(proxyHost) &&
|
||||||
|
!proxyHost.startsWith("[") &&
|
||||||
|
!proxyHost.endsWith("]")
|
||||||
|
) {
|
||||||
|
proxyHost = `[${proxyHost}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyHost !== proxy_host) {
|
||||||
|
patch.proxy_host = proxyHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -199,6 +312,31 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
</FlexBox>
|
</FlexBox>
|
||||||
)}
|
)}
|
||||||
</BaseFieldset>
|
</BaseFieldset>
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText primary={t("Proxy Host")} />
|
||||||
|
<Autocomplete
|
||||||
|
size="small"
|
||||||
|
sx={{ width: 150 }}
|
||||||
|
options={hostOptions}
|
||||||
|
value={value.proxy_host}
|
||||||
|
freeSolo
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField {...params} placeholder="127.0.0.1" size="small" />
|
||||||
|
)}
|
||||||
|
onChange={(_, newValue) => {
|
||||||
|
setValue((v) => ({
|
||||||
|
...v,
|
||||||
|
proxy_host: newValue || "127.0.0.1",
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
onInputChange={(_, newInputValue) => {
|
||||||
|
setValue((v) => ({
|
||||||
|
...v,
|
||||||
|
proxy_host: newInputValue || "127.0.0.1",
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
<ListItemText primary={t("Use PAC Mode")} />
|
<ListItemText primary={t("Use PAC Mode")} />
|
||||||
<Switch
|
<Switch
|
||||||
|
@ -225,6 +225,8 @@
|
|||||||
"Enabled": "ممكّن",
|
"Enabled": "ممكّن",
|
||||||
"Disabled": "معطّل",
|
"Disabled": "معطّل",
|
||||||
"Server Addr": "عنوان الخادم:",
|
"Server Addr": "عنوان الخادم:",
|
||||||
|
"Proxy Host": "مضيف الوكيل",
|
||||||
|
"Invalid Proxy Host Format": "تنسيق مضيف الوكيل غير صالح",
|
||||||
"Not available": "غير متوفر",
|
"Not available": "غير متوفر",
|
||||||
"Proxy Guard": "حماية الوكيل",
|
"Proxy Guard": "حماية الوكيل",
|
||||||
"Proxy Guard Info": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام",
|
"Proxy Guard Info": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام",
|
||||||
|
@ -243,6 +243,8 @@
|
|||||||
"Enabled": "Enabled",
|
"Enabled": "Enabled",
|
||||||
"Disabled": "Disabled",
|
"Disabled": "Disabled",
|
||||||
"Server Addr": "Server Addr: ",
|
"Server Addr": "Server Addr: ",
|
||||||
|
"Proxy Host": "Proxy Host",
|
||||||
|
"Invalid Proxy Host Format": "Invalid Proxy Host Format",
|
||||||
"Not available": "Not available",
|
"Not available": "Not available",
|
||||||
"Proxy Guard": "Proxy Guard",
|
"Proxy Guard": "Proxy Guard",
|
||||||
"Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings",
|
"Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings",
|
||||||
|
@ -225,6 +225,8 @@
|
|||||||
"Enabled": "توانایی فعال شد",
|
"Enabled": "توانایی فعال شد",
|
||||||
"Disabled": "غیرفعال شد",
|
"Disabled": "غیرفعال شد",
|
||||||
"Server Addr": "آدرس سرور: ",
|
"Server Addr": "آدرس سرور: ",
|
||||||
|
"Proxy Host": "میزبان پراکسی",
|
||||||
|
"Invalid Proxy Host Format": "فرمت میزبان پراکسی نامعتبر است",
|
||||||
"Not available": "غیر فعال شد",
|
"Not available": "غیر فعال شد",
|
||||||
"Proxy Guard": "محافظ پراکسی",
|
"Proxy Guard": "محافظ پراکسی",
|
||||||
"Proxy Guard Info": "امکان جلوگیری از نرمافزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید",
|
"Proxy Guard Info": "امکان جلوگیری از نرمافزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید",
|
||||||
|
@ -257,6 +257,8 @@
|
|||||||
"Enabled": "Diaktifkan",
|
"Enabled": "Diaktifkan",
|
||||||
"Disabled": "Dinonaktifkan",
|
"Disabled": "Dinonaktifkan",
|
||||||
"Server Addr": "Alamat Server: ",
|
"Server Addr": "Alamat Server: ",
|
||||||
|
"Proxy Host": "Host Proksi",
|
||||||
|
"Invalid Proxy Host Format": "Format Host Proksi Tidak Valid",
|
||||||
"Not available": "Tidak tersedia",
|
"Not available": "Tidak tersedia",
|
||||||
"Proxy Guard": "Penjaga Proksi",
|
"Proxy Guard": "Penjaga Proksi",
|
||||||
"Proxy Guard Info": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi",
|
"Proxy Guard Info": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi",
|
||||||
|
@ -240,6 +240,8 @@
|
|||||||
"Enabled": "Включено",
|
"Enabled": "Включено",
|
||||||
"Disabled": "Отключено",
|
"Disabled": "Отключено",
|
||||||
"Server Addr": "Адрес сервера: ",
|
"Server Addr": "Адрес сервера: ",
|
||||||
|
"Proxy Host": "Хост прокси",
|
||||||
|
"Invalid Proxy Host Format": "Неверный формат хоста прокси",
|
||||||
"Not available": "Недоступно",
|
"Not available": "Недоступно",
|
||||||
"Proxy Guard": "Proxy Guard",
|
"Proxy Guard": "Proxy Guard",
|
||||||
"Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО",
|
"Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО",
|
||||||
|
@ -225,6 +225,8 @@
|
|||||||
"Enabled": "Кушылган",
|
"Enabled": "Кушылган",
|
||||||
"Disabled": "Сүнгән",
|
"Disabled": "Сүнгән",
|
||||||
"Server Addr": "Сервер адресы",
|
"Server Addr": "Сервер адресы",
|
||||||
|
"Proxy Host": "Прокси хосты",
|
||||||
|
"Invalid Proxy Host Format": "Прокси хосты форматы дөрес түгел",
|
||||||
"Not available": "Мөмкин түгел",
|
"Not available": "Мөмкин түгел",
|
||||||
"Proxy Guard": "Прокси саклаучы",
|
"Proxy Guard": "Прокси саклаучы",
|
||||||
"Proxy Guard Info": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз",
|
"Proxy Guard Info": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз",
|
||||||
|
@ -243,6 +243,8 @@
|
|||||||
"Enabled": "已启用",
|
"Enabled": "已启用",
|
||||||
"Disabled": "未启用",
|
"Disabled": "未启用",
|
||||||
"Server Addr": "服务地址:",
|
"Server Addr": "服务地址:",
|
||||||
|
"Proxy Host": "代理主机",
|
||||||
|
"Invalid Proxy Host Format": "代理主机格式无效",
|
||||||
"Not available": "不可用",
|
"Not available": "不可用",
|
||||||
"Proxy Guard": "系统代理守卫",
|
"Proxy Guard": "系统代理守卫",
|
||||||
"Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置",
|
"Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置",
|
||||||
|
@ -265,6 +265,10 @@ export async function getNetworkInterfaces() {
|
|||||||
return invoke<string[]>("get_network_interfaces");
|
return invoke<string[]>("get_network_interfaces");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSystemHostname() {
|
||||||
|
return invoke<string>("get_system_hostname");
|
||||||
|
}
|
||||||
|
|
||||||
export async function getNetworkInterfacesInfo() {
|
export async function getNetworkInterfacesInfo() {
|
||||||
return invoke<INetworkInterface[]>("get_network_interfaces_info");
|
return invoke<INetworkInterface[]>("get_network_interfaces_info");
|
||||||
}
|
}
|
||||||
|
1
src/services/types.d.ts
vendored
1
src/services/types.d.ts
vendored
@ -750,6 +750,7 @@ interface IVergeConfig {
|
|||||||
enable_external_controller?: boolean;
|
enable_external_controller?: boolean;
|
||||||
proxy_auto_config?: boolean;
|
proxy_auto_config?: boolean;
|
||||||
pac_file_content?: string;
|
pac_file_content?: string;
|
||||||
|
proxy_host?: string;
|
||||||
enable_random_port?: boolean;
|
enable_random_port?: boolean;
|
||||||
verge_mixed_port?: number;
|
verge_mixed_port?: number;
|
||||||
verge_socks_port?: number;
|
verge_socks_port?: number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user