Thanks for your assistance but I am still having issues and will continue to investigate with SIP enabled as you suggested. In the meantime this is what I have.
ViewController.swift
Code Block | import Cocoa |
| import os |
| import NetworkExtension |
| import SystemExtensions |
|
| class ViewController: NSViewController { |
|
| override func viewDidLoad() { |
| super.viewDidLoad() |
|
| os_log("DNSFILTER: viewDidLoad") |
| installSystemExtension() |
| configureProxy() |
| } |
|
| override var representedObject: Any? { |
| didSet { |
| // Update the view, if already loaded. |
| } |
| } |
| |
| var manager: NEDNSProxyManager? |
|
| private func installSystemExtension() { |
| os_log("DNSFILTER: installing system extension") |
| let request = OSSystemExtensionRequest.activationRequest( |
| forExtensionWithIdentifier: "com.blob.macappproxy.dns", |
| queue: .main |
| ) |
| request.delegate = self |
| OSSystemExtensionManager.shared.submitRequest(request) |
| } |
| |
| private func configureProxy() { |
| os_log("DNSFILTER: configuring proxy") |
| guard let dnsManager = manager else { return } |
| dnsManager.loadFromPreferences { error in |
| precondition(Thread.isMainThread) |
| |
| if let nsError = error as NSError? { |
| os_log("DNSFILTER: Failed to load the filter configuration: %@", nsError.localizedDescription) |
| return |
| } |
| let proto = NEDNSProxyProviderProtocol() |
| proto.serverAddress = "localhost" /* Just for testing purposes */ |
| proto.providerBundleIdentifier = "com.blob.macappproxy.dns" |
| dnsManager.providerProtocol = proto |
| dnsManager.isEnabled = true |
| dnsManager.localizedDescription = "Testing DNS Proxy" |
| |
| dnsManager.saveToPreferences { saveError in |
| if let nsError = saveError as NSError? { |
| os_log("DNSFILTER: Failed to disable the filter configuration: %@", nsError.localizedDescription) |
| return |
| } |
| /* Handle Success Case */ |
| os_log("DNSFILTER: dns proxy configured") |
| } |
| } |
| } |
| } |
| extension ViewController: OSSystemExtensionRequestDelegate { |
| func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction { |
| os_log("DNSFILTER: Replacing extension %@ version %@ with version %@", request.identifier, existing.bundleShortVersion, ext.bundleShortVersion) |
| return .replace |
| } |
| |
| func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) { |
| os_log("DNSFILTER: Extension %@ requires user approval", request.identifier) |
| } |
| |
| func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) { |
| os_log("DNSFILTER: System extension request failed: %@", error.localizedDescription) |
| } |
| |
| /* Other delegate methods here */ |
| func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) { |
| switch result { |
| case .completed: |
| manager = NEDNSProxyManager.shared() |
| case .willCompleteAfterReboot: |
| os_log("DNSFILTER: willCompleteAfterReboot") |
| @unknown default: |
| os_log("DNSFILTER: default") |
| } |
| } |
| } |
|
Code Block | 2021-03-18 17:09:27.676100+1100 macappproxy[1142:14431] DNSFILTER: viewDidLoad |
| 2021-03-18 17:09:27.676187+1100 macappproxy[1142:14431] DNSFILTER: installing system extension |
| 2021-03-18 17:09:27.678794+1100 macappproxy[1142:14431] DNSFILTER: configuring proxy |
| 2021-03-18 17:09:27.922090+1100 macappproxy[1142:14431] DNSFILTER: System extension request failed: The operation couldn’t be completed. (OSSystemExtensionErrorDomain error 1.) |
When
configureProxy() is invoked it doesn't get past line 36 in ViewController.swift, which I guess is understandable if the extension hasn't started.
My
DNSProxyProvider.swift is barebones:
Code Block | import NetworkExtension |
| import os |
|
| class DNSProxyProvider: NEAppProxyProvider { |
|
| override func startProxy(options: [String : Any]?, completionHandler: @escaping (Error?) -> Void) { |
| // Add code here to start the process of connecting the tunnel. |
| os_log("DNSFILTER: provider started") |
| completionHandler(nil) |
| } |
| |
| override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { |
| // Add code here to start the process of stopping the tunnel. |
| completionHandler() |
| } |
| |
| override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { |
| // Add code here to handle the message. |
| if let handler = completionHandler { |
| handler(messageData) |
| } |
| } |
| |
| 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. |
| return false |
| } |
| } |
Let me know if anything looks awry. Thanks. I will continue to trawl through the console logs for any clues.