DNS Proxy network extension doesn't start even after saving preferences successfully

Hello, I'm having some problems starting my DNS proxy network extension.

Even after I call NEDNSProxyManager.saveToPreference() successfully I don't see any logs from my dns proxy.

This is the code from the user space app:

import SwiftUI
import NetworkExtension

func configureDNSProxy() {
    let dnsProxyManager = NEDNSProxyManager.shared()

    dnsProxyManager.loadFromPreferences { error in
        if let error = error {
            print("Error loading DNS proxy preferences: \(error)")
            return
        }

        dnsProxyManager.localizedDescription = "my DNS proxy"
        let proto = NEDNSProxyProviderProtocol()
        proto.providerBundleIdentifier = "com.myteam.dns-proxy-tests.ne"
        dnsProxyManager.providerProtocol = proto

        // Enable the DNS proxy.
        dnsProxyManager.isEnabled = true
        dnsProxyManager.saveToPreferences { error in
            if let error = error {                                                                     
                print("Error saving DNS proxy preferences: \(error)")
            } else {
                NSLog("DNS Proxy enabled successfully")
            }
        }

    }
}

@main
struct dns_proxy_testsApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
    init() {
        configureDNSProxy()
    }

}

This is the code for my network extension(DNSProxyProvider.swift):

import NetworkExtension

class DNSProxyProvider: NEDNSProxyProvider {

    override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
        NSLog("dns proxy ne started")
        completionHandler(nil)
    }

    override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        NSLog("dns proxy ne stopped")
        completionHandler()
    }

    override func sleep(completionHandler: @escaping () -> Void) {
        NSLog("dns proxy ne sleep")
        completionHandler()
    }

    override func wake() {
        NSLog("dns proxy ne wake")
    }

    override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
        NSLog("dns proxy ne flow")
        return true
    }

}

The bundle identifier for my network extension is: com.myteam.dns-proxy-tests.ne and both the user space app and the network extension have the DNS Proxy capability. Both have the same app group capability with the same group name group.com.myteam.dns-proxy-test.

The info.plist from the network extension look like this(I didn't really modify it from the default template created by xcode)

<?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>NetworkExtension</key>
	<dict>
		<key>NEMachServiceName</key>
		<string>$(TeamIdentifierPrefix)com.example.app-group.MySystemExtension</string>
		<key>NEProviderClasses</key>
		<dict>
			<key>com.apple.networkextension.dns-proxy</key>
			<string>$(PRODUCT_MODULE_NAME).DNSProxyProvider</string>
		</dict>
	</dict>
</dict>
</plist>

In the logs I do see DNS Proxy enabled successfully and also I see:

NESMDNSProxySession[Primary Tunnel:my DNS proxy:<...>:(null)] starting with configuration: {
    name = my DNS proxy
    identifier = <..>
    applicationName = dns-proxy-tests
    application = com.myteam.dns-proxy-tests
    grade = 1
    dnsProxy = {
        enabled = YES
        protocol = {
            type = dnsProxy
            identifier = <...>
            identityDataImported = NO
            disconnectOnSleep = NO
            disconnectOnIdle = NO
            disconnectOnIdleTimeout = 0
            disconnectOnWake = NO
            disconnectOnWakeTimeout = 0
            disconnectOnUserSwitch = NO
            disconnectOnLogout = NO
            includeAllNetworks = NO
            excludeLocalNetworks = NO
            excludeCellularServices = YES
            excludeAPNs = YES
            excludeDeviceCommunication = YES
            enforceRoutes = NO
            pluginType = com.myteam.dns-proxy-tests
            providerBundleIdentifier = com.myteam.dns-proxy-tests.ne
            designatedRequirement = identifier "com.myteam.dns-proxy-tests.ne" <...> /* exists */
        }
    }
}

But then I see:

Checking for com.myteam.dns-proxy-tests.ne - com.apple.networkextension.dns-proxy

But then finally

Found 0 registrations for com.myteam.dns-proxy-tests.ne (com.apple.networkextension.dns-proxy)

So I think that last log probably indicates the problem.

I'm a bit lost at what I'm doing wrong so I'd be super thankful for any pointer!

Answered by DTS Engineer in 831297022

I suspect that the sysextd crash is a known issue that seems to be caused by a race condition in the code (r. 99777199).

The nesessionmanager crash is more likely to be caused by the properties in your sysex. The crashing thread looks like this:

5 Foundation       0x191f5c120 -[NSString initWithFormat:] + 52
6 nesessionmanager 0x100138ac0 -[NESMProviderManager createSystemExtensionErrorWithCode:extensionInfo:] + 440
7 nesessionmanager 0x100139558 -[NESMProviderManager createLaunchdPlistEntriesFromExtensionBundle:extensionInfo:error:] + 2464
8 nesessionmanager 0x1001399d8 __84-[NESMProviderManager listener:validateExtension:atTemporaryBundleURL:replyHandler:]_block_invoke + 212

NE is trying to validate your sysex, that’s failed, and it’s crashed trying to generate the error O-:

Both of these are obviously bugs in our OS — these subsystems should fail rather than crash — and I encourage you to file bug reports about them. Include a sysdiagnose log and a copy of your built app (the broken one, not the fixed one). Please post your bug numbers, just for the record.

However, frame 7 in the NE crash suggests that you have an app group mismatch. NE wants your Mach service name to be ‘inside’ an app group. For example, in my test project I have this:

% codesign -d --entitlements - QNE2DNSProxyMac.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.QNE2DNSProxyMac.SysEx.systemextension
…
[Dict]
    …
	[Value]
		[Array]
			[String] SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac
    …
% plutil -p QNE2DNSProxyMac.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.QNE2DNSProxyMac.SysEx.systemextension/Contents/Info.plist
{
  …
  "NetworkExtension" => {
    "NEMachServiceName" => "SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac.service"
    "NEProviderClasses" => {
      "com.apple.networkextension.dns-proxy" => "com_example_apple_samplecode_QNE2DNSProxyMac_SysEx.DNSProxyProvider"
    }
  }
  …
}

My app group, SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac, is a prefix of the Mach service name, SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac.service, and that’s what NE is checking for.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

However, frame 7 in the NE crash suggests that you have an app group mismatch. NE wants your Mach service name to be ‘inside’ an app group. For example, in my test project I have this:

My app group, SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac, is a prefix of the Mach service name, SKMME9E2Y8.com.example.apple-samplecode.QNE2DNSProxyMac.service, and that’s what NE is checking for.

Ah! Very nice, that was it! :D

I'll report this bug

Have you solved this? i have a issue similar with you @conectado , here is my post

DNS Proxy network extension doesn't start even after saving preferences successfully
 
 
Q