Get DNS servers from the system

Hello!

I'd like to ask about the best way of getting a list of DNS servers from the system (iOS & macOS).

Why?
I am using NEPacketTunnelProvider to implement a VPN app. When a device joins a network with a Captive Portal and the VPN is on, the VPN should redirect DNS queries to the DNS servers that were received from the network's DHCP server. So that my VPN is able to correctly reroute the traffic which is not blocked by the network's gateway and the Captive Portal landing page is served.

When I don't do anything, the traffic goes to the tunnel and the tunnel's encrypted traffic is then dropped by the gateway serving the Captive Portal.

When I temporarily turn off the VPN, opt out of all the traffic or pass the traffic to the system resolver, the traffic gets affected by other network settings (like DNSSettings) which leads to the same situation - the user not being able to authenticate with the Captive Portal.

So far, I have tried multiple ways, including res_9_getservers but unsuccessfully. As a part of my investigation, I have found out that the /etc/resolv.conf file is not populated with DNS servers until the Captive Portal is acknowledged by the user which makes getaddrinfo unusable to achieve my goal. But I am not sure if that's a bug or intended behavior.

Thank you for your help!

I'd like to ask about the best way of getting a list of DNS servers from the system (iOS & macOS).

There isn’t a good way to do this on either platform. That’s because the concept of “a list of DNS servers” doesn’t make sense on our Apple systems. DNS servers can be scoped, based on a variety of criteria, and so there’s no one single list.

On macOS you can get a lot more insight into this via System Configuration framework, but in the SC preferences and the SC dynamic store. Those APIs aren’t available on iOS.

Regarding your big picture issue, if the device is on a captive network and you’re unable to communicate with your VPN server, shouldn’t you just take your tunnel down?

Share and Enjoy

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

Hello Eskimo!
Thank you for your answer! Basically, what I am looking for is "if Captive Network gateway provides DNS servers to use, use them for clearing Captive Portal". So maybe even more close to what ipconfig getpacket en0 returns, but using some API that's available on both platforms.

Regarding the bigger picture - you're right and that's what we do when our VPN app is running as the only VPN in the system. But we'd like to support compatibility with other network settings that can be pushed via configuration profile (like DNSSettings with DNS over HTTPS payload).

I have found this question about the system behaviour when the device is connected to the Captive Network and DoH settings are in place which is tightly connected to what we're trying to resolve. If OS would be able to clear the captive portal with DoH payload, we can just continue to take down the tunnel and leave it on the system.

Get DNS servers from the system
 
 
Q