DNS Resolution on macOS Sierra
Posted: Thu Feb 01, 2018 3:52 pm
I had a previous generation MacBook Pro (it also ran Sierra) that I could force DNS resolution with local servers using the networksetup -setdnsservers operation before and after (to set and then unset DNS servers) the openvpn operation in a tidy little shell script. I know this isn't the cleanest way to do things, but it worked, and I was happy. Now I have the current generation (the one with the stupid touch bar that has the stupid virtual escape key which makes vi really fun) MBP (still macOS Sierra), but this script no longer works. The DNS servers get set, but I am entirely unable to perform local name resolution when I connect. So, I looked into it and found that I could add an interface up/down script pair that is a wrapper for scutil to make the resolver changes, but that REALLY doesn't work... I'm guessing I have a bum script because if I run scutil --dns, all the resolvers are gone. And when it runs the down script, the network configuration gets all kinds of screwed up... the settings panel insists that the Wi-Fi connection can't get an IP address even though all network services continue to function as normal. To fix it, I have to reboot. I even tried downloading the GUI client and stop using my OVPN scripts, but that also doesn't work any more, which really confuses me. I know that the server is handing out DNS servers because Windows hosts work just fine. The only thing I've noticed that seems weird is that the MBP stubbornly hangs on to a configuration that points all DNS queries to the local name resolver. I don't know if the old machine also did that or not, but I thought it might be a data point.
from my ovpn config file:
[oconf]client
pull
script-security 2
up /Library/openvpn/client.up.osx.sh
down /Library/openvpn/client.down.osx.sh[/oconf]
my up script:
[script]#!/bin/bash -x
# client.up.osx.sh - SCRIPT Set name resolution options using the DHCP-delivered
# configuration coming over the openvpn tunnel
# Copyright (c) 2005 by OpenVPN Solutions LLC
# Licensed under the GPL version 2
# First version by Jesse Adelman
# someone at boldandbusted dink com
# http://www.boldandbusted.com/
# Modified for OS X by Dylan Muir <dylan@xxxxxxxxxxxxxxxx>
# 17th June, 2005
# INSTALL NOTES:
# Place this in /Library/openvpn/client.up.osx.sh
# Then, add the following to your /etc/openvpn/<clientconfig>.conf:
# client
# pull dhcp-options
# up /Library/openvpn/client.up.osx.sh
# Next, "chmod a+x /Library/openvpn/client.up.sh"
# USAGE NOTES:
# Note that this script is best served with the companion "client.down.sh"
# script.
# This script is for OS X only.
# Initialise variables
nOptionIndex=1
nNameServerIndex=1
unset vForOptions
unset vDNS
unset vOptions
# Generate some temporary file names
ID_TMPFILE=/tmp/loc.id.${RANDOM}.tmp
SCRIPT_TMPFILE=/tmp/scselect.${RANDOM}.script
# Clean up tempfiles
rm ${ID_TMPFILE} ${SCRIPT_TMPFILE} &> /dev/null
# Collect name servers and search domains from pushed options
while vForOptions=foreign_option_$nOptionIndex; [ -n "${!vForOptions}" ]; do
{
vOptions[nOptionIndex-1]=${!vForOptions}
case ${vOptions[nOptionIndex-1]} in
*DOMAIN* ) domain=`echo ${vOptions[nOptionIndex-1]} | sed -e 's/dhcp-option DOMAIN //g'` ;;
*DNS* ) vDNS[nNameServerIndex-1]=`echo ${vOptions[nOptionIndex-1]} | sed -e 's/dhcp-option DNS //g'` let nNameServerIndex++ ;;
esac
let nOptionIndex++
}
done
# Set up 'scutil' script to determine primary service
echo "open" >> ${SCRIPT_TMPFILE}
echo "get State:/Network/Global/IPv4" >> ${SCRIPT_TMPFILE}
echo "d.show" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Get current primary service from scutil using script
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil &> ${ID_TMPFILE}
SERVICE_ID=`grep 'PrimaryService' ${ID_TMPFILE} | awk '{print $3}'`
# -- Make script to assign DNS resolution options
# Clean up previous script and initialise
rm ${SCRIPT_TMPFILE}
echo "open" >> ${SCRIPT_TMPFILE}
echo "d.init" >> ${SCRIPT_TMPFILE}
# Add server addresses and domain name to script file
if [ -n "${vDNS[*]}" ]; then
echo "d.add ServerAddresses * ${vDNS[*]}" >> ${SCRIPT_TMPFILE}
fi
if [ -n "${domain}" ]; then
echo "d.add DomainName ${domain}" >> ${SCRIPT_TMPFILE}
fi
echo "set State:/Network/Service/${SERVICE_ID}/DNS" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Apply configuration using script
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil
# Remove temporary files
rm ${ID_TMPFILE} ${SCRIPT_TMPFILE}
# Exit cleanly
exit 0[/script]
my down script
[script]#!/bin/bash -x
# client.down.osx.sh - SCRIPT Re-initialise OS Xnetwork configuration
# Usage: Should be called as a 'down' script by openvpn
# Author: Dylan Muir <dylan@xxxxxxxxxxxxxxxx>
# Created: 17th June, 2005
# Constants
NET_IPV4_KEY="State:/Network/Global/IPv4"
# Generate some temporary file names
IF_TMPFILE=/tmp/net.if.${RANDOM}.tmp
SCRIPT_TMPFILE=/tmp/scselect.${RANDOM}.script
# Ensure tempfiles are clean
rm ${IF_TMPFILE} ${SCRIPT_TMPFILE} &> /dev/null
# Set up 'scutil' script to determine primary service
echo "open" >> ${SCRIPT_TMPFILE}
echo "show ${NET_IPV4_KEY}" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Get current primary interface from scutil using script
/usr/sbin/scutil -w ${NET_IPV4_KEY}
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil &> ${IF_TMPFILE}
PRIMARY_IF=`grep 'PrimaryInterface' ${IF_TMPFILE} | awk '{print $3}'`
# Reset networking by setting the primary interface to down, then back
# to using DHCP
/usr/sbin/ipconfig set ${PRIMARY_IF} NONE
sleep 5
/usr/sbin/ipconfig set ${PRIMARY_IF} DHCP
# Clean up tempfile
rm ${IF_TMPFILE} ${SCRIPT_TMPFILE}
# Exit cleanly
exit 0[/script]
from my ovpn config file:
[oconf]client
pull
script-security 2
up /Library/openvpn/client.up.osx.sh
down /Library/openvpn/client.down.osx.sh[/oconf]
my up script:
[script]#!/bin/bash -x
# client.up.osx.sh - SCRIPT Set name resolution options using the DHCP-delivered
# configuration coming over the openvpn tunnel
# Copyright (c) 2005 by OpenVPN Solutions LLC
# Licensed under the GPL version 2
# First version by Jesse Adelman
# someone at boldandbusted dink com
# http://www.boldandbusted.com/
# Modified for OS X by Dylan Muir <dylan@xxxxxxxxxxxxxxxx>
# 17th June, 2005
# INSTALL NOTES:
# Place this in /Library/openvpn/client.up.osx.sh
# Then, add the following to your /etc/openvpn/<clientconfig>.conf:
# client
# pull dhcp-options
# up /Library/openvpn/client.up.osx.sh
# Next, "chmod a+x /Library/openvpn/client.up.sh"
# USAGE NOTES:
# Note that this script is best served with the companion "client.down.sh"
# script.
# This script is for OS X only.
# Initialise variables
nOptionIndex=1
nNameServerIndex=1
unset vForOptions
unset vDNS
unset vOptions
# Generate some temporary file names
ID_TMPFILE=/tmp/loc.id.${RANDOM}.tmp
SCRIPT_TMPFILE=/tmp/scselect.${RANDOM}.script
# Clean up tempfiles
rm ${ID_TMPFILE} ${SCRIPT_TMPFILE} &> /dev/null
# Collect name servers and search domains from pushed options
while vForOptions=foreign_option_$nOptionIndex; [ -n "${!vForOptions}" ]; do
{
vOptions[nOptionIndex-1]=${!vForOptions}
case ${vOptions[nOptionIndex-1]} in
*DOMAIN* ) domain=`echo ${vOptions[nOptionIndex-1]} | sed -e 's/dhcp-option DOMAIN //g'` ;;
*DNS* ) vDNS[nNameServerIndex-1]=`echo ${vOptions[nOptionIndex-1]} | sed -e 's/dhcp-option DNS //g'` let nNameServerIndex++ ;;
esac
let nOptionIndex++
}
done
# Set up 'scutil' script to determine primary service
echo "open" >> ${SCRIPT_TMPFILE}
echo "get State:/Network/Global/IPv4" >> ${SCRIPT_TMPFILE}
echo "d.show" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Get current primary service from scutil using script
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil &> ${ID_TMPFILE}
SERVICE_ID=`grep 'PrimaryService' ${ID_TMPFILE} | awk '{print $3}'`
# -- Make script to assign DNS resolution options
# Clean up previous script and initialise
rm ${SCRIPT_TMPFILE}
echo "open" >> ${SCRIPT_TMPFILE}
echo "d.init" >> ${SCRIPT_TMPFILE}
# Add server addresses and domain name to script file
if [ -n "${vDNS[*]}" ]; then
echo "d.add ServerAddresses * ${vDNS[*]}" >> ${SCRIPT_TMPFILE}
fi
if [ -n "${domain}" ]; then
echo "d.add DomainName ${domain}" >> ${SCRIPT_TMPFILE}
fi
echo "set State:/Network/Service/${SERVICE_ID}/DNS" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Apply configuration using script
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil
# Remove temporary files
rm ${ID_TMPFILE} ${SCRIPT_TMPFILE}
# Exit cleanly
exit 0[/script]
my down script
[script]#!/bin/bash -x
# client.down.osx.sh - SCRIPT Re-initialise OS Xnetwork configuration
# Usage: Should be called as a 'down' script by openvpn
# Author: Dylan Muir <dylan@xxxxxxxxxxxxxxxx>
# Created: 17th June, 2005
# Constants
NET_IPV4_KEY="State:/Network/Global/IPv4"
# Generate some temporary file names
IF_TMPFILE=/tmp/net.if.${RANDOM}.tmp
SCRIPT_TMPFILE=/tmp/scselect.${RANDOM}.script
# Ensure tempfiles are clean
rm ${IF_TMPFILE} ${SCRIPT_TMPFILE} &> /dev/null
# Set up 'scutil' script to determine primary service
echo "open" >> ${SCRIPT_TMPFILE}
echo "show ${NET_IPV4_KEY}" >> ${SCRIPT_TMPFILE}
echo "quit" >> ${SCRIPT_TMPFILE}
# Get current primary interface from scutil using script
/usr/sbin/scutil -w ${NET_IPV4_KEY}
cat ${SCRIPT_TMPFILE} | /usr/sbin/scutil &> ${IF_TMPFILE}
PRIMARY_IF=`grep 'PrimaryInterface' ${IF_TMPFILE} | awk '{print $3}'`
# Reset networking by setting the primary interface to down, then back
# to using DHCP
/usr/sbin/ipconfig set ${PRIMARY_IF} NONE
sleep 5
/usr/sbin/ipconfig set ${PRIMARY_IF} DHCP
# Clean up tempfile
rm ${IF_TMPFILE} ${SCRIPT_TMPFILE}
# Exit cleanly
exit 0[/script]