Network extension web content filter not working in iOS

I have added the Network extension to my app successfully for web content filtering. I have the entitlement file checked for the Networking key and capabilities added as well. Snippet from my entitlements file:

<key>com.apple.developer.networking.networkextension</key>
  <array>
  <string>content-filter-provider</string>
  </array>

I have also pushed web-content filtering payload from my MDM server which has my app's bundle identifier and type as plug-in. However, I have installed the app on a supervised device from my MDM server as an enterprise app. But none of my log statements get printed from the extension (I assume that the extension is not activated). I haven't configured any rules so far. Just want the extension to run. Am I missing something ? P.S. I am using XCode 9.2(objective-c) and device functioning on iOS 11.0.1.

Replies

For initial bring up I recommend that you not go the supervised device route, but instead exploit

NEFilterManager
ability to explicitly save filter configurations when called from a development build. The NEFilterManager docs explain how this works.

The most common cause of problems with initial bring up is entitlements. You should check the entitlements of both your

.app
and the
.appex
nested within that. Don’t rely on what Xcode shows you in the
.entitlements
file, check the entitlements of the built binaries using the process I described in Debugging Entitlement Issues.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Quinn,
I checked the entitlements of the built binaries as well and could see that the Network extension key was same in .app as well as the .appex entitlement files. Filter configuration is being pushed from the server as a .xml file to the device which has the payload required for NEFilterManager to save the configuration. And sadly , the application is still in the same state.

Hi Quinn ,
Update on the issue : I have the same error logs as the user had mentioned in this forum post here (https://forums.developer.apple.com/thread/31824). I am unable to understand what problem did the user had there and how did the user resolved it there . Copying the plugins into the framework folder instead of the plugins foler. Any assistance on this would be useful.

There’s some good news and some bad news here. The good news is that Xcode 9 introduced radically better support for building Network Extension providers. Specifically:

  • There’s a new Network Extension target template

  • The Capabilities editor now has a fully functional Network Extensions section

The bad news is that this makes the advice from old DevForums threads, anything before the release of Xcode 9, less than useful, because back in the day we were using much more primitive tools.

In terms of your specific issue, my advice is:

  • Check the entitlements (as I’ve described above)

  • Check the project layout

  • Check the various

    Info.plist
    files

I’ll discuss each of the last two points in section below

Here’s the expected file system layout for an app hosting Network Extension filter providers:

$ find QNEFilter.app
QNEFilter.app
… _CodeSignature stuff …
QNEFilter.app/embedded.mobileprovision
… Frameworks stuff …
QNEFilter.app/Info.plist
… Frameworks stuff …
… Storyboard stuff …
QNEFilter.app/PlugIns
QNEFilter.app/PlugIns/QNEFilterControlProvider.appex
… _CodeSignature stuff …
QNEFilter.app/PlugIns/QNEFilterControlProvider.appex/embedded.mobileprovision
QNEFilter.app/PlugIns/QNEFilterControlProvider.appex/Info.plist
QNEFilter.app/PlugIns/QNEFilterControlProvider.appex/QNEFilterControlProvider
QNEFilter.app/PlugIns/QNEFilterDataProvider.appex
… _CodeSignature stuff …
QNEFilter.app/PlugIns/QNEFilterDataProvider.appex/embedded.mobileprovision
QNEFilter.app/PlugIns/QNEFilterDataProvider.appex/Info.plist
QNEFilter.app/PlugIns/QNEFilterDataProvider.appex/QNEFilterDataProvider
QNEFilter.app/QNEFilter

Note:

  • Lines 10 and 15 show that both

    .appex
    es are within the
    PlugIns
    directory
  • Lines 14, 19 and 20, which are the actual executables; these should include the necessary entitlements, as discussed above

  • Lines 4, 12 and 17 show that each executable has an embedded provisioning profile; this profile should whitelist the necessary entitlements, as discussed above

With regards the various

Info.plist
files, here’s what I’d expect to see:
  • Nothing special in the main app’s

    Info.plist
    :
  • An

    NSExtension
    entry in the control provider’s
    Info.plist
    :
    $ /usr/libexec/PlistBuddy -c "print :NSExtension" QNEFilter.app/PlugIns/QNEFilterControlProvider.appex/Info.plist
    Dict {
        NSExtensionPointIdentifier = com.apple.networkextension.filter-control
        NSExtensionPrincipalClass = QNEFilterControlProvider.ControlProvider
    }

    Note:

    • The

      NSExtensionPointIdentifier
      property must be
      com.apple.networkextension.filter-control
      to indicate that this is a control provider.
    • The

      NSExtensionPrincipalClass
      combines the Swift module name (
      QNEFilterControlProvider
      ) and the class name within that module (
      ControlProvider
      ). If you’re using Objective-C, you just include the class name.
  • An

    NSExtension
    entry in the data provider’s
    Info.plist
    :
    $ /usr/libexec/PlistBuddy -c "print :NSExtension" QNEFilter.app/PlugIns/QNEFilterDataProvider.appex/Info.plist
    Dict {
        NSExtensionPointIdentifier = com.apple.networkextension.filter-data
        NSExtensionPrincipalClass = QNEFilterDataProvider.DataProvider
    }

    This is very like the control provider except that the extension point identifier is

    com.apple.networkextension.filter-data
    to indicate that it’s a data provider.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Quinn

I checked the presence of the appex files inside the plugins and the .appex file along with the network extension executable was inside the plugins folder only.
I checked for the network extension key and to my surprise , this got printed

$ /usr/libexec/PlistBuddy -c "print :NSExtension" MY_APPLICATION.app/PlugIns/MY_FILTER_CONTROL_EXTENSION.appex/Info.plist
Dict {
    NSExtensionPointIdentifier = com.apple.networkextension.filter-data
    NSExtensionPrincipalClass = MY_OBJECTIVE_C_CLASS
}

If you notice in Line 3 , it is filter data instead of filter-control.
However , I changed it to filter control and rechecked and it was fine this time. But the error is still persistent stating that

nesessionmanager(NetworkExtension)[13049] <Error>: -[NESMPluginRegistry copyInfoF:177  Plugin <BUNDLE_ID> does not have a bundle URL
nesessionmanager(NetworkExtension)[13049] <Error>: -[NESMFilterSession initialize:257  Failed to find plugin <BUNDLE_ID>


And one more thing , I am using only the FilterControl extension and not FilterData extension. Is it mandatory to use both the extensions for the plug-in to work as intended ?




Thanks and regards

Maneesh Sharma

Is it mandatory to use both the extensions for the plug-in to work as intended ?

Yes. If you’re just coming up to speed on Network Extension filter providers then I recommend that you watch WWDC 2015 Session 717 What’s New in Network Extension and VPN, which is a good high-level introduction to the overall architecture.

The NetworkExtension framework reference includes a lot of this info as well. Scroll down to the On-Device Network Content Filter and follow the three links that it contains.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Erica
I referred the conference video thoroughly and I implemented the FilterData as well with the Filter Control extension and the errors that were persistent went away. However, I get no log statements printed from either the Filter Data extension or the FilterControl extension. This happens when I work with my application as well as the QNEFilter application that you had provided for testing purpose. I have checked the entitlements file as well as adding the capabilities to the targets that I have. and everything seems to be at place in terms of provisioning profile and the entitlements, Can you please guide if I'm supposed to check anything else apart from that ?
Regards
Maneesh Sharma

However, I get no log statements printed from either the Filter Data extension or the FilterControl extension.

How are you looking for those log statements? The approach I recommend is to run the Console app on macOS, select your device on the left, and then build and save a search that filters for the log statements you care about (once of the reasons why all of my log statements contain

QNEFilter
is that this makes it easy to build a search to find them).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I use NSLog Statements to see the logs in the Apple Configurator device console. and I had searched for QNEFilter as well as the name of my application but could not find any log statements that were supposed to be printed.


Regards
Maneesh Sharma

Hmmm. There’s two possibilities here:

  • You’re somehow not finding the log statements.

  • The statements aren’t being run, presumably because your code isn’t being loaded.

One way to tell these apart is to put an

abort
call in your provider’s initialiser. If that runs, the system will generate a crash log (assuming you’re not attached with the debugger). If you see the crash log, you know your code is running, and you can then investigate why the logs are MIA. If you don’t see the crash log, your code isn’t running and you can investigate that.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello guys,
I have been running into same kind of issue. But this time it is for share extension.
I didn't yet get any answer on the forum i posted.


https://forums.developer.apple.com/message/280896#280896

@eskimo can you help finding the cause, as we showed the demo of our app to user(using different app extension).


I need to add the share extension inside my main app.

It’s unlikely that your share extension is suffering from the same problem as maneesh.sharma’s content filter extension; these are very different beasts. If you don’t find the answers you’re looking for here on DevForums, my recommendation is that you request one-to-one support by opening a DTS tech support incident.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello ,

I have used NEFilterDataProvider & NEFilterControlProvider in my app. It works fine in my development builds. But It's not working on the Live Builds (TestFlight build / AdHoc build).

Can you please help me to figure out the issue and how can i resolve it for all the users?

Is it possible to use (NEFilterDataProvider & NEFilterControlProvider) for any normal users? I mean can I upload it to the AppStore?

Thanks

[My filter] works fine in my development builds. But It's not working on the Live Builds (TestFlight build / AdHoc build).

I recommend that you start a new thread for that. Apply the Network Extension tag so that I see it.

Share and Enjoy

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