refactor: system dns
This commit is contained in:
parent
8e88476f27
commit
9a3b404e74
|
@ -13,9 +13,10 @@
|
||||||
018F88F9286DD0CB004DD0F7 /* DualTitleMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018F88F8286DD0CB004DD0F7 /* DualTitleMenuItem.swift */; };
|
018F88F9286DD0CB004DD0F7 /* DualTitleMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018F88F8286DD0CB004DD0F7 /* DualTitleMenuItem.swift */; };
|
||||||
01943259287D19BC008CC51A /* ClashRuleProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01943258287D19BC008CC51A /* ClashRuleProvider.swift */; };
|
01943259287D19BC008CC51A /* ClashRuleProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01943258287D19BC008CC51A /* ClashRuleProvider.swift */; };
|
||||||
019A239628657A7A00AE5698 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019A239528657A7A00AE5698 /* main.swift */; };
|
019A239628657A7A00AE5698 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019A239528657A7A00AE5698 /* main.swift */; };
|
||||||
|
01A645D3292C769D00B37FA2 /* DNSConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01A645D2292C759100B37FA2 /* DNSConfiguration.swift */; };
|
||||||
01B009AE2854533300B93618 /* geoip.dat.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01B009AC2854533200B93618 /* geoip.dat.gz */; };
|
01B009AE2854533300B93618 /* geoip.dat.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01B009AC2854533200B93618 /* geoip.dat.gz */; };
|
||||||
01B009AF2854533300B93618 /* geosite.dat.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01B009AD2854533300B93618 /* geosite.dat.gz */; };
|
01B009AF2854533300B93618 /* geosite.dat.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01B009AD2854533300B93618 /* geosite.dat.gz */; };
|
||||||
01B30C43291CE18F0081C4F7 /* MetaDNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B30C41291C98930081C4F7 /* MetaDNS.swift */; };
|
01BC9ABE2928EB5A00F9B177 /* MetaDNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */; };
|
||||||
01C1462A28962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */; };
|
01C1462A28962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */; };
|
||||||
185CBAEDFE986E6E1B836359 /* libPods-ClashX Meta.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA63125BBF03DC1A291D3351 /* libPods-ClashX Meta.a */; };
|
185CBAEDFE986E6E1B836359 /* libPods-ClashX Meta.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA63125BBF03DC1A291D3351 /* libPods-ClashX Meta.a */; };
|
||||||
4913C82321157D0200F6B87C /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4913C82221157D0200F6B87C /* Notification.swift */; };
|
4913C82321157D0200F6B87C /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4913C82221157D0200F6B87C /* Notification.swift */; };
|
||||||
|
@ -140,9 +141,10 @@
|
||||||
018F88F8286DD0CB004DD0F7 /* DualTitleMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DualTitleMenuItem.swift; sourceTree = "<group>"; };
|
018F88F8286DD0CB004DD0F7 /* DualTitleMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DualTitleMenuItem.swift; sourceTree = "<group>"; };
|
||||||
01943258287D19BC008CC51A /* ClashRuleProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClashRuleProvider.swift; sourceTree = "<group>"; };
|
01943258287D19BC008CC51A /* ClashRuleProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClashRuleProvider.swift; sourceTree = "<group>"; };
|
||||||
019A239528657A7A00AE5698 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
019A239528657A7A00AE5698 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||||
|
01A645D2292C759100B37FA2 /* DNSConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSConfiguration.swift; sourceTree = "<group>"; };
|
||||||
01B009AC2854533200B93618 /* geoip.dat.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = geoip.dat.gz; sourceTree = "<group>"; };
|
01B009AC2854533200B93618 /* geoip.dat.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = geoip.dat.gz; sourceTree = "<group>"; };
|
||||||
01B009AD2854533300B93618 /* geosite.dat.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = geosite.dat.gz; sourceTree = "<group>"; };
|
01B009AD2854533300B93618 /* geosite.dat.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = geosite.dat.gz; sourceTree = "<group>"; };
|
||||||
01B30C41291C98930081C4F7 /* MetaDNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDNS.swift; sourceTree = "<group>"; };
|
01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDNS.swift; sourceTree = "<group>"; };
|
||||||
01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = com.metacubex.ClashX.ProxyConfigHelper.meta.gz; sourceTree = "<group>"; };
|
01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = com.metacubex.ClashX.ProxyConfigHelper.meta.gz; sourceTree = "<group>"; };
|
||||||
3F86DA2DA3CC14731BE1ABF7 /* Pods-ClashX Meta.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ClashX Meta.release.xcconfig"; path = "Pods/Target Support Files/Pods-ClashX Meta/Pods-ClashX Meta.release.xcconfig"; sourceTree = "<group>"; };
|
3F86DA2DA3CC14731BE1ABF7 /* Pods-ClashX Meta.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ClashX Meta.release.xcconfig"; path = "Pods/Target Support Files/Pods-ClashX Meta/Pods-ClashX Meta.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
4913C82221157D0200F6B87C /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
4913C82221157D0200F6B87C /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||||
|
@ -464,7 +466,6 @@
|
||||||
49761DA521C9490400AE13EF /* Resources */,
|
49761DA521C9490400AE13EF /* Resources */,
|
||||||
49CF3B3A20CD783A001EBF94 /* Support Files */,
|
49CF3B3A20CD783A001EBF94 /* Support Files */,
|
||||||
49CF3B2020CD7463001EBF94 /* AppDelegate.swift */,
|
49CF3B2020CD7463001EBF94 /* AppDelegate.swift */,
|
||||||
01B30C41291C98930081C4F7 /* MetaDNS.swift */,
|
|
||||||
49CF3B2620CD7465001EBF94 /* Main.storyboard */,
|
49CF3B2620CD7465001EBF94 /* Main.storyboard */,
|
||||||
49CF3B2920CD7465001EBF94 /* Info.plist */,
|
49CF3B2920CD7465001EBF94 /* Info.plist */,
|
||||||
49CF3B2A20CD7465001EBF94 /* ClashX.entitlements */,
|
49CF3B2A20CD7465001EBF94 /* ClashX.entitlements */,
|
||||||
|
@ -529,6 +530,8 @@
|
||||||
498960722340F21C00AFB7EC /* com.metacubex.ClashX.ProxyConfigHelper.entitlements */,
|
498960722340F21C00AFB7EC /* com.metacubex.ClashX.ProxyConfigHelper.entitlements */,
|
||||||
019A239528657A7A00AE5698 /* main.swift */,
|
019A239528657A7A00AE5698 /* main.swift */,
|
||||||
0162E74E2864B819007218A6 /* MetaTask.swift */,
|
0162E74E2864B819007218A6 /* MetaTask.swift */,
|
||||||
|
01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */,
|
||||||
|
01A645D2292C759100B37FA2 /* DNSConfiguration.swift */,
|
||||||
F935B2F12307C802009E4D33 /* Helper-Launchd.plist */,
|
F935B2F12307C802009E4D33 /* Helper-Launchd.plist */,
|
||||||
F935B2EA2307B6BA009E4D33 /* Helper-Info.plist */,
|
F935B2EA2307B6BA009E4D33 /* Helper-Info.plist */,
|
||||||
F935B2F22307CD32009E4D33 /* ProxyConfigHelper.h */,
|
F935B2F22307CD32009E4D33 /* ProxyConfigHelper.h */,
|
||||||
|
@ -710,7 +713,6 @@
|
||||||
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */,
|
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */,
|
||||||
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,
|
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,
|
||||||
4929F67F258CE04700A435F6 /* Settings.swift in Sources */,
|
4929F67F258CE04700A435F6 /* Settings.swift in Sources */,
|
||||||
01B30C43291CE18F0081C4F7 /* MetaDNS.swift in Sources */,
|
|
||||||
493AEAE3221AE3420016FE98 /* AppVersionUtil.swift in Sources */,
|
493AEAE3221AE3420016FE98 /* AppVersionUtil.swift in Sources */,
|
||||||
49CF3B2120CD7463001EBF94 /* AppDelegate.swift in Sources */,
|
49CF3B2120CD7463001EBF94 /* AppDelegate.swift in Sources */,
|
||||||
496BDEE021196F1E00C5207F /* Logger.swift in Sources */,
|
496BDEE021196F1E00C5207F /* Logger.swift in Sources */,
|
||||||
|
@ -774,9 +776,11 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
F935B2F42307CD32009E4D33 /* ProxyConfigHelper.m in Sources */,
|
F935B2F42307CD32009E4D33 /* ProxyConfigHelper.m in Sources */,
|
||||||
|
01A645D3292C769D00B37FA2 /* DNSConfiguration.swift in Sources */,
|
||||||
0162E74F2864B819007218A6 /* MetaTask.swift in Sources */,
|
0162E74F2864B819007218A6 /* MetaTask.swift in Sources */,
|
||||||
019A239628657A7A00AE5698 /* main.swift in Sources */,
|
019A239628657A7A00AE5698 /* main.swift in Sources */,
|
||||||
491E6203258A424D00313AEF /* CommonUtils.m in Sources */,
|
491E6203258A424D00313AEF /* CommonUtils.m in Sources */,
|
||||||
|
01BC9ABE2928EB5A00F9B177 /* MetaDNS.swift in Sources */,
|
||||||
F935B2FA23083EE6009E4D33 /* ProxySettingTool.m in Sources */,
|
F935B2FA23083EE6009E4D33 /* ProxySettingTool.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -72,8 +72,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
var dashboardWindowController: ClashWebViewWindowController?
|
var dashboardWindowController: ClashWebViewWindowController?
|
||||||
|
|
||||||
let metaDNS = MetaDNS()
|
|
||||||
|
|
||||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||||
signal(SIGPIPE, SIG_IGN)
|
signal(SIGPIPE, SIG_IGN)
|
||||||
// crash recorder
|
// crash recorder
|
||||||
|
@ -138,8 +136,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
var shouldWait = false
|
var shouldWait = false
|
||||||
|
|
||||||
PrivilegedHelperManager.shared.helper()?.stopMeta()
|
PrivilegedHelperManager.shared.helper()?.stopMeta()
|
||||||
|
PrivilegedHelperManager.shared.helper()?.updateTun(with: false)
|
||||||
metaDNS.updateTunState(false)
|
|
||||||
|
|
||||||
if ConfigManager.shared.proxyPortAutoSet && !ConfigManager.shared.isProxySetByOtherVariable.value || NetworkChangeNotifier.isCurrentSystemSetToClash(looser: true) ||
|
if ConfigManager.shared.proxyPortAutoSet && !ConfigManager.shared.isProxySetByOtherVariable.value || NetworkChangeNotifier.isCurrentSystemSetToClash(looser: true) ||
|
||||||
NetworkChangeNotifier.hasInterfaceProxySetToClash() {
|
NetworkChangeNotifier.hasInterfaceProxySetToClash() {
|
||||||
|
@ -241,7 +238,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.bind { _ in
|
.bind { _ in
|
||||||
let isTunMode = ConfigManager.shared.isTunModeVariable.value
|
let isTunMode = ConfigManager.shared.isTunModeVariable.value
|
||||||
self.metaDNS.updateTunState(isTunMode)
|
PrivilegedHelperManager.shared.helper()?.updateTun(with: isTunMode)
|
||||||
|
Logger.log("tun state updated,new: \(isTunMode)")
|
||||||
}.disposed(by: disposeBag)
|
}.disposed(by: disposeBag)
|
||||||
|
|
||||||
Observable
|
Observable
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
//
|
|
||||||
// MetaDNS.swift
|
|
||||||
// ClashX
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
class MetaDNS: NSObject {
|
|
||||||
|
|
||||||
var defaultDNS = "198.18.0.2"
|
|
||||||
var savedDNS: [String]?
|
|
||||||
|
|
||||||
func updateTunState(_ isTun: Bool) {
|
|
||||||
if isTun {
|
|
||||||
if savedDNS == nil {
|
|
||||||
let dns = getDNS()
|
|
||||||
if dns.count == 1, dns[0] == defaultDNS {
|
|
||||||
savedDNS = []
|
|
||||||
} else {
|
|
||||||
savedDNS = dns
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setDNS()
|
|
||||||
} else {
|
|
||||||
if savedDNS == nil || savedDNS!.count == 0 {
|
|
||||||
setDNS([])
|
|
||||||
} else if let dns = savedDNS {
|
|
||||||
setDNS(dns)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDNS() -> [String] {
|
|
||||||
let re = runCommand("/usr/sbin/networksetup", args: [
|
|
||||||
"-getdnsservers",
|
|
||||||
"\(networkServiceName())"
|
|
||||||
])
|
|
||||||
|
|
||||||
if re.contains("There aren't any DNS Servers") {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return re.split(separator: "\n").map(String.init)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setDNS(_ dns: [String] = ["198.18.0.2"]) {
|
|
||||||
var args = [
|
|
||||||
"-setdnsservers",
|
|
||||||
"\(networkServiceName())"
|
|
||||||
]
|
|
||||||
if dns.count > 0 {
|
|
||||||
args.append(contentsOf: dns)
|
|
||||||
} else {
|
|
||||||
args.append("Empty")
|
|
||||||
}
|
|
||||||
_ = runCommand("/usr/sbin/networksetup", args: args)
|
|
||||||
}
|
|
||||||
|
|
||||||
func networkServiceName() -> String {
|
|
||||||
// https://apple.stackexchange.com/a/432170
|
|
||||||
|
|
||||||
runCommand("/bin/bash", args: ["-c", "networksetup -listnetworkserviceorder | awk -v DEV=$(/usr/sbin/scutil --nwi | awk -F': ' '/Network interfaces/ {print $2;exit;}') -F': |,' '$0~ DEV {print $2;exit;}'"])
|
|
||||||
}
|
|
||||||
|
|
||||||
func runCommand(_ path: String, args: [String]) -> String {
|
|
||||||
let proc = Process()
|
|
||||||
proc.executableURL = .init(fileURLWithPath: path)
|
|
||||||
proc.arguments = args
|
|
||||||
let pipe = Pipe()
|
|
||||||
proc.standardOutput = pipe
|
|
||||||
do {
|
|
||||||
try proc.run()
|
|
||||||
} catch let error {
|
|
||||||
Logger.log(error.localizedDescription)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
proc.waitUntilExit()
|
|
||||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
|
||||||
|
|
||||||
guard proc.terminationStatus == 0,
|
|
||||||
var out = String(data: data, encoding: .utf8) else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if out.last == "\n" {
|
|
||||||
out.removeLast()
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// DNSConfiguration.swift
|
||||||
|
// ClashX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import SystemConfiguration
|
||||||
|
|
||||||
|
// https://github.com/ivanstegic/menu-bar-dns/blob/main/Menu%20Bar%20DNS/Menu%20Bar%20DNS/DNSConfiguration.swift
|
||||||
|
|
||||||
|
class DNSConfiguration: NSObject {
|
||||||
|
|
||||||
|
static let DNSConfigurationTypeKey = Bundle.main.bundleIdentifier! + ".dns"
|
||||||
|
static let ServiceTypeWiFi = "IEEE80211"
|
||||||
|
static let ServiceTypeEthernet = "Ethernet"
|
||||||
|
|
||||||
|
static func getnterfaceTypeByServiceIDs(_ services: Array<SCNetworkService>) throws -> Dictionary<String, String> {
|
||||||
|
let allServicesIDsAndInterfaceType = try services.map { service -> (String, String) in
|
||||||
|
guard
|
||||||
|
let id = SCNetworkServiceGetServiceID(service) as String?,
|
||||||
|
let interface = SCNetworkServiceGetInterface(service),
|
||||||
|
let interfaceType = SCNetworkInterfaceGetInterfaceType(interface) as String?
|
||||||
|
else {
|
||||||
|
throw SCCopyLastError()
|
||||||
|
}
|
||||||
|
return (id, interfaceType)
|
||||||
|
}
|
||||||
|
return Dictionary(uniqueKeysWithValues: allServicesIDsAndInterfaceType)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func isConnectedService(_ service : SCNetworkService) throws -> Bool {
|
||||||
|
|
||||||
|
guard
|
||||||
|
let id = SCNetworkServiceGetServiceID(service) as String?
|
||||||
|
else {
|
||||||
|
throw SCCopyLastError()
|
||||||
|
}
|
||||||
|
|
||||||
|
let dynmaicStore = SCDynamicStoreCreate(kCFAllocatorSystemDefault, "DNSSETTING" as CFString, nil, nil)
|
||||||
|
let serviceStateIPv4Key = "State:/Network/Service/\(id)/IPv4" as CFString
|
||||||
|
let value = SCDynamicStoreCopyValue(dynmaicStore, serviceStateIPv4Key) as CFPropertyList?
|
||||||
|
return value != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getDNSForServiceID(_ serviceID:String) -> [String] {
|
||||||
|
let serviceDNSKey = "State:/Network/Service/\(serviceID)/DNS" as CFString
|
||||||
|
let serviceSetupDNSKey = "Setup:/Network/Service/\(serviceID)/DNS" as CFString
|
||||||
|
let dynmaicStore = SCDynamicStoreCreate(kCFAllocatorSystemDefault, "DNSSETTING" as CFString, nil, nil)
|
||||||
|
var allDNSIPAddresses : Array<String> = []
|
||||||
|
|
||||||
|
let dynamicPlist = SCDynamicStoreCopyValue(dynmaicStore, serviceDNSKey)
|
||||||
|
let manualAddressPlist = SCDynamicStoreCopyValue(dynmaicStore, serviceSetupDNSKey)
|
||||||
|
|
||||||
|
if let dnsValues = manualAddressPlist?[kSCPropNetDNSServerAddresses] as? [String] {
|
||||||
|
allDNSIPAddresses += dnsValues
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if let dhcpValues = dynamicPlist?[kSCPropNetDNSServerAddresses] as? [String] {
|
||||||
|
let uniqueValues = Array(Set(dhcpValues))
|
||||||
|
for dhcpValue in uniqueValues {
|
||||||
|
let newvalue = dhcpValue.appending(" (via DHCP)")
|
||||||
|
allDNSIPAddresses.append(newvalue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return allDNSIPAddresses
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getAddresses() -> (Array<String>, Array<String>) {
|
||||||
|
var ethernetDNSAddresses : Array<String> = []
|
||||||
|
var WiFiDNSAddresses : Array<String> = []
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
let prefs = SCPreferencesCreate(
|
||||||
|
nil, DNSConfigurationTypeKey as NSString,
|
||||||
|
nil
|
||||||
|
) as SCPreferences?
|
||||||
|
let allServicesCF = SCNetworkServiceCopyAll(prefs!)
|
||||||
|
let allServices = allServicesCF as? [SCNetworkService]
|
||||||
|
|
||||||
|
let allConnectedServices = try allServices?.filter({ (service) -> Bool in
|
||||||
|
return try isConnectedService(service)
|
||||||
|
})
|
||||||
|
let serviceTypeByIDs = try getnterfaceTypeByServiceIDs(allConnectedServices!) as Dictionary<String, String>?
|
||||||
|
for (id, type) in serviceTypeByIDs! {
|
||||||
|
switch (type) {
|
||||||
|
case ServiceTypeWiFi:
|
||||||
|
WiFiDNSAddresses += getDNSForServiceID(id)
|
||||||
|
case ServiceTypeEthernet:
|
||||||
|
ethernetDNSAddresses += getDNSForServiceID(id)
|
||||||
|
default:
|
||||||
|
print("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return ([], [])
|
||||||
|
}
|
||||||
|
return (ethernetDNSAddresses, WiFiDNSAddresses)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,9 +9,9 @@
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>com.metacubex.ClashX.ProxyConfigHelper</string>
|
<string>com.metacubex.ClashX.ProxyConfigHelper</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.5</string>
|
<string>1.6</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>6</string>
|
<string>7</string>
|
||||||
<key>SMAuthorizedClients</key>
|
<key>SMAuthorizedClients</key>
|
||||||
<array>
|
<array>
|
||||||
<string>anchor apple generic and identifier "com.metacubex.ClashX.ProxyConfigHelper" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = MEWHFZ92DY)</string>
|
<string>anchor apple generic and identifier "com.metacubex.ClashX.ProxyConfigHelper" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = MEWHFZ92DY)</string>
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
//
|
||||||
|
// MetaDNS.swift
|
||||||
|
// ClashX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import SystemConfiguration
|
||||||
|
|
||||||
|
// https://github.com/zhuhaow/Specht2/blob/main/app/me.zhuhaow.Specht2.proxy-helper/ProxyHelper.swift
|
||||||
|
|
||||||
|
class MetaDNS: NSObject {
|
||||||
|
|
||||||
|
var savedDns = [String: [String]]()
|
||||||
|
let defaultDNS = "198.18.0.2"
|
||||||
|
|
||||||
|
let authRef: AuthorizationRef
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
var auth: AuthorizationRef?
|
||||||
|
let authFlags: AuthorizationFlags = [.extendRights, .interactionAllowed, .preAuthorize]
|
||||||
|
|
||||||
|
let authErr = AuthorizationCreate(nil, nil, authFlags, &auth)
|
||||||
|
|
||||||
|
if authErr != noErr {
|
||||||
|
NSLog("Error: Failed to create administration authorization due to error \(authErr).")
|
||||||
|
}
|
||||||
|
|
||||||
|
if auth == nil {
|
||||||
|
NSLog("Error: No authorization has been granted to modify network configuration.")
|
||||||
|
}
|
||||||
|
|
||||||
|
authRef = auth!
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
AuthorizationFree(authRef, AuthorizationFlags())
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func updateDns() {
|
||||||
|
let dns = getAllDns()
|
||||||
|
dns.forEach {
|
||||||
|
if $0.value.count == 1,
|
||||||
|
$0.value[0] == defaultDNS {
|
||||||
|
savedDns[$0.key] = []
|
||||||
|
} else {
|
||||||
|
savedDns[$0.key] = $0.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dnsDic = dns.reduce(into: [:]) {
|
||||||
|
$0[$1.key] = [defaultDNS]
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDNSConfigure(dnsDic)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func revertDns() {
|
||||||
|
updateDNSConfigure(savedDns)
|
||||||
|
savedDns.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllDns() -> [String: [String]] {
|
||||||
|
var re = [String: [String]]()
|
||||||
|
|
||||||
|
guard let prefs = SCPreferencesCreate(nil, "ClashX" as CFString, nil),
|
||||||
|
let values = SCPreferencesGetValue(prefs, kSCPrefNetworkServices) as? [String: AnyObject] else {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
values.reduce(into: [:]) {
|
||||||
|
$0[$1.key] = $1.value.value(forKeyPath: "Interface.Hardware") as? String
|
||||||
|
}.filter {
|
||||||
|
["AirPort", "Wi-Fi", "Ethernet"].contains($0.value)
|
||||||
|
}.forEach {
|
||||||
|
re[$0.key] = DNSConfiguration.getDNSForServiceID($0.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func flushDnsCache() {
|
||||||
|
CommonUtils.runCommand("/usr/bin/killall", args: ["-HUP", "mDNSResponder"])
|
||||||
|
|
||||||
|
print("flushDnsCache")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateDNSConfigure(_ dnsDic: [String: [String]]) {
|
||||||
|
|
||||||
|
guard let prefRef = SCPreferencesCreateWithAuthorization(
|
||||||
|
nil,
|
||||||
|
"com.metacubex.ClashX.ProxyConfigHelper.config" as CFString,
|
||||||
|
nil,
|
||||||
|
authRef) else {
|
||||||
|
NSLog("Error: Failed to obtain preference ref.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard SCPreferencesLock(prefRef, true) else {
|
||||||
|
NSLog("Error: Failed to obtain lock to preference.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer {
|
||||||
|
SCPreferencesUnlock(prefRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let networks = SCNetworkSetCopyCurrent(prefRef),
|
||||||
|
let services = SCNetworkSetCopyServices(networks) as? [SCNetworkService] else {
|
||||||
|
NSLog("Error: Failed to load network services.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = kSCNetworkProtocolTypeDNS
|
||||||
|
|
||||||
|
services.forEach { service in
|
||||||
|
guard let id = SCNetworkServiceGetServiceID(service) as? String,
|
||||||
|
let dns = dnsDic[id] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
guard let protoc = SCNetworkServiceCopyProtocol(service, type) else {
|
||||||
|
NSLog("Error: Failed to obtain \(type) settings for \(SCNetworkServiceGetName(service)!)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = SCNetworkProtocolGetConfiguration(protoc)
|
||||||
|
|
||||||
|
var dic = (config as NSDictionary?)?.mutableCopy() as? NSMutableDictionary ?? NSMutableDictionary()
|
||||||
|
|
||||||
|
dic["ServerAddresses"] = dns
|
||||||
|
|
||||||
|
guard SCNetworkProtocolSetConfiguration(protoc, dic as CFDictionary) else {
|
||||||
|
NSLog("Error: Failed to set \(type) settings for \(SCNetworkServiceGetName(service)!)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog("Set \(type) settings for \(SCNetworkServiceGetName(service)!)")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
guard SCPreferencesCommitChanges(prefRef) else {
|
||||||
|
NSLog("Error: Failed to commit preference change")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard SCPreferencesApplyChanges(prefRef) else {
|
||||||
|
NSLog("Error: Failed to apply preference change")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ ProxyConfigRemoteProcessProtocol
|
||||||
@property (nonatomic, assign) BOOL shouldQuit;
|
@property (nonatomic, assign) BOOL shouldQuit;
|
||||||
|
|
||||||
@property (nonatomic, strong) MetaTask *metaTask;
|
@property (nonatomic, strong) MetaTask *metaTask;
|
||||||
|
@property (nonatomic, strong) MetaDNS *metaDNS;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ ProxyConfigRemoteProcessProtocol
|
||||||
self.listener = [[NSXPCListener alloc] initWithMachServiceName:@"com.metacubex.ClashX.ProxyConfigHelper"];
|
self.listener = [[NSXPCListener alloc] initWithMachServiceName:@"com.metacubex.ClashX.ProxyConfigHelper"];
|
||||||
self.listener.delegate = self;
|
self.listener.delegate = self;
|
||||||
self.metaTask = [MetaTask new];
|
self.metaTask = [MetaTask new];
|
||||||
|
self.metaDNS = [MetaDNS new];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -158,4 +160,15 @@ ProxyConfigRemoteProcessProtocol
|
||||||
[self.metaTask getUsedPorts:reply];
|
[self.metaTask getUsedPorts:reply];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updateTunWith:(BOOL)state {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (state) {
|
||||||
|
[self.metaDNS updateDns];
|
||||||
|
} else {
|
||||||
|
[self.metaDNS revertDns];
|
||||||
|
}
|
||||||
|
[self.metaDNS flushDnsCache];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -27,6 +27,8 @@ typedef void(^dictReplyBlock)(NSDictionary *);
|
||||||
|
|
||||||
- (void)getUsedPorts:(stringReplyBlock)reply;
|
- (void)getUsedPorts:(stringReplyBlock)reply;
|
||||||
|
|
||||||
|
- (void)updateTunWith:(BOOL)state;
|
||||||
|
|
||||||
- (void)stopMeta;
|
- (void)stopMeta;
|
||||||
|
|
||||||
- (void)getVersion:(stringReplyBlock)reply;
|
- (void)getVersion:(stringReplyBlock)reply;
|
||||||
|
|
|
@ -6,3 +6,4 @@
|
||||||
#import "ProxyConfigHelper.h"
|
#import "ProxyConfigHelper.h"
|
||||||
#import "ProxyConfigRemoteProcessProtocol.h"
|
#import "ProxyConfigRemoteProcessProtocol.h"
|
||||||
#import "CommonUtils.h"
|
#import "CommonUtils.h"
|
||||||
|
#import "ProxySettingTool.h"
|
||||||
|
|
Loading…
Reference in New Issue