configuration-templates – Blame information for rev 24

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