Lifecycle of a DNS Proxy network extension

We are developing an application to filter and block DNS traffic on macOS based on the NEDNSProxyProvider API and would like to comply with Apple's best practices, as well as be eligible for the App Store.
Currently, we understand the lifecycle of our extension as follows:
First,  the host app “installs” the network extension with an OSSystemExtensionRequest.activationRequest. After the user confirms the request and it succeeds, this starts the extension and executes the code in main.swift in the extension target, like in the SimpleFirewall example application. DNS traffic is not yet being routed to the proxy, however. For this post I would like to refer to the part that is running now as the “system extension” and the part that is not yet running as the “DNS proxy”.
To start the DNS proxy, you now need to enable it in the DNSProxyManager and save this to preferences.

If the user wants  to enable/disable DNS blocking from a setting in the host app, we imagine that they will be enabling/disabling the DNS proxy through DNSProxyManager. This leaves the system extension running.

Is it indeed the intended practice to leave the system extension running and performing basic tasks even while the DNS proxy is disabled, or is this “abusing” the system extension? Such basic tasks could for example include occasional communication with the backend server, and leaving the XPC listener for communication with the host app running and would hence still use (some) system resources even though the user has decided to disable the functionality.
Is the system extension guaranteed to keep running indefinitely and to be launched at reboot, even if the DNS proxy remains disabled?

Is it even possible to shut down the system extension completely, without requiring a restart (like OSSystemExtensionRequest.deactivationRequest might)?


Answered by Systems Engineer in 662787022

We are developing an application to filter and block DNS traffic on macOS based on the NEDNSProxyProvider API and would like to comply with Apple's best practices, as well as be eligible for the App Store.

First, the host app “installs” the network extension with an OSSystemExtensionRequest.activationRequest.

Since this is a Network System Extension and you want to distribute to the Mac App Store I will need to review what is and is not possible and get back to you on this. If you do not here from me on this, ping the post late next week sometime.


Regarding:

If the user wants to enable/disable DNS blocking from a setting in the host app, we
imagine that they will be enabling/disabling the DNS proxy through DNSProxyManager. This
leaves the system extension running.

If you mean that you are updating the network configuration for NEDNSProxyManager then you would stop and start the NEDNSProxyProvider and this would stop/start your Network System Extension also. If you are sending information to your provider from the container app then you could look at sending this information similar to how SimpleFirewall does it, but there is not method like sendProviderMessage and handleAppMessage on the packet tunel side.


Regarding:

Is it indeed the intended practice to leave the system extension running and performing
basic tasks even while the DNS proxy is disabled

If your Network System Extension is up and running and processing flows, then it is fine to keep it running. If it is not processing flows or performing the task that it was designed to do by the system then it should not be running.

Regarding:

Is the system extension guaranteed to keep running indefinitely and to be launched at
reboot, even if the DNS proxy remains disabled?

A functioning Network System Extension should start up again after reboot. If it is disabled there is no guarantee that this will happen.

Regarding:

Is it even possible to shut down the system extension completely, without requiring a
restart (like OSSystemExtensionRequest.deactivationRequest might)?

Typically submitting a deactivationRequest is the workflow here. However, you can also stop your container app, and delete your container app. This typically provokes that deletion of your Network System Extension as well.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Accepted Answer

We are developing an application to filter and block DNS traffic on macOS based on the NEDNSProxyProvider API and would like to comply with Apple's best practices, as well as be eligible for the App Store.

First, the host app “installs” the network extension with an OSSystemExtensionRequest.activationRequest.

Since this is a Network System Extension and you want to distribute to the Mac App Store I will need to review what is and is not possible and get back to you on this. If you do not here from me on this, ping the post late next week sometime.


Regarding:

If the user wants to enable/disable DNS blocking from a setting in the host app, we
imagine that they will be enabling/disabling the DNS proxy through DNSProxyManager. This
leaves the system extension running.

If you mean that you are updating the network configuration for NEDNSProxyManager then you would stop and start the NEDNSProxyProvider and this would stop/start your Network System Extension also. If you are sending information to your provider from the container app then you could look at sending this information similar to how SimpleFirewall does it, but there is not method like sendProviderMessage and handleAppMessage on the packet tunel side.


Regarding:

Is it indeed the intended practice to leave the system extension running and performing
basic tasks even while the DNS proxy is disabled

If your Network System Extension is up and running and processing flows, then it is fine to keep it running. If it is not processing flows or performing the task that it was designed to do by the system then it should not be running.

Regarding:

Is the system extension guaranteed to keep running indefinitely and to be launched at
reboot, even if the DNS proxy remains disabled?

A functioning Network System Extension should start up again after reboot. If it is disabled there is no guarantee that this will happen.

Regarding:

Is it even possible to shut down the system extension completely, without requiring a
restart (like OSSystemExtensionRequest.deactivationRequest might)?

Typically submitting a deactivationRequest is the workflow here. However, you can also stop your container app, and delete your container app. This typically provokes that deletion of your Network System Extension as well.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Dear Matt Eaton,
Thank you for your quick and helpful response, as always.

Indeed we are talking to our network extension by adapting what the SimpleFirewall app does to include a method like sendProviderMessage added to the ProviderCommunication protocol as you describe.

From your answer I would expect that the process of the network extension is terminated when the NEDNSProxyProvider disabled using the NEDNSProxyManager. Experimenting with the SimpleFirewall application, however, I see this process still alive after disabling the FilterProvider and even after stopping the debugging session in xcode (I set systemextensionsctl developer on to make running the network extension from the xcode debugger possible). From what I can see the process seems to keep running until a reboot, and then it is either launched again or not depending on whether the filter was enabled or disabled.
Adding an object that periodically logs that it is still alive to the network extension’s main.swift also shows that the process keeps running until a reboot. Hence my confusion about how to terminate the network extension process, since this doesn’t seem to be done by disabling the filter.

We are unsure whether this process continuing to run without interruption independently of enabling/disabling the ProxyProvider is something we can rely on, or whether the OS might at some point decide to terminate it since the provider that it belongs to has been disabled for some time.
Also, we are unsure about whether it is appropriate to do occasional communication with our backend from this process even when the ProxyProvider is disabled, for example to keep configuration up to date.
Pinging this post as suggested by @meaton

From your answer I would expect that the process of the network extension is terminated when the NEDNSProxyProvider disabled using the NEDNSProxyManager.

If you are disabling the provider then it will not terminate the Network System Extension. The provider will just be disabled. To terminate the Network System Extension, which is what is being used in the SimpleFirewall app, you will need to either submit a deactivationRequestForExtension with the OSSystemExtensionRequest class, or actually terminate and delete the container app that is running in the /Applications directory. Running this with Developer Mode on from Xcode complicates the deletion a bit because you need to dig through the file system to make sure you are deleting the actual container app being run from Xcode. Building your project on a test machine and then dragging the container app into the /Applications directory and running from there should give you a clean testing process.

A Network System Extension is expected to exist between reboots of the system. It can even exist while there is no user logged in. All of the Network Extension types can be run as a Network System Extension on macOS except for NEDNSSettings, so you can expect the same behavior with a Network Extension like NEAppProxyProvider.

Pinging this post as suggested by @meaton

Unfortunately I do not have a solid update on this.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
I did want to update the thread that the distribution guidelines for DNS Proxy Provider have now been updated.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Lifecycle of a DNS Proxy network extension
 
 
Q