How to implement Content Filter in macOS

I've implemented a content filter in iOS using Network Extension with help of NEFilterDataProvider, NEFilterPacketProvider. Which works fine, getting all requests and blocking based on the requirement.

But When I implement the same this in macOS, getting NEFilterManager.shared().isEnabled true means it's connected, still able to access all the sites.

I notice one thing that for macOS in NEFilterProviderConfiguration, "filterBrowsers is not supported on macOS" is deprecated What does it mean?

I've implemented a content filter in iOS using Network Extension with help of NEFilterDataProvider, NEFilterPacketProvider.

NEFilterPacketProvider on iOS? Did you mean NEFilterControlProvider?

Regarding:

I notice one thing that for macOS in NEFilterProviderConfiguration, "filterBrowsers is not supported on macOS" is deprecated What does it mean?

Right, as the property comments state, filterBrowsers is not supported on macOS. It will compile but will not work on macOS.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

How do I implement a working demo? I'm building a mac application that blocks URLs based on categories. For eg. If a user tries to open vimeo.com, It must be blocked. Is there any alternative to achieve that?

Right, so on macOS with NEFilterDataProvider if you know the address or hostname and it's always going to be static then you can setup a default NEFilterRule for this traffic. For example:

let exampleRule = NENetworkRule(
	remoteNetwork: NWHostEndpoint(hostname: "example.com", port: "0"),
	remotePrefix: 0,
	localNetwork: nil,
	localPrefix: 0,
	protocol: .TCP,
	direction: .any
)
let filterRule = NEFilterRule(networkRule: exampleRule, action: .drop)

The rule above will drop all traffic to example.com if that is what you want. The same can be done to allow traffic. Now, if you need to filter traffic further, you would create a NENetworkRule that catches all TCP traffic with the action to filterData. This rule will give your provider all TCP traffic in handleNewFlow:

let exampleRule = NENetworkRule(
	remoteNetwork: nil,
	remotePrefix: 0,
	localNetwork: nil,
	localPrefix: 0,
	protocol: .TCP,
	direction: .any
)
let filterRule = NEFilterRule(networkRule: exampleRule, action: .filterData)

The gotcha here is that you will receive an address for the inbound or outbound traffic and it will be up to you to decide whether this is a known address to allow or if it should be investigated further.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

This is FilterDataProvider class. I tried https://www.vimeo.com & vimeo.com This is the URL of demo. https://github.com/anismansuri63/MacFilter

class FilterDataProvider: NEFilterDataProvider {
  override func startFilter(completionHandler: @escaping (Error?) -> Void) {
    let exampleRule = NENetworkRule(
      remoteNetwork: NWHostEndpoint(hostname: "https://www.vimeo.com/", port: "0"),
      remotePrefix: 0,
      localNetwork: nil,
      localPrefix: 0,
      protocol: .TCP,
      direction: .any
    )
    let filterRule = NEFilterRule(networkRule: exampleRule, action: .drop)

    let filterSettings = NEFilterSettings(rules: [filterRule], defaultAction: .drop)
    apply(filterSettings) { error in
      if let applyError = error {
        os_log("Failed to apply filter settings: %@", applyError.localizedDescription)
      }
      completionHandler(error)
    }
  }
  override func stopFilter(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
    completionHandler()
  }

  override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict {
    return .drop()
  }
}

If your have tried with a remoteNetwork that contains a NWHostEndpoint that looks like this:

NWHostEndpoint(hostname: "example.com", port: "0")

Without https:// and it still does not work then try opening a TSI so someone in DTS can evaluate this further.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

So we can't use NEFilterControlProvider in MacOS to filter content at the flow layer as opposed to the packet layer?

So we can't use NEFilterControlProvider in macOS to filter content at the flow layer as opposed to the packet layer?

That’s incorrect. Lemme explain:

  • iOS supports filter control providers and filter data providers.

  • This separation exists to enforce a privacy policy. See the Overview section on this page.

  • macOS does not enforce this policy, so there is only the filter data provider. Like the iOS filter data provider, this works at the flow layer.

  • Separately, macOS also supports a filter packet provider.

  • macOS also supports a transparent proxy provider, which gives you even more control.

For an overview of NE provider types and their deployment options, see TN3134 Network Extension provider deployment.

Share and Enjoy

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

How to implement Content Filter in macOS
 
 
Q