Yet another dumb Network Extension (App Proxy Provider) question!

This is mainly caused by my having misread the documentation, but then the behaviour seemed to match my misreading, but then suddenly it didn't.

Specifically, I had thought that handleNewFlow could return false to indicate "I'm not interested in this particular connection," but it turns out to close it (killing some but not all? networking on the system) if I always return false. The specific thing I was trying to do was exclude certain apps from being proxied (without building a list of all apps, to filter them all).

So my question is two-fold: how dumb was I to misread the documentation, and is there a way to do what I was trying to do? (Short of, say, monitoring all new processes as they start, adding them to the NEAppRule set, and deliberately excluding the ones I wanted to whitelist.)

how dumb was I to misread the documentation

You are not dumb at all. There are many places where we need to do better with the documentation and this is one of them. In the context of handleNewFlow, when the documentation states: Return false to indicate that the flow should be closed, this means that returning false with discard the flow and it will not traverse the operating system. When you use NEAppProxyProvider you need to return true for everything to make sure that there are no networking interruptions for your user, unless you specifically do not want the user consuming a flow.

Regarding:

is there a way to do what I was trying to do? (Short of, say, monitoring all new processes as they start, adding them to the NEAppRule set, and deliberately excluding the ones I wanted to whitelist.)

Selectively proxying flows is only available on macOS for the NETransparentProxyProvider,, which is a sub-class of NEAppProxyProvider. Basically, if you are using macOS you can just replace the provider definition of NEAppProxyProvider with NETransparentProxyProvider and then return false for flows you do not wish to proxy and these flows will traverse the operating system.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

I changed it to subclass NETransparentProxyProvider, and my handleNewFlow method isn't being called at all. And all networking (even a ping I started beforehand) dies.

It sounds like the provider may be crashing or just not working at all? NETransparentProxyProvider is only available on macOS 11.0+. You will need to support NEAppProxyProvider if you need to work with macOS 10.15.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

No, it occurred to me in my sleep that it's behaving as if I told it to install a packet proxy and not an App Proxy. So I no doubt did something fairly wrong; I just need to figure out what that is. (If you have any common suggestions, that'd be great, otherwise I'll need to double check the entitlements, the Info.plists, the proxy setups for networks, how I am activating it, and how I am starting it.)

Ok, I got it working in its minimal fashion again (which is to say, at this point, handleNewProxy just logs each flow and then returns false). I had proto.includeAllNetworks = true and removed it. Yay.

However... a ping I have running fails whenever I have it connected. I can continue to load websites in Safari, so I didn't breakall networking this time.

However... a ping I have running fails whenever I have it connected

Sounds like you are now in need of Handling Flow Copying in your proxy now. This should hopefully allow your connection to proceed to it's destination. Now, if you are truly talking about ICMP here that is another story as the NEAppProxyProvider supports TCP and UDP only.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Right, NEAppProxyProvider only supports TCP and UDP, so I was very surprised when the already-running ping was interrupted.

However, if I turned it into two rules:

        let host = NWHostEndpoint(hostname: "", port: "0")
        let udpRule = NENetworkRule(destinationNetwork: host, prefix: 0, protocol: .UDP)
        let tcpRule = NENetworkRule(destinationNetwork: host, prefix: 0, protocol: .TCP)

        settings.includedNetworkRules = [udpRule, tcpRule]

then the ping was unaffected. (Before I'd had one rule, with .any.)

The ping failure, btw, was sendto: No route to host.

However, if I turned it into two rules:

Right because now you are specifically targeting TCP and UDP.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Yes, but if it only handles TCP and UDP, then why does .any cause it to break things? That should still only be TCP and UDP, shouldn't it?

Yes, but if it only handles TCP and UDP, then why does .any cause it to break things?

Yeah, the documentation for .any does actually state for TCP and UDP only. Okay, if you can see that your ping request goes over ICMP and you are still seeing this:

However... a ping I have running fails whenever I have it connected. I can continue to load websites in Safari

Then I would open a bug report to support ICMP.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Yet another dumb Network Extension (App Proxy Provider) question!
 
 
Q