[OpenVPN home] [Date Prev] [Date Index] [Date Next]
[OpenVPN mailing lists] [Thread Prev] [Thread Index] [Thread Next]
Google
 
Web openvpn.net

[Openvpn-users] DNS for OS X clients - the Definitive Guide


  • Subject: [Openvpn-users] DNS for OS X clients - the Definitive Guide
  • From: Ben Low <ben@xxxxxxxxx>
  • Date: Sat, 14 Oct 2006 00:36:30 +1000

There are a number of partial DNS for OS X client solutions around  
(ref. this openvpn-users list), though none that are 100% correct.  
Below are two up-down scripts that work, and at least the tun script  
works in what seems to be the Apple-certified way (according to Allan  
Nathanson, Apple developer, quoted on the Apple network mailing list  
ca. June 2005). It's not surprising there's confusion here - Apple  
don't appear to have documented the design and application of their  
System Configuration framework for 'end users' (there's detailed  
Cocoa developer doc, but previous little admin-level information).

Note that at least one of the previously published scripts works,  
however they all have various limitations - I've tried to incorporate  
the best of each into these scripts.

On to the scripts: one is for routed (tun) connections, the other for  
bridged (tap) links. Both are for OS X 10.4 (at least 10.4.7 and .8).

The routed (tun) script extracts the OpenVPN-assigned address and DNS  
details (from the server-pushed (pseudo-)"dhcp-options") and inserts  
them into the necessary System Configuration database using the  
scutil utility.

The bridged (tap) script uses the server-end DHCP server to acquire  
an address, just like any host on the bridged network. Alas, OS X  
needs help incorporating the DHCP-provided DNS information into the  
SC database, as per the tun case.

-------------------------------------------------------

#!/bin/bash
# - must be bash: uses bash-specific tricks
#
# openvpn-tun-up-down.sh
#
#
# A script to be used as an OpenVPN routed (tun) up/down script on  
Mac OSX 10.4
# - OpenVPN will have assigned peer address as part of the tun  
establishment
# - the server may also have pushed routes, and "DHCP"-like  
information (DNS Domain and server)
#   - this script extracts any such options and merges them into the  
current DNS config
#
# Use in your OpenVPN config file as follows:
#
#    up  openvpn-tun-up-down.sh
#
# 2006-09-21    Ben Low    original
#
# 200x-xx-xx    name
#

if [ -z "$dev" ]; then echo "$0: \$dev not defined, exiting"; exit 1; fi


# relevant script_type values are 'up' or 'down'
case "$script_type" in
   up)

     # need to create two Network Service keys:
     # 1. State:/Network/Service/<serviceID>/IPv4 key containing  
information about the tunnel
     # 2. State:/Network/Service/<serviceID>/DNS key including the  
SupplementalMatchDomains key
     # ref. thread: http://lists.apple.com/archives/Macnetworkprog/ 
2005/Jun/msg00011.html
     # and http://lists.apple.com/archives/Macnetworkprog/2005/Sep/ 
msg00047.html
     # - the first thread mentions 'OverridePrimary', but that sets  
"Both the default route
     #   and the default resolver configuration ..." which is NOT  
what we want here.

     # "parse" foreign_options into separate DNS and DOMAIN records
     # - based on Tunnelblick's client.up.osx.sh
     # e.g. (could be any number, in any order; assume consecutive):
     #   foreign_option_1=dhcp-option DOMAIN example.net
     #   foreign_option_2=dhcp-option DNS 10.1.0.1
     unset dns
     unset domain
     n=1; i=0; j=0;
     while o=foreign_option_${n}; o=${!o}; [ "$o" ]
     do
         #echo "$n - $o ($i, $j)"
         case $o in
             'dhcp-option DNS '*)        dns[i++]=${o/dhcp-option  
DNS /};;
             'dhcp-option DOMAIN '*)     domain[j++]=${o/dhcp-option  
DOMAIN /} ;;
         esac;
         let n++
     done

     #echo "dns [${dns[0]}] [${dns[1]}] [${dns[2]}]"
     #echo "dom [${domain[0]}] [${domain[1]}] [${domain[2]}]"

     if [ ${#dns[@]} ]; then
         /usr/sbin/scutil <<EOF
d.init
d.add Addresses * ${ifconfig_local}
d.add DestAddresses * ${ifconfig_remote}
d.add InterfaceName ${dev}
set State:/Network/Service/openvpn-${dev}/IPv4
d.init
d.add ServerAddresses * ${dns[*]}
d.add SupplementalMatchDomains * ${domain[*]}
set State:/Network/Service/openvpn-${dev}/DNS
EOF
     fi

   ;;

   down)

     if [ `/usr/bin/id -u` -eq 0 ]; then
         /usr/sbin/scutil <<EOF
remove State:/Network/Service/openvpn-${dev}/IPv4
remove State:/Network/Service/openvpn-${dev}/DNS
EOF
     fi
   ;;
   *) echo "$0: invalid script_type" && exit 1 ;;
esac

##### FIN

-------------------------------------------------------

#!/bin/sh
#
# openvpn-tap-up-down.sh
#
#
# A script to be used as an OpenVPN bridged (tap) up/down script on  
Mac OSX 10.4
# - uses ipconfig to acquire a DHCP lease via the OpenVPN tap  
interface, and scutil to
#  incorporate the DHCP-supplied DNS configuration
#
# Use in your OpenVPN config file as follows:
#
#    up  openvpn-tap-up-down.sh
#
# - up: openvpn calls the 'up' script after the tun/tap interface is  
created, but before the link
#   to the server is available for use (ditto 'up-delay' at least for  
UDP)
#   - on testing w/ openvpn 2.0.5, and tcpdump on the tap interface  
as soon as it comes up,
#     packets are queued up on the interface (and not actually sent  
over the openvpn tunnel)
#     until *after* this script returns; this makes sense: this  
script could fail in which
#     case the connection is invalid
#     - this means the DHCP acquisition can't complete until after  
this script exits
#     - that's not directly a problem as the OS X DHCP client should  
do everything we need
#       to make the interface functional, all by itself - *except*  
for one small thing: as of
#       OS X 10.4.7 the DHCP-acquired DNS information is not "merged"  
into the System
#       Configuration (OS X bug?)
#       - thus we have a chicken-and-egg situation: we need to  
manually fixup the DNS config,
#         but can't until we get the DHCP lease; we won't get the  
lease until we this script exits
#       - the solution is to spawn a little "helper" that waits until  
the lease is acquired,
#         and then does the DNS fixup
#
# - down: the only sensible 'down' action is to release the DHCP  
lease (as a courtesy to the
#   DHCP server), alas it's too late to do this *after* the  
connection has been shutdown (as
#   of OpenVPN 2.0 there's no "pre-disconnect" script option; note  
that both 'down' and
#   'down-pre' are called only after the connection to the server is  
closed ('down-pre' before
#   closing the tun/tap device, 'down' after)
#   - OS X automatically cleans up the System Config keys created  
from ipconfig, but we need to
#     manually remove the DNS fixup
#
# 2006-09-21    Ben Low    original
#
# 200x-xx-xx    name
#

if [ -z "$dev" ]; then echo "$0: \$dev not defined, exiting"; exit 1; fi

# relevant script_type values are 'up' or 'down'
case "$script_type" in
   up)

     # bring the interface up and set it to DHCP
     # - System Configuration dynamic store will be automatically  
updated, with the
     #       State:/Network/Service/DHCP-tap0
     #   data store created.
     # - the ipconfig man page notes that it should only be used for  
"test and debug" purposes,
     #   and that you're supposed to use the SystemConfiguration APIs  
to manipulate the network
     #   configuration
     #   - alas, there appears to be no CLI utility other than ipconfig

     /usr/sbin/ipconfig set "$dev" DHCP

     # spawn our little DNS-fixerupper
     {
         # whilst ipconfig will have created the neccessary Network  
Service keys, the DNS
         # settings won't actually be used by OS X unless the  
SupplementalMatchDomains key
         # is added
         # ref. <http://lists.apple.com/archives/Macnetworkprog/2005/ 
Jun/msg00011.html>
         # - is there a way to extract the domains from the SC  
dictionary and re-insert
         #   as SupplementalMatchDomains? i.e. not requiring the  
ipconfig domain_name call?

         # - wait until we get a lease before extracting the DNS  
domain name and merging into SC
         # - despite it's name, ipconfig waitall doesn't (but maybe  
one day it will :-)
         /usr/sbin/ipconfig waitall

         # usually takes at least a few seconds to get a DHCP lease
         sleep 3
         n=0
         while [ -z "$domain_name" -a $n -lt 5 ]
         do
             sleep $n
             n=`expr $n + 1`
             domain_name=`/usr/sbin/ipconfig getoption $dev  
domain_name 2>/dev/null`
         done

         if [ "$domain_name" ]; then
         /usr/sbin/scutil <<EOF
d.init
get State:/Network/Service/DHCP-$dev/DNS
d.add SupplementalMatchDomains * $domain_name
set State:/Network/Service/DHCP-$dev/DNS
EOF
         fi

     } &

   ;;

   down)

     # for completeness...
     if [ `/usr/bin/id -u` -eq 0 ]; then
         /usr/sbin/ipconfig set "$dev" NONE
     fi

   ;;
   *) echo "$0: invalid script_type" && exit 1 ;;
esac

##### FIN


--
Ben Low
ben@xxxxxxxxx

"Behind every great fortune there is a crime." - Honore de Balzac
______________________
OpenVPN mailing lists
https://lists.sourceforge.net/lists/listinfo/openvpn-users