How to implement a full-tunnel packet tunnel provider that relies on the system DNS resolver?

Assume a VPN client with a packet tunnel provider is implemented where the NEPacketTunnelNetworkSettings of the tunnel indicate that all traffic must be routed through it (includedRoutes=0.0.0.0/0).

One of our requirements is that we don't want to force our customers to use a DNS server operated by the VPN. Some customers want to route their traffic over the VPN, but operate their own DNS servers. Other customers might be using a DNS proxy provider on their Mac. Others might have a DoH/DoT configuration profile installed. We essentially would like all traffic to be routed through the VPN, but DNS resolution should use the DNS resolver that the Mac would have used if the VPN were not connected.

We considered two potential solutions to implement this.

Firstly, we tried setting in the configuration an NEDNSSettings object where the nameservers field is set to an empty array. In our testing, it appears that such setup (includedRoutes=0.0.0.0/0 with nameservers=[]) results in no DNS resolver appearing in /etc/resolv.conf. scutil --dns reports that no global resolver is set on the system when such configuration is applied. DNS resolution on the system is entirely broken when these settings are applied. This fundamentally makes sense: we're telling the system that all traffic must go through the VPN interface, but also the VPN interface provides no DNS resolver! Interestingly, with this setup DNS resolution is still possible if a DNS proxy provider or DoH/DoT configuration profile is installed.

An alternative approach we considered is based on the fact that we are able to determine the IP address(es) of the local DNS resolvers on the network. We could set those resolver IPs in the NEDNSSettings configuration. For instance, if the LAN of the Mac provides a DNS forwarder at 192.168.1.1, we could pass nameservers=["192.168.1.1"] in the NEDNSSettings . Then, in NEPacketTunnelNetworkSettings we can set includedRoutes=["0.0.0.0/0"] and excludedRoutes=["192.168.1.1/32"]. This setup works, as all traffic goes through the VPN, except that DNS queries are forwarded to 192.168.1.1. However, this doesn't properly handle a DNS proxy provider or DoH/DoT configuration profile installed on the Mac. With this setup, DNS resolution ignores the DNS proxy/encrypted DNS configuration, and all DNS queries are always sent to 192.168.1.1. We could fix this if our network extension was able to detect that such provider/configuration profile is enabled and switch back to specifying an empty array of resolvers, but of course privacy consideration prevent such information from being available to a sandboxed network extension.

Is there a way for developers in NEDNSSettings to indicate that we want the system DNS resolver to handle all queries as if our VPN hadn't been installed?

I don’t see a good way to achieve all of your goals, so I’m going to recommend that you file an enhancement request for an API to do this. Make sure to include an explanation for the rationale behind your goals.

Please post your bug number, just for the record.

Share and Enjoy

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

How to implement a full-tunnel packet tunnel provider that relies on the system DNS resolver?
 
 
Q