Skip to content

Commit e574cd9

Browse files
committed
feat: configure system DNS with core lifecycle
1 parent ce10d82 commit e574cd9

13 files changed

Lines changed: 255 additions & 48 deletions

File tree

bridge/system_proxy.go

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func (a *App) GetSystemProxy() FlagResult {
3535
return FlagResult{true, proxy}
3636
}
3737

38-
func (a *App) SetSystemProxy(enable bool, server string, proxyType string, bypass string, darwinServices []string) FlagResult {
39-
log.Printf("SetSystemProxy: %t %s %s %s %v", enable, server, proxyType, bypass, darwinServices)
38+
func (a *App) SetSystemProxy(enable bool, server string, proxyType string, bypass string, services []string) FlagResult {
39+
log.Printf("SetSystemProxy: %t %s %s %s %v", enable, server, proxyType, bypass, services)
4040

4141
if proxyType == "" {
4242
proxyType = "mixed"
@@ -48,7 +48,7 @@ func (a *App) SetSystemProxy(enable bool, server string, proxyType string, bypas
4848
case "windows":
4949
err = setWindowsSystemProxy(server, enable, proxyType, bypass)
5050
case "darwin":
51-
err = setDarwinSystemProxy(server, enable, proxyType, bypass, darwinServices)
51+
err = setDarwinSystemProxy(server, enable, proxyType, bypass, services)
5252
case "linux":
5353
err = setLinuxSystemProxy(server, enable, proxyType, bypass)
5454
}
@@ -60,6 +60,25 @@ func (a *App) SetSystemProxy(enable bool, server string, proxyType string, bypas
6060
return FlagResult{true, "Success"}
6161
}
6262

63+
func (a *App) SetSystemDNS(servers string, services []string) FlagResult {
64+
log.Printf("SetSystemDNS: %s %v", servers, services)
65+
66+
var err error
67+
switch Env.OS {
68+
case "darwin":
69+
err = setDarwinSystemDNS(servers, services)
70+
case "linux":
71+
err = setLinuxSystemDNS(servers, services)
72+
default:
73+
return FlagResult{true, "Success"}
74+
}
75+
76+
if err != nil {
77+
return FlagResult{false, err.Error()}
78+
}
79+
return FlagResult{true, "Success"}
80+
}
81+
6382
func (a *App) GetSystemProxyBypass() FlagResult {
6483
log.Printf("GetSystemProxyBypass")
6584

@@ -347,6 +366,59 @@ func setLinuxSystemProxy(server string, enabled bool, proxyType string, bypass s
347366
}
348367
}
349368

369+
func setDarwinSystemDNS(servers string, services []string) error {
370+
dnsServers := splitCommaSeparated(servers)
371+
if len(dnsServers) == 0 {
372+
dnsServers = []string{"Empty"}
373+
}
374+
375+
commands := make([][]string, 0, len(services))
376+
for _, service := range services {
377+
service = strings.TrimSpace(service)
378+
if service == "" {
379+
continue
380+
}
381+
commands = append(commands, append([]string{"networksetup", "-setdnsservers", service}, dnsServers...))
382+
}
383+
return runSystemProxyCommands(commands...)
384+
}
385+
386+
func setLinuxSystemDNS(servers string, services []string) error {
387+
dnsServers := splitCommaSeparated(servers)
388+
ipv4Servers := make([]string, 0, len(dnsServers))
389+
ipv6Servers := make([]string, 0, len(dnsServers))
390+
for _, server := range dnsServers {
391+
if strings.Contains(server, ":") {
392+
ipv6Servers = append(ipv6Servers, server)
393+
} else {
394+
ipv4Servers = append(ipv4Servers, server)
395+
}
396+
}
397+
ignoreAutoDNS := "yes"
398+
if len(dnsServers) == 0 {
399+
ignoreAutoDNS = "no"
400+
}
401+
402+
for _, service := range services {
403+
service = strings.TrimSpace(service)
404+
if service == "" {
405+
continue
406+
}
407+
_, err := runSystemProxyCommand(
408+
"nmcli", "connection", "modify", service,
409+
"ipv4.ignore-auto-dns", ignoreAutoDNS, "ipv4.dns", strings.Join(ipv4Servers, ","),
410+
"ipv6.ignore-auto-dns", ignoreAutoDNS, "ipv6.dns", strings.Join(ipv6Servers, ","),
411+
)
412+
if err != nil {
413+
return err
414+
}
415+
if _, err := runSystemProxyCommand("nmcli", "connection", "up", service); err != nil {
416+
return err
417+
}
418+
}
419+
return nil
420+
}
421+
350422
func getWindowsSystemProxyBypass() (string, error) {
351423
out, err := runSystemProxyCommand("reg", "query", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyOverride")
352424
if err != nil {
@@ -483,6 +555,17 @@ func splitBypass(bypass string) []string {
483555
return result
484556
}
485557

558+
func splitCommaSeparated(value string) []string {
559+
result := []string{}
560+
for item := range strings.SplitSeq(value, ",") {
561+
item = strings.TrimSpace(item)
562+
if item != "" {
563+
result = append(result, item)
564+
}
565+
}
566+
return result
567+
}
568+
486569
func normalizeBypass(bypass string, separator string) string {
487570
return strings.Join(splitBypass(bypass), separator)
488571
}

frontend/src/bridge/app.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@ export const SetSystemProxy = async (
4242
server: string,
4343
proxyType: 'mixed' | 'http' | 'socks' = 'mixed',
4444
bypass = '',
45-
darwinServices: string[] = [],
45+
services: string[] = [],
4646
) => {
47-
const { flag, data } = await App.SetSystemProxy(enable, server, proxyType, bypass, darwinServices)
47+
const { flag, data } = await App.SetSystemProxy(enable, server, proxyType, bypass, services)
48+
if (!flag) {
49+
throw data
50+
}
51+
return data
52+
}
53+
54+
export const SetSystemDNS = async (servers: string, services: string[] = []) => {
55+
const { flag, data } = await App.SetSystemDNS(servers, services)
4856
if (!flag) {
4957
throw data
5058
}

frontend/src/bridge/wailsjs/go/bridge/App.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ export function Requests(arg1:string,arg2:string,arg3:Record<string, string>,arg
6060

6161
export function RestartApp():Promise<bridge.FlagResult>;
6262

63+
export function SetSystemDNS(arg1:string,arg2:Array<string>):Promise<bridge.FlagResult>;
64+
6365
export function SetSystemProxy(arg1:boolean,arg2:string,arg3:string,arg4:string,arg5:Array<string>):Promise<bridge.FlagResult>;
6466

6567
export function ShowMainWindow():Promise<void>;

frontend/src/bridge/wailsjs/go/bridge/App.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ export function RestartApp() {
118118
return window['go']['bridge']['App']['RestartApp']();
119119
}
120120

121+
export function SetSystemDNS(arg1, arg2) {
122+
return window['go']['bridge']['App']['SetSystemDNS'](arg1, arg2);
123+
}
124+
121125
export function SetSystemProxy(arg1, arg2, arg3, arg4, arg5) {
122126
return window['go']['bridge']['App']['SetSystemProxy'](arg1, arg2, arg3, arg4, arg5);
123127
}

frontend/src/lang/locale/en.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,11 @@ export default {
679679
},
680680
proxyBypassList: 'Proxy Bypass List',
681681
proxyBypassListTips: 'Separate with semicolons',
682-
darwinSystemProxyServices: 'Proxy Network Service Names',
682+
systemProxyServices: 'Network Service Names',
683+
autoSetSystemDNS: 'Auto-configure System DNS',
684+
autoSetSystemDNSTips: 'Used for DNS hijacking in TUN mode',
685+
systemProxyDNS: 'DNS While Core Is Running',
686+
systemDefaultDNS: 'DNS While Core Is Stopped',
683687
autoStartKernel: 'Start core on launch',
684688
realMemoryUsage: 'Show actual core memory usage',
685689
autoRestartKernel: {

frontend/src/lang/locale/zh.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,11 @@ export default {
678678
},
679679
proxyBypassList: '不使用代理的地址',
680680
proxyBypassListTips: '分号分隔',
681-
darwinSystemProxyServices: '代理网络服务名称',
681+
systemProxyServices: '网络服务名称',
682+
autoSetSystemDNS: '自动配置系统 DNS',
683+
autoSetSystemDNSTips: '用于 TUN 模式劫持 DNS',
684+
systemProxyDNS: '核心运行时的主备 DNS 服务器',
685+
systemDefaultDNS: '核心停止时的主备 DNS 服务器',
682686
autoStartKernel: '程序启动时开启核心',
683687
realMemoryUsage: '显示真实的核心内存占用',
684688
autoRestartKernel: {

frontend/src/stores/appSettings.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,7 @@ import {
3535
} from '@/enums/app'
3636
import i18n, { loadLocale } from '@/lang'
3737
import { useAppStore, useEnvStore } from '@/stores'
38-
import {
39-
debounce,
40-
updateTrayAndMenus,
41-
ignoredError,
42-
deepClone,
43-
} from '@/utils'
38+
import { debounce, updateTrayAndMenus, ignoredError, deepClone, message } from '@/utils'
4439

4540
import type { AppSettings } from '@/types/app'
4641

@@ -70,10 +65,13 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
7065
exitOnClose: true,
7166
closeKernelOnExit: true,
7267
autoSetSystemProxy: true,
68+
autoSetSystemDNS: false,
7369
requestProxyMode: RequestProxyMode.System,
7470
customProxy: '',
7571
proxyBypassList: '',
76-
darwinSystemProxyServices: ['Ethernet', 'Wi-Fi'],
72+
systemProxyServices: [],
73+
systemProxyDNS: '',
74+
systemDefaultDNS: '',
7775
autoStartKernel: false,
7876
autoRestartKernel: false,
7977
userAgent: '',
@@ -137,8 +135,29 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
137135
if (!settings.proxyBypassList) {
138136
settings.proxyBypassList = (await ignoredError(GetSystemProxyBypass)) || ''
139137
}
140-
if (!settings.darwinSystemProxyServices) {
141-
settings.darwinSystemProxyServices = ['Ethernet', 'Wi-Fi']
138+
if ('darwinSystemProxyServices' in settings) {
139+
settings.systemProxyServices = settings.darwinSystemProxyServices as string[]
140+
delete settings.darwinSystemProxyServices
141+
}
142+
const defaultSystemProxyServices = envStore.env.os === 'darwin' ? ['Ethernet', 'Wi-Fi'] : []
143+
if (!data) {
144+
settings.systemProxyServices = defaultSystemProxyServices
145+
} else if (!settings.systemProxyServices) {
146+
settings.systemProxyServices = defaultSystemProxyServices
147+
} else if (
148+
envStore.env.os === 'linux' &&
149+
settings.systemProxyServices.join(',') === 'Ethernet,Wi-Fi'
150+
) {
151+
settings.systemProxyServices = defaultSystemProxyServices
152+
}
153+
if (settings.autoSetSystemDNS === undefined) {
154+
settings.autoSetSystemDNS = false
155+
}
156+
if (settings.systemProxyDNS === undefined) {
157+
settings.systemProxyDNS = ''
158+
}
159+
if (settings.systemDefaultDNS === undefined) {
160+
settings.systemDefaultDNS = ''
142161
}
143162
if (!settings.requestProxyMode) {
144163
settings.requestProxyMode = RequestProxyMode.System
@@ -209,7 +228,12 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
209228
},
210229
systemProxyBypass() {
211230
if (envStore.systemProxy) {
212-
envStore.setSystemProxy()
231+
envStore.setSystemProxy().catch((err) => message.error(err))
232+
}
233+
},
234+
systemDNS() {
235+
if (app.value.autoSetSystemDNS) {
236+
envStore.setSystemDNS(envStore.systemDNSSet).catch((err) => message.error(err))
213237
}
214238
},
215239
}
@@ -285,7 +309,16 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
285309
const setSystemProxyBypass = debounce(() => {
286310
applyAppSettings.systemProxyBypass()
287311
}, 3000)
288-
watch(() => [app.value.proxyBypassList, app.value.darwinSystemProxyServices], setSystemProxyBypass)
312+
watch(() => [app.value.proxyBypassList, app.value.systemProxyServices], setSystemProxyBypass)
313+
314+
/* Apply SystemDNS */
315+
const setSystemDNS = debounce(() => {
316+
applyAppSettings.systemDNS()
317+
}, 3000)
318+
watch(
319+
() => [app.value.systemProxyServices, app.value.systemProxyDNS, app.value.systemDefaultDNS],
320+
setSystemDNS,
321+
)
289322

290323
return { setupAppSettings, app, themeMode }
291324
})

frontend/src/stores/env.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { defineStore } from 'pinia'
22
import { ref, watch } from 'vue'
33

4-
import { GetEnv, GetSystemProxy, SetSystemProxy } from '@/bridge'
4+
import { GetEnv, GetSystemProxy, SetSystemDNS, SetSystemProxy } from '@/bridge'
55
import { OS } from '@/enums/app'
66
import { useAppSettingsStore, useKernelApiStore } from '@/stores'
77
import { formatProxyHost, ignoredError, updateTrayAndMenus } from '@/utils'
@@ -23,6 +23,7 @@ export const useEnvStore = defineStore('env', () => {
2323
})
2424

2525
const systemProxy = ref(false)
26+
const systemDNSSet = ref(false)
2627

2728
const setupEnv = async () => {
2829
const _env = await GetEnv()
@@ -67,22 +68,22 @@ export const useEnvStore = defineStore('env', () => {
6768

6869
const setSystemProxy = async () => {
6970
const proxyBypassList = appSettings.app.proxyBypassList
70-
const darwinServices = appSettings.app.darwinSystemProxyServices
71+
const services = appSettings.app.systemProxyServices
7172
let proxyEndpoint = kernelApiStore.getProxyEndpoint()
7273
if (!proxyEndpoint) {
7374
await kernelApiStore.updateConfig('inbound', undefined)
7475
}
7576
proxyEndpoint = kernelApiStore.getProxyEndpoint()
7677
if (!proxyEndpoint) throw 'home.overview.needPort'
7778
const server = `${formatProxyHost(proxyEndpoint.host)}:${proxyEndpoint.port}`
78-
await SetSystemProxy(true, server, proxyEndpoint.proxyType, proxyBypassList, darwinServices)
79+
await SetSystemProxy(true, server, proxyEndpoint.proxyType, proxyBypassList, services)
7980
systemProxy.value = true
8081
}
8182

8283
const clearSystemProxy = async () => {
8384
const proxyBypassList = appSettings.app.proxyBypassList
84-
const darwinServices = appSettings.app.darwinSystemProxyServices
85-
await SetSystemProxy(false, '', undefined, proxyBypassList, darwinServices)
85+
const services = appSettings.app.systemProxyServices
86+
await SetSystemProxy(false, '', undefined, proxyBypassList, services)
8687
systemProxy.value = false
8788
}
8889

@@ -91,15 +92,24 @@ export const useEnvStore = defineStore('env', () => {
9192
else await clearSystemProxy()
9293
}
9394

95+
const setSystemDNS = async (proxy: boolean) => {
96+
if (![OS.Linux, OS.Darwin].includes(env.value.os)) return
97+
const servers = proxy ? appSettings.app.systemProxyDNS : appSettings.app.systemDefaultDNS
98+
await SetSystemDNS(servers, appSettings.app.systemProxyServices)
99+
systemDNSSet.value = proxy
100+
}
101+
94102
watch(systemProxy, updateTrayAndMenus)
95103

96104
return {
97105
env,
98106
setupEnv,
99107
systemProxy,
108+
systemDNSSet,
100109
setSystemProxy,
101110
clearSystemProxy,
102111
switchSystemProxy,
103112
updateSystemProxyStatus,
113+
setSystemDNS,
104114
}
105115
})

frontend/src/stores/kernelApi.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
309309
if (appSettingsStore.app.autoSetSystemProxy) {
310310
await envStore.setSystemProxy().catch((err) => message.error(err))
311311
}
312+
if (appSettingsStore.app.autoSetSystemDNS) {
313+
await envStore.setSystemDNS(true).catch((err) => message.error(err))
314+
}
312315
await envStore.updateSystemProxyStatus()
313316

314317
await pluginsStore.onCoreStartedTrigger()
@@ -329,6 +332,9 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
329332
if (envStore.systemProxy) {
330333
await envStore.clearSystemProxy()
331334
}
335+
if (appSettingsStore.app.autoSetSystemDNS || envStore.systemDNSSet) {
336+
await envStore.setSystemDNS(false).catch((err) => message.error(err))
337+
}
332338

333339
resetConfig()
334340

frontend/src/types/app.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,13 @@ export interface AppSettings {
7070
exitOnClose: boolean
7171
closeKernelOnExit: boolean
7272
autoSetSystemProxy: boolean
73+
autoSetSystemDNS: boolean
7374
requestProxyMode: RequestProxyMode
7475
customProxy: string
7576
proxyBypassList: string
76-
darwinSystemProxyServices: string[]
77+
systemProxyServices: string[]
78+
systemProxyDNS: string
79+
systemDefaultDNS: string
7780
autoStartKernel: boolean
7881
autoRestartKernel: boolean
7982
userAgent: string

0 commit comments

Comments
 (0)