mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-16 23:40:32 +08:00
fix(proxy): check if proxy port is in use #5891
This commit is contained in:
parent
5afe11e55b
commit
16c3dcc616
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- 修复 macOS 有线网络 DNS 劫持失败
|
- 修复 macOS 有线网络 DNS 劫持失败
|
||||||
- 修复 Monaco 编辑器内右键菜单显示异常
|
- 修复 Monaco 编辑器内右键菜单显示异常
|
||||||
|
- 修复设置代理端口时检查端口占用
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong> ✨ 新增功能 </strong></summary>
|
<summary><strong> ✨ 新增功能 </strong></summary>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use clash_verge_logging::{Type, logging};
|
|||||||
use gethostname::gethostname;
|
use gethostname::gethostname;
|
||||||
use network_interface::NetworkInterface;
|
use network_interface::NetworkInterface;
|
||||||
use serde_yaml_ng::Mapping;
|
use serde_yaml_ng::Mapping;
|
||||||
|
use std::net::TcpListener;
|
||||||
use sysproxy::{Autoproxy, Sysproxy};
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
use tauri_plugin_clash_verge_sysinfo;
|
use tauri_plugin_clash_verge_sysinfo;
|
||||||
|
|
||||||
@ -95,3 +96,11 @@ pub fn get_network_interfaces_info() -> CmdResult<Vec<NetworkInterface>> {
|
|||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn is_port_in_use(port: u16) -> bool {
|
||||||
|
match TcpListener::bind(("127.0.0.1", port)) {
|
||||||
|
Ok(_listener) => false,
|
||||||
|
Err(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -137,6 +137,7 @@ mod app_init {
|
|||||||
tauri_plugin_clash_verge_sysinfo::commands::get_app_uptime,
|
tauri_plugin_clash_verge_sysinfo::commands::get_app_uptime,
|
||||||
tauri_plugin_clash_verge_sysinfo::commands::app_is_admin,
|
tauri_plugin_clash_verge_sysinfo::commands::app_is_admin,
|
||||||
tauri_plugin_clash_verge_sysinfo::commands::export_diagnostic_info,
|
tauri_plugin_clash_verge_sysinfo::commands::export_diagnostic_info,
|
||||||
|
cmd::is_port_in_use,
|
||||||
cmd::get_sys_proxy,
|
cmd::get_sys_proxy,
|
||||||
cmd::get_auto_proxy,
|
cmd::get_auto_proxy,
|
||||||
cmd::open_app_dir,
|
cmd::open_app_dir,
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useLockFn, useRequest } from "ahooks";
|
import { useLockFn, useRequest } from "ahooks";
|
||||||
import { forwardRef, useImperativeHandle, useState } from "react";
|
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { BaseDialog, Switch } from "@/components/base";
|
import { BaseDialog, Switch } from "@/components/base";
|
||||||
import { useClashInfo } from "@/hooks/use-clash";
|
import { useClashInfo } from "@/hooks/use-clash";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
|
import { isPortInUse } from "@/services/cmds";
|
||||||
import { showNotice } from "@/services/notice-service";
|
import { showNotice } from "@/services/notice-service";
|
||||||
import getSystem from "@/utils/get-system";
|
import getSystem from "@/utils/get-system";
|
||||||
|
|
||||||
@ -59,6 +60,9 @@ export const ClashPortViewer = forwardRef<ClashPortViewerRef>((_, ref) => {
|
|||||||
verge?.verge_tproxy_enabled ?? false,
|
verge?.verge_tproxy_enabled ?? false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 保存打开对话框时的原始值,用于在检测到端口被占用时恢复
|
||||||
|
const originalPortsRef = useRef<Record<string, any> | null>(null);
|
||||||
|
|
||||||
// 添加保存请求,防止GUI卡死
|
// 添加保存请求,防止GUI卡死
|
||||||
const { loading, run: saveSettings } = useRequest(
|
const { loading, run: saveSettings } = useRequest(
|
||||||
async (params: { clashConfig: any; vergeConfig: any }) => {
|
async (params: { clashConfig: any; vergeConfig: any }) => {
|
||||||
@ -82,15 +86,27 @@ export const ClashPortViewer = forwardRef<ClashPortViewerRef>((_, ref) => {
|
|||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
open: () => {
|
open: () => {
|
||||||
setMixedPort(verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897);
|
originalPortsRef.current = {
|
||||||
setSocksPort(verge?.verge_socks_port ?? 7898);
|
mixedPort: verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897,
|
||||||
setSocksEnabled(verge?.verge_socks_enabled ?? false);
|
socksPort: verge?.verge_socks_port ?? 7898,
|
||||||
setHttpPort(verge?.verge_port ?? 7899);
|
socksEnabled: verge?.verge_socks_enabled ?? false,
|
||||||
setHttpEnabled(verge?.verge_http_enabled ?? false);
|
httpPort: verge?.verge_port ?? 7899,
|
||||||
setRedirPort(verge?.verge_redir_port ?? 7895);
|
httpEnabled: verge?.verge_http_enabled ?? false,
|
||||||
setRedirEnabled(verge?.verge_redir_enabled ?? false);
|
redirPort: verge?.verge_redir_port ?? 7895,
|
||||||
setTproxyPort(verge?.verge_tproxy_port ?? 7896);
|
redirEnabled: verge?.verge_redir_enabled ?? false,
|
||||||
setTproxyEnabled(verge?.verge_tproxy_enabled ?? false);
|
tproxyPort: verge?.verge_tproxy_port ?? 7896,
|
||||||
|
tproxyEnabled: verge?.verge_tproxy_enabled ?? false,
|
||||||
|
};
|
||||||
|
|
||||||
|
setMixedPort(originalPortsRef.current.mixedPort);
|
||||||
|
setSocksPort(originalPortsRef.current.socksPort);
|
||||||
|
setSocksEnabled(originalPortsRef.current.socksEnabled);
|
||||||
|
setHttpPort(originalPortsRef.current.httpPort);
|
||||||
|
setHttpEnabled(originalPortsRef.current.httpEnabled);
|
||||||
|
setRedirPort(originalPortsRef.current.redirPort);
|
||||||
|
setRedirEnabled(originalPortsRef.current.redirEnabled);
|
||||||
|
setTproxyPort(originalPortsRef.current.tproxyPort);
|
||||||
|
setTproxyEnabled(originalPortsRef.current.tproxyEnabled);
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
},
|
},
|
||||||
close: () => setOpen(false),
|
close: () => setOpen(false),
|
||||||
@ -124,6 +140,47 @@ export const ClashPortViewer = forwardRef<ClashPortViewerRef>((_, ref) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const port of portList) {
|
||||||
|
try {
|
||||||
|
const inUse = await isPortInUse(port);
|
||||||
|
if (inUse) {
|
||||||
|
showNotice.error("settings.modals.clashPort.messages.portInUse", {
|
||||||
|
port,
|
||||||
|
});
|
||||||
|
const original = originalPortsRef.current;
|
||||||
|
if (original) {
|
||||||
|
setMixedPort(original.mixedPort);
|
||||||
|
setSocksPort(original.socksPort);
|
||||||
|
setSocksEnabled(original.socksEnabled);
|
||||||
|
setHttpPort(original.httpPort);
|
||||||
|
setHttpEnabled(original.httpEnabled);
|
||||||
|
setRedirPort(original.redirPort);
|
||||||
|
setRedirEnabled(original.redirEnabled);
|
||||||
|
setTproxyPort(original.tproxyPort);
|
||||||
|
setTproxyEnabled(original.tproxyEnabled);
|
||||||
|
} else {
|
||||||
|
setMixedPort(
|
||||||
|
verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897,
|
||||||
|
);
|
||||||
|
setSocksPort(verge?.verge_socks_port ?? 7898);
|
||||||
|
setSocksEnabled(verge?.verge_socks_enabled ?? false);
|
||||||
|
setHttpPort(verge?.verge_port ?? 7899);
|
||||||
|
setHttpEnabled(verge?.verge_http_enabled ?? false);
|
||||||
|
setRedirPort(verge?.verge_redir_port ?? 7895);
|
||||||
|
setRedirEnabled(verge?.verge_redir_enabled ?? false);
|
||||||
|
setTproxyPort(verge?.verge_tproxy_port ?? 7896);
|
||||||
|
setTproxyEnabled(verge?.verge_tproxy_enabled ?? false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showNotice.error("settings.modals.clashPort.messages.portCheckFailed", {
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 准备配置数据
|
// 准备配置数据
|
||||||
const clashConfig = {
|
const clashConfig = {
|
||||||
"mixed-port": mixedPort,
|
"mixed-port": mixedPort,
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import { getVersion } from "tauri-plugin-mihomo-api";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
getClashInfo,
|
getClashInfo,
|
||||||
patchClashConfig,
|
|
||||||
getRuntimeConfig,
|
getRuntimeConfig,
|
||||||
|
patchClashConfig,
|
||||||
} from "@/services/cmds";
|
} from "@/services/cmds";
|
||||||
|
|
||||||
const PORT_KEYS = [
|
const PORT_KEYS = [
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "منفذ عشوائي"
|
"random": "منفذ عشوائي"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Zufälliger Port"
|
"random": "Zufälliger Port"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Random Port"
|
"random": "Random Port"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Puerto aleatorio"
|
"random": "Puerto aleatorio"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "پورت تصادفی"
|
"random": "پورت تصادفی"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Port Acak"
|
"random": "Port Acak"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "ランダムポート"
|
"random": "ランダムポート"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "임의 포트"
|
"random": "임의 포트"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "포트 설정이 저장되었습니다",
|
"saved": "포트 설정이 저장되었습니다",
|
||||||
"saveFailed": "포트 설정 저장에 실패했습니다"
|
"saveFailed": "포트 설정 저장에 실패했습니다"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Случайный порт"
|
"random": "Случайный порт"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Rastgele Port"
|
"random": "Rastgele Port"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "Очраклы порт"
|
"random": "Очраклы порт"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "Port settings saved",
|
"saved": "Port settings saved",
|
||||||
"saveFailed": "Failed to save port settings"
|
"saveFailed": "Failed to save port settings"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "随机端口"
|
"random": "随机端口"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "端口 {{port}} 已被占用",
|
||||||
"saved": "端口设置已保存",
|
"saved": "端口设置已保存",
|
||||||
"saveFailed": "端口设置保存失败"
|
"saveFailed": "端口设置保存失败"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@
|
|||||||
"random": "隨機連接埠"
|
"random": "隨機連接埠"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"portInUse": "Port {{port}} is already in use",
|
||||||
"saved": "連結埠設定已儲存",
|
"saved": "連結埠設定已儲存",
|
||||||
"saveFailed": "連結埠設定儲存失敗"
|
"saveFailed": "連結埠設定儲存失敗"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -554,3 +554,12 @@ export const isAdmin = async () => {
|
|||||||
export async function getNextUpdateTime(uid: string) {
|
export async function getNextUpdateTime(uid: string) {
|
||||||
return invoke<number | null>("get_next_update_time", { uid });
|
return invoke<number | null>("get_next_update_time", { uid });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isPortInUse = async (port: number) => {
|
||||||
|
try {
|
||||||
|
return await invoke<boolean>("is_port_in_use", { port });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("检查端口使用状态失败:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -453,6 +453,7 @@ export const translationKeys = [
|
|||||||
"settings.modals.clashPort.fields.redir",
|
"settings.modals.clashPort.fields.redir",
|
||||||
"settings.modals.clashPort.fields.tproxy",
|
"settings.modals.clashPort.fields.tproxy",
|
||||||
"settings.modals.clashPort.actions.random",
|
"settings.modals.clashPort.actions.random",
|
||||||
|
"settings.modals.clashPort.messages.portInUse",
|
||||||
"settings.modals.clashPort.messages.saved",
|
"settings.modals.clashPort.messages.saved",
|
||||||
"settings.modals.clashPort.messages.saveFailed",
|
"settings.modals.clashPort.messages.saveFailed",
|
||||||
"settings.modals.clashCore.variants.release",
|
"settings.modals.clashCore.variants.release",
|
||||||
|
|||||||
@ -793,6 +793,7 @@ export interface TranslationResources {
|
|||||||
tproxy: string;
|
tproxy: string;
|
||||||
};
|
};
|
||||||
messages: {
|
messages: {
|
||||||
|
portInUse: string;
|
||||||
saved: string;
|
saved: string;
|
||||||
saveFailed: string;
|
saveFailed: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user