Network Extension (App Extension) Not Launching

I'm having a lot of trouble just getting a basic network extension startup, I have a main application that creates the configuration and requests the app extension based network extension to launch.

The network extension implements a NEPacketTunnelProvider and the application doesn't receive an error when starting the tunnel but when I inspect the networkextension system logs, I keep getting errors and the network extension itself doesn't appear to start nor does it log anything.

 log stream --predicate 'subsystem == "com.apple.networkextension"'

neagent: (NetworkExtension) [com.apple.networkextension:] Extension request with extension $(BUNDLE_ID) started with identifier (null)
neagent: (NetworkExtension) [com.apple.networkextension:] Failed to start extension $(BUNDLE_ID): Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named $(BUNDLE_ID)" UserInfo={NSDebugDescription=connection to service named $(BUNDLE_ID)}
nesessionmanager: [com.apple.networkextension:] Validation failed - no audit tokens
nesessionmanager: [com.apple.networkextension:] NEVPNTunnelPlugin($(BUNDLE_ID)[inactive]): Validation of the extension failed

The network extension is written in Objective-C as it needs to integrate with another language. It's not entirely clear what kind of executable the network extension is meant to be, is it meant to have a main entrypoint, or is it supposed to be a shared library / bundle?

Answered by DTS Engineer in 856827022

What platform are you developing for? This matters because there are important platform-specific differences between iOS (and its ‘child’ platforms) and macOS when it comes to NE.

Also, I have some general advice on how to debug problems like this in Debugging a Network Extension Provider. I recommend that you start there and then, if you aren’t able to fix things, come back here with your latest results.

It's not entirely clear what kind of executable the network extension is meant to be …

Network Extensions providers are packaged as either an app extension or a system extension, depending on the platform and distribution channel. TN3134 Network Extension provider deployment shows all the options.

If you’re using Xcode, create your NE target from the appropriate target template, for example, choose File > New > New Target and then select iOS > Network Extension. Xcode will then do the right thing.

If you’re not using Xcode then, well, things get more complex. Lemme know in that case and I can offer some suggestions.

Share and Enjoy

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

What platform are you developing for? This matters because there are important platform-specific differences between iOS (and its ‘child’ platforms) and macOS when it comes to NE.

Also, I have some general advice on how to debug problems like this in Debugging a Network Extension Provider. I recommend that you start there and then, if you aren’t able to fix things, come back here with your latest results.

It's not entirely clear what kind of executable the network extension is meant to be …

Network Extensions providers are packaged as either an app extension or a system extension, depending on the platform and distribution channel. TN3134 Network Extension provider deployment shows all the options.

If you’re using Xcode, create your NE target from the appropriate target template, for example, choose File > New > New Target and then select iOS > Network Extension. Xcode will then do the right thing.

If you’re not using Xcode then, well, things get more complex. Lemme know in that case and I can offer some suggestions.

Share and Enjoy

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

I know you’ve been having problems posting replies. If that continues, please let me know. But, in general…

It’s better to reply as a reply, rather than in the comments; see Quinn’s Top Ten DevForums Tips for this and other titbits.

I don't need to disable system integrity to turn on debugging.

You don’t need to do that for an NE sysex either. Debugging a Network Extension Provider explains how I develop NE sysexes without disabling SIP.

IMO packaging your NE provider as a sysex make more sense on macOS, because macOS supports multiple users and the network stack is a shared resource.

Based on other comments it looks like you’re trying to build this outside of Xcode. That’s supported, but Xcode provides a lot of smarts and it’s good to take advantage of those smarts when you’re getting started. I recommend that you use Xcode for your initial bring up. Once you have the basics working, you can then map what Xcode does to your real app. I’ve found Xcode’s full build log to be super useful for that [1].

For example, you wrote:

Is there an equivalent main entrypoint for App Extensions when building a Objective-C application for example?

I wouldn’t even attempt to build an appex without looking at how Xcode does it.

not subject to the 15mb memory limit

I’m not sure where you got that number from [2], but such memory limits don’t apply on iOS.

Share and Enjoy

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

[1] I talk about how to do that in Command [something] failed with a nonzero exit code.

[2] I shared some iOS numbers here.

Thanks for your help! I've figured out what the main entrypoint needs to do for an app extension, here's the relevant Objective-C code:

// https://medium.com/@avaidyam/nsextension-pluginkit-a-brief-intro-2803be91a777
void NSExtensionMain() {
    @autoreleasepool {
        // Retrieve the default PKService instance
        id pkService = [NSClassFromString(@"PKService") defaultService];
        if (pkService) {
            // Call the internal run method with arguments
            // Note: This mimics the behavior described, but PKService's _defaultRun:arguments: is private API.
            // In practice, use public APIs like NSXPCListener.resume() in your extension's principal class.
            [pkService run];
        } else {
            // Fallback: Manually set up the NSXPCListener if PKService isn't available
            NSXPCListener *listener = [NSXPCListener serviceListener];
            // Set your delegate that conforms to NSXPCListenerDelegate
            // Example: listener.delegate = [[YourExtensionDelegate alloc] init];
            [listener resume];
        }
    }
}

The network extension starts up now and successfully connects (just dropping the packets right now but this should be enough to start from).

While digging into how things are implemented is fun, it’s not the path to long-term binary compatibility. Do not use the code you posted in a product. Rather, follow the advice that I posted earlier, that is, look at how Xcode builds the extension and do what it does.

If you do that you’ll see that the build transcript for the link step includes this:

…/XcodeDefault.xctoolchain/usr/bin/clang \
    …
    -e _NSExtensionMain \
    …

The causes the linker to set the main entry point to _NSExtensionMain, which is actually a symbol imported from Foundation:

% nm -m Packet.appex/Contents/MacOS/Packet
                 …
                 (undefined) external _NSExtensionMain (from Foundation)
                 …

This techniques ensures that your extension bootstrap code is revlocked to the system, so it’ll always do the right thing. If you embed the bootstrap in your product, it might fail on future systems.

IMPORTANT This is the link step for a packet tunnel provider app extension whose deployment target is macOS 15.5. You might see different commands if you build different app extension types or for a different deployment target.

Share and Enjoy

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

Network Extension (App Extension) Not Launching
 
 
Q