I would like something like the folllowing:
Intercept and modify all DNS traffic (port 53)
Intercept and modify TCP and UDP flows going to a specific subnet.
An NEAppProxyProvider seems like an obvious choice since you can setup various rules for what you want to intercept. For example that you want to intercept traffic going to specific subnets and everything going to port 53. Also, it intercepts TCP flows rather than raw IP packets which is simpler. However:
According to the documentation for NEAppProxyProviderManager (https://developer.apple.com/documentation/networkextension/neappproxyprovidermanager ), an AppProxy can only be used for per-app VPN routing. So I guess an AppProxy is not an option given that I need to intercept traffic from all applications?
There is a (to me) somewhat mysterious class NETransparentProxyManager (https://developer.apple.com/documentation/networkextension/netransparentproxymanager ). It is not clear to me how NETransparentProxyManager is different from NEAppProxyProviderManager. But I assume that NETransparentProxyManager can also only be used to intercept traffic per-app?
One thing that puzzles me is that if NEAppProxyProviderManager and NETransparentProxyManager can only be used to intercept traffic on a per App basis, then why does NEAppProxyProvider (https://developer.apple.com/documentation/networkextension/neappproxyprovider ) have a routingMethod member (https://developer.apple.com/documentation/networkextension/netunnelprovider/1405979-routingmethod )? Shouldn’t this value always be ‘sourceApplication’? Perhaps it is because it is in the super class NETunnelProvider which is shared with NEPacketTunnelProvider. I did try to create an NEAppProxyProvider with an NETransparentProxyManager and the routingMethod member did get a value of ‘sourceApplication’
I cannot intercept all traffic to port 53 unless I intercept all subnets.
If there is some traffic to the intercepted destination IP subnets which I don’t want to intercept anyway, I will have create my own sockets and send the data from the raw TCP and UDP packets on them (which may be challenging as the local ports and source IPs may change when doing this)