Compare commits

..

3 Commits

Author SHA1 Message Date
ezequielnick
2ebb5db055 chore: update log 2025-08-20 20:06:37 +08:00
ezequielnick
4325c77b4c fix: default tun device name doesn't work 2025-08-20 20:06:24 +08:00
zengql
d6b88d407c
feat: 修复权限检查并优化TUN与自启联动 (#977)
1. 修复管理员权限检查不准导致TUN无法开启的问题
   - 增加 'fltmc' 命令作为主要判断,'net session' 作为备用,提高在特定环境下的准确性。

2. 优化自启动以自动保持TUN模式开启
   - 设置自启动时,根据当前运行身份决定任务权限。
   - 为TUN模式提权而重启后,若自启已开启,则自动将计划任务更新为管理员权限。
   - 普通权限启动但TUN开启时,主动提示用户需以管理员身份重启。
2025-08-20 20:01:09 +08:00
7 changed files with 71 additions and 21 deletions

View File

@ -1,3 +1,20 @@
## 1.8.5
### 新功能 (Feat)
- 支持 cron 表达式以自定义订阅更新频率(#766)
- 修复权限检查并优化TUN与自启联动(#977)
### 修复 (Fix)
- Windows 下当前运行内核权限检测(之前没有正确检测管理员权限运行的内核)
- Windows 下 开机自启 按钮卡顿问题 隐藏运行黑框 现在申请权限会弹通知
- 修复 部分情况下 yaml 文件解析错误 (#889)
- 修复 系统中已经运行的内核名称检测
- 修复 订阅信息中的因格式问题导致的信息缺失(#951)
- 修复 轻量模式延迟启动延时输入数值问题(#962)
- 修复 轻量模式下轻量模式下规则失效的问题(#963)
- 修复 MacOS 下默认虚拟网卡名称没有生效的问题
### 样式调整 (Sytle)
- 部分样式微调
## 1.8.4 ## 1.8.4
### 新功能 (Feat) ### 新功能 (Feat)

View File

@ -1,6 +1,6 @@
{ {
"name": "mihomo-party", "name": "mihomo-party",
"version": "1.8.4", "version": "1.8.5-dev",
"description": "Mihomo Party", "description": "Mihomo Party",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "mihomo-party-org", "author": "mihomo-party-org",

View File

@ -38,10 +38,6 @@ export async function patchControledMihomoConfig(patch: Partial<IMihomoConfig>):
controledMihomoConfig.sniffer = defaultControledMihomoConfig.sniffer controledMihomoConfig.sniffer = defaultControledMihomoConfig.sniffer
} }
if (process.platform === 'darwin') {
delete controledMihomoConfig?.tun?.device
}
await generateProfile() await generateProfile()
await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8') await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8')
} }

View File

@ -290,13 +290,7 @@ export async function checkTunPermissions(): Promise<boolean> {
try { try {
if (process.platform === 'win32') { if (process.platform === 'win32') {
const execPromise = promisify(exec) return await checkAdminPrivileges()
try {
await execPromise('net session')
return true
} catch {
return false
}
} }
if (process.platform === 'darwin' || process.platform === 'linux') { if (process.platform === 'darwin' || process.platform === 'linux') {
@ -341,13 +335,26 @@ export async function checkAdminPrivileges(): Promise<boolean> {
return true return true
} }
try {
const execPromise = promisify(exec) const execPromise = promisify(exec)
await execPromise('net session')
try {
// 首先尝试 fltmc 命令检测管理员权限
await execPromise('fltmc')
await managerLogger.info('Admin privileges confirmed via fltmc')
return true return true
} catch { } catch (fltmcError) {
await managerLogger.info('fltmc failed, trying net session as fallback', fltmcError)
try {
// 如果 fltmc 失败,尝试 net session 命令作为备用检测方法
await execPromise('net session')
await managerLogger.info('Admin privileges confirmed via net session')
return true
} catch (netSessionError) {
await managerLogger.info('Both fltmc and net session failed, no admin privileges', netSessionError)
return false return false
} }
}
} }
// TUN 权限确认框 // TUN 权限确认框
@ -604,6 +611,13 @@ export async function checkAdminRestartForTun(): Promise<void> {
const hasAdminPrivileges = await checkAdminPrivileges() const hasAdminPrivileges = await checkAdminPrivileges()
if (hasAdminPrivileges) { if (hasAdminPrivileges) {
await patchControledMihomoConfig({ tun: { enable: true }, dns: { enable: true } }) await patchControledMihomoConfig({ tun: { enable: true }, dns: { enable: true } })
const { checkAutoRun, enableAutoRun } = await import('../sys/autoRun')
const autoRunEnabled = await checkAutoRun()
if (autoRunEnabled) {
await enableAutoRun()
}
await restartCore() await restartCore()
await managerLogger.info('TUN mode auto-enabled after admin restart') await managerLogger.info('TUN mode auto-enabled after admin restart')
@ -635,8 +649,16 @@ export async function validateTunPermissionsOnStartup(): Promise<void> {
const hasPermissions = await checkMihomoCorePermissions() const hasPermissions = await checkMihomoCorePermissions()
if (!hasPermissions) { if (!hasPermissions) {
await managerLogger.warn('TUN is enabled but insufficient permissions detected, auto-disabling TUN...') await managerLogger.warn(
'TUN is enabled but insufficient permissions detected, prompting user...'
)
const confirmed = await showTunPermissionDialog()
if (confirmed) {
await restartAsAdmin()
return
}
await managerLogger.warn('User declined admin restart, auto-disabling TUN...')
await patchControledMihomoConfig({ tun: { enable: false } }) await patchControledMihomoConfig({ tun: { enable: false } })
const { mainWindow } = await import('../index') const { mainWindow } = await import('../index')

View File

@ -9,7 +9,8 @@ import { managerLogger } from '../utils/logger'
const appName = 'mihomo-party' const appName = 'mihomo-party'
function getTaskXml(): string { function getTaskXml(asAdmin: boolean): string {
const runLevel = asAdmin ? 'HighestAvailable' : 'LeastPrivilege'
return `<?xml version="1.0" encoding="UTF-16"?> return `<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Triggers> <Triggers>
@ -21,7 +22,7 @@ function getTaskXml(): string {
<Principals> <Principals>
<Principal id="Author"> <Principal id="Author">
<LogonType>InteractiveToken</LogonType> <LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel> <RunLevel>${runLevel}</RunLevel>
</Principal> </Principal>
</Principals> </Principals>
<Settings> <Settings>
@ -83,9 +84,9 @@ export async function enableAutoRun(): Promise<void> {
if (process.platform === 'win32') { if (process.platform === 'win32') {
const execPromise = promisify(exec) const execPromise = promisify(exec)
const taskFilePath = path.join(tmpdir(), `${appName}.xml`) const taskFilePath = path.join(tmpdir(), `${appName}.xml`)
await writeFile(taskFilePath, Buffer.from(`\ufeff${getTaskXml()}`, 'utf-16le'))
const { checkAdminPrivileges } = await import('../core/manager') const { checkAdminPrivileges } = await import('../core/manager')
const isAdmin = await checkAdminPrivileges() const isAdmin = await checkAdminPrivileges()
await writeFile(taskFilePath, Buffer.from(`\ufeff${getTaskXml(isAdmin)}`, 'utf-16le'))
if (isAdmin) { if (isAdmin) {
await execPromise(`%SystemRoot%\\System32\\schtasks.exe /create /tn "${appName}" /xml "${taskFilePath}" /f`) await execPromise(`%SystemRoot%\\System32\\schtasks.exe /create /tn "${appName}" /xml "${taskFilePath}" /f`)
} else { } else {

View File

@ -250,7 +250,8 @@ async function migration(): Promise<void> {
authentication, authentication,
'bind-address': bindAddress, 'bind-address': bindAddress,
'lan-allowed-ips': lanAllowedIps, 'lan-allowed-ips': lanAllowedIps,
'lan-disallowed-ips': lanDisallowedIps 'lan-disallowed-ips': lanDisallowedIps,
tun
} = await getControledMihomoConfig() } = await getControledMihomoConfig()
// add substore sider card // add substore sider card
if (useSubStore && !siderOrder.includes('substore')) { if (useSubStore && !siderOrder.includes('substore')) {
@ -276,6 +277,16 @@ async function migration(): Promise<void> {
if (!lanDisallowedIps) { if (!lanDisallowedIps) {
await patchControledMihomoConfig({ 'lan-disallowed-ips': [] }) await patchControledMihomoConfig({ 'lan-disallowed-ips': [] })
} }
// default tun device
if (!tun?.device || (process.platform === 'darwin' && tun.device === 'Mihomo')) {
const defaultDevice = process.platform === 'darwin' ? 'utun1500' : 'Mihomo'
await patchControledMihomoConfig({
tun: {
...tun,
device: defaultDevice
}
})
}
// remove custom app theme // remove custom app theme
if (!['system', 'light', 'dark'].includes(appTheme)) { if (!['system', 'light', 'dark'].includes(appTheme)) {
await patchAppConfig({ appTheme: 'system' }) await patchAppConfig({ appTheme: 'system' })

View File

@ -75,6 +75,9 @@ const TunSwitcher: React.FC<Props> = (props) => {
} }
await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } }) await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } })
if (enable && appConfig?.silentStart) {
await window.electron.ipcRenderer.invoke('enableAutoRun')
}
} else { } else {
await patchControledMihomoConfig({ tun: { enable } }) await patchControledMihomoConfig({ tun: { enable } })
} }