Am I setting up routes and DNS for a private network properly?

macOS uses a system configuration database to maintain things like which DNS servers to use, and what domains those serves are used for. This database is exposed to the user through the interactive scutil program.

To update DNS servers and search domains, the simplest invocation of this tool would happen like this:

[root@host]$ scutil
> d.init
> d.add ServerAddresses * 172.16.1.10
> d.set State:/Network/Service/UniqueKey/DNS
> quit

To perform this configuration change, I created two expect scripts, one to load the configuration and the other to unload the configuration.

Here's the script to load the DNS configuration (note the "Corporate-VPN" part of the key which is the unique identifier for this configuration element):

#!/opt/local/bin/expect -f
set timeout -1
spawn /usr/sbin/scutil
match_max 100000
expect "> "
send -- "d.init\r"
expect "> "
send -- "d.add ServerAddresses * $env(VPNHOST)\r"
expect "> "
send -- "d.add SupplementalMatchDomains * intranet.company.com services.company.com\r"
expect "> "
send -- "set State:/Network/Service/Corporate-VPN/DNS\r"
expect "> "
send -- "quit\r"
expect eof

And then the script to unload the configuration:

#!/opt/local/bin/expect -f
set timeout -1
spawn /usr/sbin/scutil
match_max 100000
expect "> "
send -- "remove State:/Network/Service/Corporate-VPN/DNS\r"
expect "> "
send -- "quit\r"
expect eof

There is still plenty of tidy-up to do here (notably handling errors).

The previous method I wrote using the Resolvers system remains below. It still works but it's not the recommended method.


As per Gordon's comment, using the resolver system provided a solution:

#!/bin/sh
# Alters routing and DNS to use private network routes and DNS for
# private network destinations

networks=( "10.10.0.0/16" "192.168.20.0/24"  )
work_domains=( "intranet.company.com" "services.company.com" "customer.org" )
gateway=172.16.1.10

if [ "$1" = "up" -o "$1" = "on" -o "$1" = "start" ] ; then
    echo "Setting up private configuration"
    for net in ${networks[@]}; do
        /sbin/route add -net $net -gateway $gateway
    done
    for netname in ${work_domains[@]}; do
        echo "nameserver $gateway" >> /etc/resolver/$netname
    done
elif [ "$1" = "down" -o "$1" = "off" -o "$1" = "stop" ] ; then
    echo "Shutting down private configuration"
    for netname in ${work_domains[@]}; do
        rm /etc/resolver/$netname
    done
    for net in ${networks[@]}; do
        /sbin/route delete -net $net -gateway $gateway
    done
else
    echo "Usage: $0 (start|stop)"
fi
dscacheutil -flushcache