Im new to Mac Development, we are having our own custom DNS app with the use of NEDNSSetting, it just resolving all the traffic on device when we activate our own custom DNS option in System Setting->Network Preferences. Now we have to add DNSProxy into the app. But as per My research till now and after reading similar replies on developer forum, NEDNSSetting and NEDNSProxy service can not be run together or it's complex to run them together. So I have remove earlier DNSSetting implementation and added NEDNSProxy, Below is what I have done so far:
Custom Class I have created:
import Foundation
import SystemExtensions
import NetworkExtension
import os
@available(macOS 10.15, *)
public final class ConfigureProxyManager: NSObject {
public static let shared = ConfigureProxyManager()
public func installSystemExtension() {
let request = OSSystemExtensionRequest.activationRequest(
forExtensionWithIdentifier: "com.***.MacOS-DNSProxyNetworkExtension",
queue: .main
)
request.delegate = self
OSSystemExtensionManager.shared.submitRequest(request)
print("System Request has been submitted successfully")
}
public func startNetworkExtension() {
print("Enter in startNetworkExtension")
NEDNSProxyManager.shared().loadFromPreferences { error in
precondition(Thread.isMainThread)
if let nsError = error as NSError? {
/* Handle error */
return
}
let proto = NEDNSProxyProviderProtocol()
proto.serverAddress = "localhost" /* Here we have to pass custom DNS*/
proto.providerBundleIdentifier = "com.***.MacOS-DNSProxyNetworkExtension"
NEDNSProxyManager.shared().providerProtocol = proto
NEDNSProxyManager.shared().isEnabled = true
NEDNSProxyManager.shared().localizedDescription = "Custom DNS Proxy"
NEDNSProxyManager.shared().saveToPreferences { saveError in
if let nsError = saveError as NSError? {
/* Handle error */
return
}
/* Handle Success Case */
}
}
}
}
@available(macOS 10.15, *)
extension ConfigureProxyManager: OSSystemExtensionRequestDelegate {
public func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
return .replace
}
public func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
print("Enter in requestNeedsUserApproval")
}
public func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
print("Enter in didFailWithError")
}
/* Other delegate methods here */
public func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
switch result {
case .completed:
startNetworkExtension()
//manager = NEDNSProxyManager.shared()
case .willCompleteAfterReboot: break
/* Proceed with result here */
@unknown default: break
/* Proceed with result here */
}
}
}
Extension DNSProxyProvider
import NetworkExtension
import os
class DNSProxyProvider: NEDNSProxyProvider {
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "DNSProxyProvider")
override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) { os_log("Entered in startProxy Method")
// Add code here to start the DNS proxy.
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
// Add code here to stop the DNS proxy.
completionHandler()
}
override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep.
completionHandler()
}
override func wake() {
// Add code here to wake up.
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
// Add code here to handle the incoming flow.
logger.log("Flow Enter in handlenewflow method")
return false
}
Extension Main File
import Foundation
import NetworkExtension
autoreleasepool {
NEProvider.startSystemExtensionMode()
}
dispatchMain()
Container app entitlement
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy</string>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
<string>com.hyas.protect.agent-spks</string>
<string>com.hyas.protect.agent-spki</string>
</array>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(TeamIdentifierPrefix)com.*** </string>
</array>
</dict>
</plist>
Extension entitlement
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(TeamIdentifierPrefix)com.***.DNSProxyProvider</string>
</array>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy</string>
</array>
</dict>
</plist>
**This is setup till now I have. **
I trying to debug my system extension its showing waiting for attach, due to that Im not getting call in handleNewFlow method of DNSProxyProvider. What’s wrong Im doing here?