NEDNSProxyProvider handleNewFlow example code

Class: NEDNSProxyProvider
Function: handleNewFlow(_ flow: NEAppProxyFlow)

Hello, I've set up an macOS application containing a system extension which now receives all DNS requests. This is all good and what I want to happen. However, I'm not sure how to proceed with actually handling the NEAppProxyFlow.

If someone could provide some example code that would handle the DNS requests in the same way in the case that I did not have my DNS requests go through NEDNSProxyProvider that would be wonderful.

Please feel free to ask for clarification if needed. Thank you!


Answered by Systems Engineer in 644793022

How specific can I get with the configuration? For example, can I only handle flows which are DNS requests that contain certain hostnames?

Setup the NENetworkRule's and set them as includedNetworkRules to NETransparentProxyNetworkSettings to capture your DNS flows. Then once the provider is receiving new flows in handleNewFlow, you must decide if these are flows you want to proxy. This is something you need to do. Once you have done that use the rules I have provided for you on this thread.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

If someone could provide some example code that would handle the DNS requests in the same way in the case that I did not have my DNS requests go through NEDNSProxyProvider that would be wonderful.

For a NEDNSProxyProvider there is no selective proxying. If you are claiming the flow by returning true, then you will need to proxy the flow. If you are returning false then the flow will be discarded.

I am actually in the process of formally documenting the flow copying process right now, but a brief overview is:

1) Decide if your provider is handling the flow. Return true or false.

2) If the provider is handling the flow then the a remote connection needs to be setup to handle outbound data. In this case I will use NWConnection as an example.

3) Once the remote side of the connection goes into the ready state, it's time to open the local flow to handle the inbound data. In this case it would be for NEAppProxyUDPFlow.

4) Then an inbound copier needs to be created to read from the remote side of the connection and write to the local side on the connection.

5) Then an outbound copier needs to be created to read from the local side of the connection and write to the remote side of the connection.

6) Implementing Flow Control is the next thing to consider during this process to ensure that your provider does not become overloaded and buffer too much data. A great rule of thumb is to not read again before the write has taken place.

7) Last but not least, be sure to mark the local flows as closed and cancel the remote side of the connection after complete.

For further information on the read/write APIs in the flow copying process see NEAppProxyUDPFlow and NWConnection.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

For a NEDNSProxyProvider there is no selective proxying.

Is there a way to do selective proxying?

I am actually in the process of formally documenting the flow copying process right now, but a brief overview is:

Out of curiosity, when would this be ready and published?

In the case of NEAppProxyTCPFlow how would the process look like?
Also, does / how does NEDNSSettingsManager have a place in all of this?

Thank you for your help.

Is there a way to do selective proxying?

For NEDNSProxyProvider no, if you commit to proxying traffic you will need to proxy all traffic to resolvers of your choice.

Out of curiosity, when would this be ready and published?

Hopefully soon, but I do not have a formal date.


In the case of NEAppProxyTCPFlow how would the process look like?

NEAppProxyTCPFlow is a lot more straight forward because it represents a single TCP connection whereas NEAppProxyUDPFlow represents a sequence of incoming and outgoing datagrams identified by a local IP address and port and a remote IP address and port.

Also, does / how does NEDNSSettingsManager have a place in all of this?

Using NEDNSSettingsManager is great because this allows you to configure DoH or DoT to resolver of your choice to handle your DNS traffic without requiring a Network Extension. Keep in mind that the difference between NEDNSSettingsManager and NEDNSProxyProvider is that the proxy provider allows you to have control over DoH or DoT and allows you to direct the DNS flows to specific resolvers by hand. You will just have to build all of this logic out yourself.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Thank you for your clarification.

I read here that I would be able to use NEAppProxyProvider to handle DNS queries.

After some more research, I stumbled upon NETransparentProxyManager, could I use this instead in combination with NETransparentProxyNetworkSettings to selectively handle DNS queries for certain hostnames?

My use case is this:
  1. Mac Client goes to "test.nonpublic.com" which does not exist within the public internet. (I will have a list of hostnames that should have their DNS requests intercepted)

  2. This DNS request should be intercepted and the request should be sent through an established web socket connection to be handled.

  3. All other DNS requests should not be handled by the application

Note: I only want to deal with DNS queries. No other network traffic is of concern to me as of this moment.

If this is the case, is there a code snippet you can provide that applies this configuration to NETransparentProxyManager?
If not, could you advise on how I should proceed to implement the behaviour I want?

After some more research, I stumbled upon NETransparentProxyManager, could I use this instead in combination with NETransparentProxyNetworkSettings to selectively handle DNS queries for certain hostnames?

You have to be careful with the symbol names here; I think what you mean is "NETransparentProxyProvider to selectively handle DNS queries," instead of NETransparentProxyManager.

Using NETransparentProxyManager and NETransparentProxyNetworkSettings would still be classes used wether you are working with NETransparentProxyProvider or NEAppProxyProvider but only NETransparentProxyProvider allows you to selectively handle flows in macOS 11. In macOS 10.15 with NEAppProxyProvider you will need to commit to handling all of the flows.


If this is the case, is there a code snippet you can provide that applies this
configuration to NETransparentProxyManager?
If not, could you advise on how I should proceed to implement the behaviour I want?

There is no publicly available sample code here, but if you need help, open a TSI and I can help you with any issues you run into getting your project setup.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Sorry, what I meant was indeed NETransparentProxyProvider. In what ways can I selectively handle flows with NETransparentProxyProvider? How specific can I get with the configuration? For example, can I only handle flows which are DNS requests that contain certain hostnames?
Accepted Answer

How specific can I get with the configuration? For example, can I only handle flows which are DNS requests that contain certain hostnames?

Setup the NENetworkRule's and set them as includedNetworkRules to NETransparentProxyNetworkSettings to capture your DNS flows. Then once the provider is receiving new flows in handleNewFlow, you must decide if these are flows you want to proxy. This is something you need to do. Once you have done that use the rules I have provided for you on this thread.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
NEDNSProxyProvider handleNewFlow example code
 
 
Q