fix: dns/sniffer override logic

This commit is contained in:
ezequielnick 2025-08-06 17:21:51 +08:00
parent 73161d0cc2
commit 45484ffff2
7 changed files with 60 additions and 37 deletions

View File

@ -20,23 +20,7 @@ export async function getControledMihomoConfig(force = false): Promise<Partial<I
export async function patchControledMihomoConfig(patch: Partial<IMihomoConfig>): Promise<void> { export async function patchControledMihomoConfig(patch: Partial<IMihomoConfig>): Promise<void> {
const { useNameserverPolicy, controlDns = true, controlSniff = true } = await getAppConfig() const { useNameserverPolicy, controlDns = true, controlSniff = true } = await getAppConfig()
if (!controlDns) {
delete controledMihomoConfig.dns
delete controledMihomoConfig.hosts
} else {
// 从不接管状态恢复
if (controledMihomoConfig.dns?.ipv6 === undefined) {
controledMihomoConfig.dns = defaultControledMihomoConfig.dns
}
}
if (!controlSniff) {
delete controledMihomoConfig.sniffer
} else {
// 从不接管状态恢复
if (!controledMihomoConfig.sniffer) {
controledMihomoConfig.sniffer = defaultControledMihomoConfig.sniffer
}
}
if (patch.hosts) { if (patch.hosts) {
controledMihomoConfig.hosts = patch.hosts controledMihomoConfig.hosts = patch.hosts
} }
@ -45,12 +29,37 @@ export async function patchControledMihomoConfig(patch: Partial<IMihomoConfig>):
controledMihomoConfig.dns['nameserver-policy'] = patch.dns['nameserver-policy'] controledMihomoConfig.dns['nameserver-policy'] = patch.dns['nameserver-policy']
} }
controledMihomoConfig = deepMerge(controledMihomoConfig, patch) controledMihomoConfig = deepMerge(controledMihomoConfig, patch)
// 覆写开关控制
let configForProfile = { ...controledMihomoConfig }
if (!controlDns) {
delete configForProfile.dns
delete configForProfile.hosts
} else {
if (configForProfile.dns?.ipv6 === undefined) {
configForProfile.dns = defaultControledMihomoConfig.dns
}
}
if (!controlSniff) {
delete configForProfile.sniffer
} else {
if (!configForProfile.sniffer) {
configForProfile.sniffer = defaultControledMihomoConfig.sniffer
}
}
if (!useNameserverPolicy) { if (!useNameserverPolicy) {
delete controledMihomoConfig?.dns?.['nameserver-policy'] delete configForProfile?.dns?.['nameserver-policy']
} }
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
delete controledMihomoConfig?.tun?.device delete configForProfile?.tun?.device
} }
const originalConfig = controledMihomoConfig
controledMihomoConfig = configForProfile
await generateProfile() await generateProfile()
controledMihomoConfig = originalConfig
await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8') await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8')
} }

View File

@ -285,6 +285,7 @@
"sniffer.skipDstAddress.placeholder": "Example: 1.1.1.1/32", "sniffer.skipDstAddress.placeholder": "Example: 1.1.1.1/32",
"sniffer.skipSrcAddress.title": "Skip Source Address Sniffing", "sniffer.skipSrcAddress.title": "Skip Source Address Sniffing",
"sniffer.skipSrcAddress.placeholder": "Example: 192.168.1.1/24", "sniffer.skipSrcAddress.placeholder": "Example: 192.168.1.1/24",
"sniffer.saveOnly": "Save Only",
"sysproxy.title": "System Proxy", "sysproxy.title": "System Proxy",
"sysproxy.host.title": "Proxy Host", "sysproxy.host.title": "Proxy Host",
"sysproxy.host.placeholder": "Default 127.0.0.1, do not modify unless necessary", "sysproxy.host.placeholder": "Default 127.0.0.1, do not modify unless necessary",
@ -343,6 +344,7 @@
"dns.customHosts.list": "Hosts List", "dns.customHosts.list": "Hosts List",
"dns.customHosts.domainPlaceholder": "Domain", "dns.customHosts.domainPlaceholder": "Domain",
"dns.customHosts.valuePlaceholder": "Domain or IP", "dns.customHosts.valuePlaceholder": "Domain or IP",
"dns.saveOnly": "Save Only",
"profiles.title": "Profile Management", "profiles.title": "Profile Management",
"profiles.updateAll": "Update All Profiles", "profiles.updateAll": "Update All Profiles",
"profiles.useProxy": "Proxy", "profiles.useProxy": "Proxy",

View File

@ -276,6 +276,7 @@
"sniffer.skipDstAddress.placeholder": "مثال: 1.1.1.1/32", "sniffer.skipDstAddress.placeholder": "مثال: 1.1.1.1/32",
"sniffer.skipSrcAddress.title": "رد کردن تشخیص آدرس مبدا", "sniffer.skipSrcAddress.title": "رد کردن تشخیص آدرس مبدا",
"sniffer.skipSrcAddress.placeholder": "مثال: 192.168.1.1/24", "sniffer.skipSrcAddress.placeholder": "مثال: 192.168.1.1/24",
"sniffer.saveOnly": "فقط ذخیره",
"sysproxy.title": "پراکسی سیستم", "sysproxy.title": "پراکسی سیستم",
"sysproxy.host.title": "میزبان پراکسی", "sysproxy.host.title": "میزبان پراکسی",
"sysproxy.host.placeholder": "پیش‌فرض 127.0.0.1، در صورت عدم نیاز تغییر ندهید", "sysproxy.host.placeholder": "پیش‌فرض 127.0.0.1، در صورت عدم نیاز تغییر ندهید",
@ -334,6 +335,7 @@
"dns.customHosts.list": "لیست Hosts", "dns.customHosts.list": "لیست Hosts",
"dns.customHosts.domainPlaceholder": "دامنه", "dns.customHosts.domainPlaceholder": "دامنه",
"dns.customHosts.valuePlaceholder": "دامنه یا IP", "dns.customHosts.valuePlaceholder": "دامنه یا IP",
"dns.saveOnly": "فقط ذخیره",
"profiles.title": "مدیریت پروفایل", "profiles.title": "مدیریت پروفایل",
"profiles.updateAll": "به‌روزرسانی همه پروفایل‌ها", "profiles.updateAll": "به‌روزرسانی همه پروفایل‌ها",
"profiles.useProxy": "پراکسی", "profiles.useProxy": "پراکسی",

View File

@ -276,6 +276,7 @@
"sniffer.skipDstAddress.placeholder": "Пример: 1.1.1.1/32", "sniffer.skipDstAddress.placeholder": "Пример: 1.1.1.1/32",
"sniffer.skipSrcAddress.title": "Пропустить анализ исходных адресов", "sniffer.skipSrcAddress.title": "Пропустить анализ исходных адресов",
"sniffer.skipSrcAddress.placeholder": "Пример: 192.168.1.1/24", "sniffer.skipSrcAddress.placeholder": "Пример: 192.168.1.1/24",
"sniffer.saveOnly": "Только сохранить",
"sysproxy.title": "Системный прокси", "sysproxy.title": "Системный прокси",
"sysproxy.host.title": "Хост прокси", "sysproxy.host.title": "Хост прокси",
"sysproxy.host.placeholder": "По умолчанию 127.0.0.1, не изменяйте без необходимости", "sysproxy.host.placeholder": "По умолчанию 127.0.0.1, не изменяйте без необходимости",
@ -334,6 +335,7 @@
"dns.customHosts.list": "Список Hosts", "dns.customHosts.list": "Список Hosts",
"dns.customHosts.domainPlaceholder": "Домен", "dns.customHosts.domainPlaceholder": "Домен",
"dns.customHosts.valuePlaceholder": "Домен или IP", "dns.customHosts.valuePlaceholder": "Домен или IP",
"dns.saveOnly": "Только сохранить",
"profiles.title": "Управление профилями", "profiles.title": "Управление профилями",
"profiles.updateAll": "Обновить все профили", "profiles.updateAll": "Обновить все профили",
"profiles.useProxy": "Прокси", "profiles.useProxy": "Прокси",

View File

@ -285,6 +285,7 @@
"sniffer.skipDstAddress.placeholder": "例1.1.1.1/32", "sniffer.skipDstAddress.placeholder": "例1.1.1.1/32",
"sniffer.skipSrcAddress.title": "跳过来源地址嗅探", "sniffer.skipSrcAddress.title": "跳过来源地址嗅探",
"sniffer.skipSrcAddress.placeholder": "例192.168.1.1/24", "sniffer.skipSrcAddress.placeholder": "例192.168.1.1/24",
"sniffer.saveOnly": "仅保存",
"sysproxy.title": "系统代理", "sysproxy.title": "系统代理",
"sysproxy.host.title": "代理主机", "sysproxy.host.title": "代理主机",
"sysproxy.host.placeholder": "默认 127.0.0.1 若无特殊需求请勿修改", "sysproxy.host.placeholder": "默认 127.0.0.1 若无特殊需求请勿修改",
@ -343,6 +344,7 @@
"dns.customHosts.list": "Hosts 列表", "dns.customHosts.list": "Hosts 列表",
"dns.customHosts.domainPlaceholder": "域名", "dns.customHosts.domainPlaceholder": "域名",
"dns.customHosts.valuePlaceholder": "域名或 IP", "dns.customHosts.valuePlaceholder": "域名或 IP",
"dns.saveOnly": "仅保存",
"profiles.title": "订阅管理", "profiles.title": "订阅管理",
"profiles.updateAll": "更新全部订阅", "profiles.updateAll": "更新全部订阅",
"profiles.useProxy": "代理", "profiles.useProxy": "代理",

View File

@ -13,7 +13,7 @@ const DNS: React.FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig() const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
const { appConfig, patchAppConfig } = useAppConfig() const { appConfig, patchAppConfig } = useAppConfig()
const { nameserverPolicy, useNameserverPolicy } = appConfig || {} const { nameserverPolicy, useNameserverPolicy, controlDns = true } = appConfig || {}
const { dns, hosts } = controledMihomoConfig || {} const { dns, hosts } = controledMihomoConfig || {}
const { const {
enable = true, enable = true,
@ -128,8 +128,10 @@ const DNS: React.FC = () => {
try { try {
setChanged(false) setChanged(false)
await patchControledMihomoConfig(patch) await patchControledMihomoConfig(patch)
await patchMihomoConfig(patch) if (controlDns) {
await restartCore() await patchMihomoConfig(patch)
await restartCore()
}
} catch (e) { } catch (e) {
alert(e) alert(e)
} }
@ -175,7 +177,7 @@ const DNS: React.FC = () => {
onSave(result) onSave(result)
}} }}
> >
{t('common.save')} {controlDns ? t('common.save') : t('dns.saveOnly')}
</Button> </Button>
) )
} }

View File

@ -3,7 +3,8 @@ import BasePage from '@renderer/components/base/base-page'
import SettingCard from '@renderer/components/base/base-setting-card' import SettingCard from '@renderer/components/base/base-setting-card'
import SettingItem from '@renderer/components/base/base-setting-item' import SettingItem from '@renderer/components/base/base-setting-item'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config' import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import { restartCore } from '@renderer/utils/ipc' import { useAppConfig } from '@renderer/hooks/use-app-config'
import { restartCore, patchMihomoConfig } from '@renderer/utils/ipc'
import React, { ReactNode, useState } from 'react' import React, { ReactNode, useState } from 'react'
import { MdDeleteForever } from 'react-icons/md' import { MdDeleteForever } from 'react-icons/md'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -11,6 +12,8 @@ import { useTranslation } from 'react-i18next'
const Sniffer: React.FC = () => { const Sniffer: React.FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig() const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
const { appConfig } = useAppConfig()
const { controlSniff = true } = appConfig || {}
const { sniffer } = controledMihomoConfig || {} const { sniffer } = controledMihomoConfig || {}
const { const {
enable = true, enable = true,
@ -42,6 +45,7 @@ const Sniffer: React.FC = () => {
} = sniffer || {} } = sniffer || {}
const [changed, setChanged] = useState(false) const [changed, setChanged] = useState(false)
const [values, originSetValues] = useState({ const [values, originSetValues] = useState({
enable,
parsePureIP, parsePureIP,
forceDNSMapping, forceDNSMapping,
overrideDestination, overrideDestination,
@ -60,16 +64,11 @@ const Sniffer: React.FC = () => {
try { try {
setChanged(false) setChanged(false)
await patchControledMihomoConfig(patch) await patchControledMihomoConfig(patch)
await restartCore()
} catch (e) {
alert(e)
}
}
const onEnableChange = async (enable: boolean): Promise<void> => { if (controlSniff) {
try { await patchMihomoConfig(patch)
await patchControledMihomoConfig({ sniffer: { enable } }) await restartCore()
await restartCore() }
} catch (e) { } catch (e) {
alert(e) alert(e)
} }
@ -140,17 +139,20 @@ const Sniffer: React.FC = () => {
onPress={() => onPress={() =>
onSave({ onSave({
sniffer: { sniffer: {
enable: values.enable,
'parse-pure-ip': values.parsePureIP, 'parse-pure-ip': values.parsePureIP,
'force-dns-mapping': values.forceDNSMapping, 'force-dns-mapping': values.forceDNSMapping,
'override-destination': values.overrideDestination, 'override-destination': values.overrideDestination,
sniff: values.sniff, sniff: values.sniff,
'skip-domain': values.skipDomain, 'skip-domain': values.skipDomain,
'force-domain': values.forceDomain 'force-domain': values.forceDomain,
'skip-dst-address': values.skipDstAddress,
'skip-src-address': values.skipSrcAddress
} }
}) })
} }
> >
{t('common.save')} {controlSniff ? t('common.save') : t('sniffer.saveOnly')}
</Button> </Button>
) )
} }
@ -159,8 +161,10 @@ const Sniffer: React.FC = () => {
<SettingItem title={t('sniffer.enable')} divider> <SettingItem title={t('sniffer.enable')} divider>
<Switch <Switch
size="sm" size="sm"
isSelected={enable} isSelected={values.enable}
onValueChange={onEnableChange} onValueChange={(v) => {
setValues({ ...values, enable: v })
}}
/> />
</SettingItem> </SettingItem>
<SettingItem title={t('sniffer.overrideDestination')} divider> <SettingItem title={t('sniffer.overrideDestination')} divider>