Can't create outbound TCP connection from NEFilterDataProvider

I'm implementing an NEFilterDataProvider subclass on iOS, and am trying to make outbound network connections from it. Is this supposed to work?

URLSession doesn't do it (the connection is never established); perhaps that's by design, considering NEProvider offers createTCPConnection(to:enableTLS:tlsParameters:delegate:) which seems to be designed for the job. However, calling this method doesn't work either; the connection never completes, and alternates between connecting and waiting state while the logging things like this:

nw_endpoint_handler_start [C8 Hostname#2169586f:443 initial path ((null))]

nw_endpoint_handler_reset_mode [C8 Hostname#2169586f:443 waiting path (unsatisfied (Path was denied by NECP policy), interface: en0, ipv4, dns)] reset

nw_connection_report_state_with_handler_on_nw_queue [C8] reporting state waiting

And on the first waiting state, the NWTCPConnection's error shows:

The operation couldn’t be completed. (kNWErrorDomainDNS error -65563 - DNS Error: ServiceNotRunning)

which seems a bit strange because I'm connecting to an IP address (no DNS lookup required).

Am I overlooking something? Or is an NEFilterProvider prohibited from actually making its own outbound connections?

thanks, -ben

I'm implementing an NEFilterDataProvider subclass on iOS, and am trying to make outbound network connections from it. Is this supposed to work?

No. NEFilterDataProvider on iOS has a very restrictive Sandbox and because of this network connections for this provider on iOS will not work. In iOS try you network connection in NEFilterControlProvider instead.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

I don't know why my reply shows up as one long paragraph

Comments aren’t designed for creating long replies; it’s better to just put your reply in the badly named Your Answer box [1].

It would be helpful if the docs for NEFilterDataProvider mentioned that its implementation of the stream-creation methods is designed to fail.

The docs do explain the philosophy behind this. Consider this quote from the top-level Content Filter Providers page:

A content filter consists of two providers that work in close cooperation:

  • A filter data provider receives user network content and examines that content to determine whether to block or allow it.

  • A filter control provider passes configuration information to the filter data provider to allow that provider to do its job.

This separation exists to guarantee user privacy. The filter data provider runs in a very restrictive sandbox that prevents user network content from escaping that provider. The filter control provider has a less restrictive sandbox but doesn’t have access to user network content. By combining these providers, your content filter has access to the network but can’t use that access to export user network content.

For example, your filter control provider might download a set of filtering rules and save them to a shared app group. Your filter data provider has read-only access to that app group, allowing it use those rules to filter content but still preventing it from exporting user network content.

Note that this only applies to iOS. The filter provider story on macOS is less restrictive. Alas, we haven’t updated the docs to cover that development.


Can you suggest an alternative approach?

No. The iOS filter provider architecture was specifically designed to prevent what you’re trying to do. This makes sense when you consider the name: A content filter provider is for filtering content. It was not designed to enable traffic monitoring.

Share and Enjoy

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

[1] One day we’ll fix that, I swear (r. 80839588).

Note that this only applies to iOS. The filter provider story on macOS is less restrictive.

This is something that I failed to mention. As Quinn is pointing out, the Sandbox story on macOS is much different than iOS. NEFilterDataProvider on iOS is designed to make allow you provider to see traffic and make a NEFilterNewFlowVerdict decision, that is all.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Comments aren’t designed for creating long replies; it’s better to just put your reply in the badly named Your Answer box [1].

I guess I should have figured that out from other forum postings. (Still pine for the simpler lists.apple.com days of yore.) Glad to know I'm not the only one misled by the “Your Answer” heading though. :)

The docs do explain the philosophy behind this. Consider this quote from the top-level Content Filter Providers page:

I had read that overview in the past, but had forgotten the caveats once I'd moved on to the API documentation and appeared to be getting somewhere. That does seem adequately explicit.

Note that this only applies to iOS. The filter provider story on macOS is less restrictive. Alas, we haven’t updated the docs to cover that development.

In fact we've already deployed such an implementation on MacOS, with the System Extension EndpointSecurity entitlement, to much success. I was hoping a similar approach could be used on iOS. There is no similar entitlement available to elevate the sandbox privileges, I suppose?

Would a Packet Tunnel Provider be a reasonable alternative approach?

Would a Packet Tunnel Provider be a reasonable alternative approach?

Not if you are going to use it for any sort of content filtering action. See TN3120 Expected use cases for Network Extension packet tunnel providers.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

The objective here is to passively observe flows (or packets), inbound and outbound, for the purpose of auditing and security monitoring.

I can see that a packet tunnel provider sans VPN endpoint won't afford this (even setting aside whether or not it's expected or recommended), without a means to redeliver the packets to the physical interface, given that binding to a raw socket is prohibited on iOS. It also appears that it's not possible to set up an IP-level NWConnection (by trying to set a nil defaultProtocolStack.transportProtocol on its NWParameters, for example, which has no effect).

Can you suggest another approach?

Following up on this, I sought advice at a WWDC22 Security Lab this week. The engineer I spoke with (Pepjin B.) advised filing a Feedback Assistant report describing our needs, and suggested it would be most effective to do so from an AppleSeed For IT managed Apple ID. As I don't have an AS-for-IT account myself I had a colleague do so on my behalf; the ticket is FB10144188.

Looking forward to what may come of this!

Can't create outbound TCP connection from NEFilterDataProvider
 
 
Q