configuration-templates – Blame information for rev 25

Subversion Repositories:
Rev:
Rev Author Line No. Line
23 office 1 #!/bin/sh
2 ###########################################################################
3 ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ##
4 ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ##
5 ## rights of fair usage, the disclaimer and warranty conditions. ##
6 ###########################################################################
7 # openvpn-osx-tuntap.sh #
8 # Up / Down script for OpenVPN running on OSX as a client. #
25 office 9 # #
23 office 10 # The OpenVPN server is expected to serve clients with IP addresses via #
11 # a previously configured DHCP server. #
25 office 12 # #
23 office 13 # Note that this script does not replace the default route but instead #
25 office 14 # uses the Mac OS capability of using scoped DNS resolution in order to #
15 # make the remote network available whilst preserving the default route. #
23 office 16 # #
25 office 17 # To use this script on an OS X OpenVPN client, the following changes to #
18 # your OpenVPN configuration are required: #
19 # #
20 # up-restart #
21 # up openvpn-osx-tuntap.sh #
22 # down openvpn-osx-tuntap.sh #
23 # ipchange openvpn-osx-tuntap.sh #
24 # #
25 # where openvpn-osx-tuntap.sh is the filesystem path to this script. #
26 # #
23 office 27 # Based on: #
28 # - 2006-09-21, Ben Low - original version #
29 # - Nick Williams - for TunnelBrick #
30 # - Jonathan K. Bullard - additions for Mountain Lion #
31 ###########################################################################
32  
33 ###########################################################################
34 # CONFIGURATION #
35 ###########################################################################
36 # A MAC address for the tunnel interface.
37 STATIC_TUNTAP_MAC_ADDRESS="42:75:e2:67:43:db"
38 # Whether to prepend domain names instead of replacing the exiting ones.
39 PREPEND_DOMAIN_NAME="false"
40  
41 ###########################################################################
42 # INTERNALS #
43 ###########################################################################
44  
45 # Regular expression for matching IP addresses.
46 IPRX="(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
47 # Domain name regular expression.
48 DOMRX="(?:[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]|[A-Za-z0-9])"
49  
50 ###########################################################################
51 # Utility function to flush the DNS cache on various Mac OS releases. #
52 ###########################################################################
53 flushDNSCache()
54 {
55 if [ "${OSVER}" = "10.4" ] ; then
24 office 56 if [ -f /usr/sbin/lookupd ] ; then
57 set +e # we will catch errors from lookupd
58 /usr/sbin/lookupd -flushcache
59 set -e # bash should again fail on errors
60 fi
61 else
62 if [ -f /usr/bin/dscacheutil ] ; then
63 set +e # we will catch errors from dscacheutil
64 /usr/bin/dscacheutil -flushcache
65 set -e # bash should again fail on errors
66 fi
67 if [ -f /usr/sbin/discoveryutil ] ; then
68 set +e # we will catch errors from discoveryutil
69 /usr/sbin/discoveryutil udnsflushcaches
70 /usr/sbin/discoveryutil mdnsflushcache
71 set -e # bash should again fail on errors
72 fi
73 set +e # "grep" will return error status (1) if no matches are found, so don't fail on individual errors
74 hands_off_ps="$( ps -ax | grep HandsOffDaemon | grep -v grep.HandsOffDaemon )"
75 set -e # We instruct bash that it CAN again fail on errors
76 if [ -z "${hands_off_ps}" ] ; then
77 if [ -f /usr/bin/killall ] ; then
78 set +e # ignore errors if mDNSResponder isn't currently running
79 /usr/bin/killall -HUP mDNSResponder
80 set -e # bash should again fail on errors
81 fi
82 fi
83 fi
23 office 84 }
85  
86 ###########################################################################
87 # Sets all dynamic DHCP options on the tuntap interface. #
88 ###########################################################################
89 setDnsServersAndDomainName()
90 {
91 readonly PSID="DHCP-$dev"
92  
93 # Set up the DYN_* variables to contain what is asked for (dynamically, by a 'push' directive, for example)
24 office 94 declare -a vDNS=("${!1}")
95 declare -a vSMB=("${!3}")
96 declare -a vSD=("${!4}")
23 office 97  
24 office 98 if [ ${#vDNS[*]} -eq 0 ] ; then
99 readonly DYN_DNS_SA=""
100 else
101 readonly DYN_DNS_SA="${!1}"
102 fi
103  
104 if [ ${#vSMB[*]} -eq 0 ] ; then
105 readonly DYN_SMB_WA=""
106 else
107 readonly DYN_SMB_WA="${!3}"
108 fi
23 office 109  
24 office 110 if [ ${#vSD[*]} -eq 0 ] ; then
111 readonly DYN_DNS_SD=""
112 else
113 readonly DYN_DNS_SD="${!4}"
114 fi
23 office 115  
24 office 116 DYN_DNS_DN="$2"
117  
23 office 118 # set up the FIN_* variables with what we want to set things to
24 office 119 # Three FIN_* variables are simple -- no aggregation is done for them
120 if [ ! -z "${DYN_DNS_DN}" ] ; then
121 readonly FIN_DNS_DN="${DYN_DNS_DN}"
122 else
123 readonly FIN_DNS_DN=""
124 fi
125  
126 if [ ! -z "${DYN_SMB_NN}" ] ; then
127 readonly FIN_SMB_NN="${DYN_SMB_NN}"
128 else
129 readonly FIN_SMB_NN=""
130 fi
131  
132 if [ ! -z "${DYN_SMB_WG}" ] ; then
133 readonly FIN_SMB_WG="${DYN_SMB_WG}"
134 else
135 readonly FIN_SMB_WG=""
136 fi
23 office 137  
24 office 138 # DNS ServerAddresses (FIN_DNS_SA) are aggregated for 10.4 and 10.5
139 if [ ${#vDNS[*]} -eq 0 ] ; then
140 readonly FIN_DNS_SA=""
141 else
142 case "${OSVER}" in
143 10.4 | 10.5 )
144 # We need to remove duplicate DNS entries, so that our reference list matches MacOSX's
145 SDNS="$( echo -n "${DYN_DNS_SA}" | tr ' ' '\n' )"
23 office 146 i=0
24 office 147 for n in "${vDNS[@]}" ; do
148 if echo -n "${SDNS}" | grep -q "${n}" ; then
149 unset vDNS[${i}]
150 fi
23 office 151 let i++
24 office 152 done
153 if [ ${#vDNS[*]} -gt 0 ] ; then
154 readonly FIN_DNS_SA="$( echo -n "${DYN_DNS_SA}" | sed s/"${vDNS[*]}"//g )"
155 else
156 readonly FIN_DNS_SA="${DYN_DNS_SA}"
157 fi
158 ;;
159 * )
160 # Do nothing - in 10.6 and higher -- we don't aggregate our configurations, apparently
161 readonly FIN_DNS_SA="${DYN_DNS_SA}"
162 ;;
163 esac
164 fi
23 office 165  
24 office 166 # SMB WINSAddresses (FIN_SMB_WA) are aggregated for 10.4 and 10.5
167 if [ ${#vSMB[*]} -eq 0 ] ; then
168 readonly FIN_SMB_WA=""
169 else
170 case "${OSVER}" in
171 10.4 | 10.5 )
172 # We need to remove duplicate SMB entries, so that our reference list matches MacOSX's
173 SSMB="$( echo -n "${DYN_SMB_WA}" | tr ' ' '\n' )"
23 office 174 i=0
24 office 175 for n in "${vSMB[@]}" ; do
176 if echo -n "${SSMB}" | grep -q "${n}" ; then
177 unset vSMB[${i}]
178 fi
23 office 179 let i++
24 office 180 done
181 if [ ${#vSMB[*]} -gt 0 ] ; then
182 readonly FIN_SMB_WA="$( echo -n "${DYN_SMB_WA}" | sed s/"${vSMB[*]}"//g )"
183 else
184 readonly FIN_SMB_WA="${DYN_SMB_WA}"
185 fi
186 ;;
187 * )
188 # Do nothing - in 10.6 and higher -- we don't aggregate our configurations, apparently
189 readonly FIN_SMB_WA="${DYN_SMB_WA}"
190 ;;
191 esac
192 fi
23 office 193  
24 office 194 # DNS SearchDomains (FIN_DNS_SD) is treated specially
195 #
196 # OLD BEHAVIOR:
197 # if SearchDomains was not set manually, we set SearchDomains to the DomainName
198 # else
199 # In OS X 10.4-10.5, we add the DomainName to the end of any manual SearchDomains (unless it is already there)
200 # In OS X 10.6+, if SearchDomains was entered manually, we ignore the DomainName
201 # else we set SearchDomains to the DomainName
202 #
203 # NEW BEHAVIOR (done if ARG_PREPEND_DOMAIN_NAME is "true"):
204 #
205 # if SearchDomains was entered manually, we do nothing
206 # else we PREpend new SearchDomains (if any) to the existing SearchDomains (NOT replacing them)
207 # and PREpend DomainName to that
208 #
209 # (done if ARG_PREPEND_DOMAIN_NAME is "false" and there are new SearchDomains from DOMAIN-SEARCH):
210 #
211 # if SearchDomains was entered manually, we do nothing
212 # else we PREpend any new SearchDomains to the existing SearchDomains (NOT replacing them)
213 #
214 # This behavior is meant to behave like Linux with Network Manager and Windows
215 if "${PREPEND_DOMAIN_NAME}" ; then
216 if [ ! -z "${DYN_DNS_SD}" ] ; then
23 office 217 readonly TMP_DNS_SD="${DYN_DNS_SD}"
24 office 218 if [ ! -z "${FIN_DNS_DN}" -a "${FIN_DNS_DN}" != "localdomain" ]; then
23 office 219 if ! echo -n "${TMP_DNS_SD}" | tr ' ' '\n' | grep -q "${FIN_DNS_DN}" ; then
220 readonly FIN_DNS_SD="$( echo -n "${FIN_DNS_DN}" | sed s/"${TMP_DNS_SD}"//g )"
221 else
222 readonly FIN_DNS_SD="${TMP_DNS_SD}"
223 fi
224 else
24 office 225 readonly FIN_DNS_SD="${TMP_DNS_SD}"
226 fi
23 office 227 else
228 readonly FIN_DNS_SD="${DYN_DNS_SD}"
229 fi
24 office 230 else
231 if [ ! -z "${DYN_DNS_SD}" ] ; then
232 readonly FIN_DNS_SD="${DYN_DNS_SD}"
233 else
23 office 234 if [ ! -z "${FIN_DNS_DN}" -a "${FIN_DNS_DN}" != "localdomain" ] ; then
235 case "${OSVER}" in
236 10.4 | 10.5 )
237 readonly FIN_DNS_SD="${FIN_DNS_DN}"
238 ;;
239 * )
240 readonly FIN_DNS_SD="${FIN_DNS_DN}"
241 ;;
242 esac
243 else
244 readonly FIN_DNS_SD=""
245 fi
24 office 246 fi
247 fi
23 office 248  
249 # Set up SKP_* variables to inhibit scutil from making some changes
24 office 250 # SKP_DNS_* and SKP_SMB_* are used to comment out individual items
23 office 251 # that are not being set
24 office 252 if [ -z "${FIN_DNS_DN}" ] ; then
253 SKP_DNS_DN="#"
254 else
255 SKP_DNS_DN=""
256 fi
257 if [ -z "${FIN_DNS_SA}" ] ; then
258 SKP_DNS_SA="#"
259 else
260 SKP_DNS_SA=""
261 fi
262 if [ -z "${FIN_DNS_SD}" ] ; then
263 SKP_DNS_SD="#"
264 else
265 SKP_DNS_SD=""
266 fi
267 if [ -z "${FIN_SMB_NN}" ] ; then
268 SKP_SMB_NN="#"
269 else
270 SKP_SMB_NN=""
271 fi
272 if [ -z "${FIN_SMB_WG}" ] ; then
273 SKP_SMB_WG="#"
274 else
275 SKP_SMB_WG=""
276 fi
277 if [ -z "${FIN_SMB_WA}" ] ; then
278 SKP_SMB_WA="#"
279 else
280 SKP_SMB_WA=""
281 fi
282  
283 # if any DNS items should be set, set all that have values
284 if [ "${SKP_DNS_DN}${SKP_DNS_SA}${SKP_DNS_SD}" = "###" ] ; then
285 readonly SKP_DNS="#"
286 else
287 readonly SKP_DNS=""
288 if [ ! -z "${FIN_DNS_DN}" ] ; then
289 SKP_DNS_DN=""
290 fi
291 if [ ! -z "${FIN_DNS_SA}" ] ; then
292 SKP_DNS_SA=""
293 fi
294 if [ ! -z "${FIN_DNS_SD}" ] ; then
295 SKP_DNS_SD=""
296 fi
297 fi
23 office 298  
24 office 299 # if any SMB items should be set, set all that have values
300 if [ "${SKP_SMB_NN}${SKP_SMB_WG}${SKP_SMB_WA}" = "###" ] ; then
301 readonly SKP_SMB="#"
302 else
303 readonly SKP_SMB=""
304 if [ ! -z "${FIN_SMB_NN}" ] ; then
305 SKP_SMB_NN=""
306 fi
307 if [ ! -z "${FIN_SMB_WG}" ] ; then
308 SKP_SMB_WG=""
309 fi
310 if [ ! -z "${FIN_SMB_WA}" ] ; then
311 SKP_SMB_WA=""
312 fi
313 fi
23 office 314  
24 office 315 readonly SKP_DNS_SA SKP_DNS_SD SKP_DNS_DN
316 readonly SKP_SMB_NN SKP_SMB_WG SKP_SMB_WA
317  
23 office 318 # special-case fiddling:
24 office 319 # 10.8+ : ServerAddresses and SearchDomains must be set via the Setup:
23 office 320 # key in addition to the State: key
24 office 321 # 10.7 : if ServerAddresses or SearchDomains are manually set,
23 office 322 # ServerAddresses and SearchDomains must be similarly set with the
323 # Setup: key in addition to the State: key
24 office 324 case "${OSVER}" in
325 10.4 | 10.5 | 10.6 | 10.7 )
326 readonly SKP_SETUP_DNS="#"
327 ;;
328 * )
329 readonly SKP_SETUP_DNS=""
330 ;;
331 esac
332  
23 office 333 # Set all parameters.
24 office 334 /usr/sbin/scutil >/dev/null 2>&1 <<-EOF
335 open
336  
337 # Initialize the new DNS map via State:
338 ${SKP_DNS}d.init
339 ${SKP_DNS}${SKP_DNS_SA}d.add ServerAddresses * ${FIN_DNS_SA}
340 ${SKP_DNS}${SKP_DNS_SD}d.add SearchDomains * ${FIN_DNS_SD}
341 ${SKP_DNS}${SKP_DNS_DN}d.add DomainName ${FIN_DNS_DN}
23 office 342 ${SKP_DNS}${SKP_DNS_DN}d.add SupplementalMatchDomains * ${FIN_DNS_DN}
24 office 343 ${SKP_DNS}set State:/Network/Service/${PSID}/DNS
23 office 344  
24 office 345 # If necessary, initialize the new DNS map via Setup: also
346 ${SKP_SETUP_DNS}${SKP_DNS}d.init
347 ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_SA}d.add ServerAddresses * ${FIN_DNS_SA}
348 ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_SD}d.add SearchDomains * ${FIN_DNS_SD}
349 ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_DN}d.add DomainName ${FIN_DNS_DN}
350 ${SKP_SETUP_DNS}${SKP_DNS}set Setup:/Network/Service/${PSID}/DNS
23 office 351  
24 office 352 # Initialize the SMB map
353 ${SKP_SMB}d.init
354 ${SKP_SMB}${SKP_SMB_NN}d.add NetBIOSName ${FIN_SMB_NN}
355 ${SKP_SMB}${SKP_SMB_WG}d.add Workgroup ${FIN_SMB_WG}
356 ${SKP_SMB}${SKP_SMB_WA}d.add WINSAddresses * ${FIN_SMB_WA}
357 ${SKP_SMB}set State:/Network/Service/${PSID}/SMB
23 office 358  
24 office 359 quit
23 office 360 EOF
361  
362 }
363  
364 # If OpenVPN has not brought up the device, then terminate.
365 if [ -z "$dev" ]; then
24 office 366 echo "$0: \$dev not defined, exiting";
367 exit 1;
23 office 368 fi
369  
370 # OpenVPN passes $script_type set to the script method.
371 case "$script_type" in
25 office 372 ipchange)
373 # Set the MAC address for the tuntap device for static DHCP bindings
374 /sbin/ifconfig "$dev" ether $STATIC_TUNTAP_MAC_ADDRESS
375 # Set the interface to NONE
376 /usr/sbin/ipconfig set "$dev" NONE
377 # Set the interface to DHCP
378 /usr/sbin/ipconfig set "$dev" DHCP
379 ;;
23 office 380 up)
381  
382 # Set the MAC address for the tuntap device for static DHCP bindings
383 /sbin/ifconfig "$dev" ether $STATIC_TUNTAP_MAC_ADDRESS
25 office 384 # Set the interface to NONE
385 /usr/sbin/ipconfig set "$dev" NONE
23 office 386 # Set the interface to DHCP
387 /usr/sbin/ipconfig set "$dev" DHCP
388  
389 {
390 # Issue the waitall command - even if it does not wait.
391 /usr/sbin/ipconfig waitall
392  
393 unset PACKET
394  
395 # Spin and check for packet from the tap device
396 set +e
397 n=0
398 while [ -z "$PACKET" -a $n -lt 60 ] ; do
24 office 399 PACKET="$( /usr/sbin/ipconfig getpacket "$dev" )"
23 office 400 let n++
401 sleep 1
402 done
403 set -e
404  
405 # Get packet to set options
406 if [ -z "$PACKET" ]; then
407 exit 1
408 fi
409  
410 unset DOMAIN_NAME
411 unset DOMAIN_NAME_SERVERS
412 unset SEARCH_DOMAINS
413 unset WINS_SERVERS
414  
415 set +e
416 # Get domain name
24 office 417 DOMAIN_NAME="$( echo -n "$PACKET" | grep "domain_name " | grep -Eo ": $DOMRX" | grep -Eo "$DOMRX" | tr -d [:space:] )"
23 office 418  
419 # Get nameservers
420 DOMAIN_NAME_SERVERS_INDEX=1
421 for DOMAIN_NAME_SERVER in $( echo -n "$PACKET" | grep "domain_name_server" | grep -Eo "\{($IPRX)(, $IPRX)*\}" | grep -Eo "($IPRX)" ); do
422 DOMAIN_NAME_SERVERS[DOMAIN_NAME_SERVERS_INDEX-1]=$DOMAIN_NAME_SERVER
423 let DOMAIN_NAME_SERVERS_INDEX++
424 done
425  
426 # Get search domains
427 SEARCH_DOMAINS_INDEX=1
24 office 428 for SEARCH_DOMAIN in $( echo -n "$PACKET" | grep "search_domain" | grep -Eo "\{($DOMRX)(, $DOMRX)*\}" | grep -Eo "($DOMRX)" ); do
429 SEARCH_DOMAINS[SEARCH_DOMAINS_INDEX-1]=$SEARCH_DOMAIN
430 let SEARCH_DOMAINS_INDEX++
431 done
23 office 432  
433 # Get WINS servers
434 WINS_SERVERS_INDEX=1
24 office 435 for WINS_SERVER in $( echo -n "$PACKET" | grep "nb_over_tcpip_name_server" | grep -Eo "\{($IPRX)(, $IPRX)*\}" | grep -Eo "($IPRX)" ); do
436 WINS_SERVERS[WINS_SERVERS_INDEX-1]=$WINS_SERVER
437 let WINS_SERVERS_INDEX++
438 done
23 office 439  
24 office 440 if [ ${#DOMAIN_NAME_SERVERS[*]} -gt 0 -a "$DOMAIN_NAME" ]; then
441 setDnsServersAndDomainName DOMAIN_NAME_SERVERS[@] "$DOMAIN_NAME" WINS_SERVERS[@] SEARCH_DOMAINS[@]
23 office 442 elif [ ${#DOMAIN_NAME_SERVERS[*]} -gt 0 ]; then
24 office 443 setDnsServersAndDomainName DOMAIN_NAME_SERVERS[@] "$DEFAULT_DOMAIN_NAME" WINS_SERVERS[@] SEARCH_DOMAINS[@]
23 office 444 else
445 exit 1
24 office 446 fi
23 office 447  
448 set -e
449  
24 office 450 sleep 1
23 office 451  
24 office 452 flushDNSCache
23 office 453  
24 office 454 exit 0
23 office 455 } &
456 ;;
457 down)
458 sleep 1
459  
460 /usr/sbin/scutil >/dev/null 2>&1 <<-EOF
461 open
462 remove State:/Network/Service/DHCP-$dev/IPv4
463 remove State:/Network/Service/DHCP-$dev/DNS
464 close
465 EOF
466  
467 flushDNSCache
468  
469 exit 0
470 ;;
471 *)
472 echo "$0: invalid script_type" && exit 1
473 ;;
474 esac
475