3 # Copyright (c) 2013 Dag-Erling Smørgrav
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 # Configuration variables
49 self=$(basename $(realpath "$0"))
50 bkext=$(date "+%Y%m%d.%H%M%S")
53 # Set default values for unset configuration variables.
57 : ${workdir:=/var/unbound}
58 : ${unbound_conf:=${workdir}/unbound.conf}
59 : ${forward_conf:=${workdir}/forward.conf}
60 : ${anchor:=${workdir}/root.key}
61 : ${pidfile:=/var/run/local_unbound.pid}
62 : ${resolv_conf:=/etc/resolv.conf}
63 : ${resolvconf_conf:=/etc/resolvconf.conf}
64 : ${service:=local_unbound}
65 : ${start_unbound:=yes}
69 # Verify that the configuration files are inside the working
70 # directory, and if so, set the chroot directory accordingly.
73 chrootdir="${workdir}"
74 for file in "${unbound_conf}" "${forward_conf}" "${anchor}" ; do
75 if [ "${file#${workdir%/}/}" = "${file}" ] ; then
76 echo "warning: ${file} is outside ${workdir}" >&2
80 if [ -z "${chrootdir}" ] ; then
81 echo "warning: disabling chroot" >&2
86 # Scan through /etc/resolv.conf looking for uncommented nameserver
87 # lines that don't point to localhost and return their values.
91 local bareline=${line%%\#*}
92 local key=${bareline%% *}
93 local value=${bareline#* }
97 127.0.0.1|::1|localhost|localhost.*)
109 # Scan through /etc/resolv.conf looking for uncommented nameserver
110 # lines. Comment out any that don't point to localhost. Finally,
111 # append a nameserver line that points to localhost, if there wasn't
112 # one already, and enable the edns0 option.
118 local bareline=${line%%\#*}
119 local key=${bareline%% *}
120 local value=${bareline#* }
124 127.0.0.1|::1|localhost|localhost.*)
142 if [ "${localhost}" = "no" ] ; then
143 echo "nameserver 127.0.0.1"
145 if [ "${edns0}" = "no" ] ; then
151 # Generate resolvconf.conf so it updates forward.conf in addition to
152 # resolv.conf. Note "in addition to" rather than "instead of",
153 # because we still want it to update the domain name and search path
154 # if they change. Setting name_servers to "127.0.0.1" ensures that
155 # the libc resolver will try unbound first.
157 gen_resolvconf_conf() {
158 echo "# Generated by $self"
159 echo "resolv_conf=\"/dev/null\" # prevent updating ${resolv_conf}"
160 echo "unbound_conf=\"${forward_conf}\""
161 echo "unbound_pid=\"${pidfile}\""
162 echo "unbound_service=\"${service}\""
163 # resolvconf(8) likes to restart rather than reload
164 echo "unbound_restart=\"service ${service} reload\""
168 # Generate forward.conf
171 echo "# Generated by $self"
175 if expr "${forwarder}" : "^[0-9:.]\{1,\}$" >/dev/null ; then
176 echo " forward-addr: ${forwarder}"
178 echo " forward-host: ${forwarder}"
184 # Generate unbound.conf
187 echo "# Generated by $self"
189 echo " username: ${user}"
190 echo " directory: ${workdir}"
191 echo " chroot: ${chrootdir}"
192 echo " pidfile: ${pidfile}"
193 echo " auto-trust-anchor-file: ${anchor}"
195 if [ -f "${forward_conf}" ] ; then
196 echo "include: ${forward_conf}"
201 # Replace one file with another, making a backup copy of the first,
202 # but only if the new file is different from the old.
207 if [ ! -f "${file}" ] ; then
208 echo "${file} created"
209 mv "${newfile}" "${file}"
210 elif ! cmp -s "${file}" "${newfile}" ; then
211 local oldfile="${file}.${bkext}"
212 echo "original ${file} saved as ${oldfile}"
213 mv "${file}" "${oldfile}"
214 mv "${newfile}" "${file}"
216 echo "${file} not modified"
222 # Print usage message and exit
226 echo "usage: $self [options] [forwarder ...]"
228 echo " -n do not start unbound"
229 echo " -a path full path to trust anchor file"
230 echo " -c path full path to unbound configuration"
231 echo " -f path full path to forwarding configuration"
232 echo " -p path full path to pid file"
233 echo " -R path full path to resolvconf.conf"
234 echo " -r path full path to resolv.conf"
235 echo " -s service name of unbound service"
236 echo " -u user user to run unbound as"
237 echo " -w path full path to working directory"
248 # Parse and validate command-line options
250 while getopts "a:c:f:np:R:r:s:u:w:" option ; do
256 unbound_conf="$OPTARG"
259 forward_conf="$OPTARG"
268 resolvconf_conf="$OPTARG"
271 resolv_conf="$OPTARG"
291 # Get the list of forwarders, either from the command line or
295 if [ -z "$forwarders" ] ; then
296 echo "Extracting forwarders from ${resolv_conf}."
297 forwarders=$(get_nameservers <"${resolv_conf}")
301 # Generate forward.conf.
303 if [ -z "${forwarders}" ] ; then
304 echo -n "No forwarders found in ${resolv_conf##*/}, "
305 if [ -f "${forward_conf}" ] ; then
306 echo "using existing ${forward_conf##*/}."
308 echo "unbound will recurse."
311 local tmp_forward_conf=$(mktemp -u "${forward_conf}.XXXXX")
312 gen_forward_conf ${forwarders} >"${tmp_forward_conf}"
313 replace "${forward_conf}" "${tmp_forward_conf}"
317 # Generate unbound.conf.
319 local tmp_unbound_conf=$(mktemp -u "${unbound_conf}.XXXXX")
321 gen_unbound_conf >"${tmp_unbound_conf}"
322 replace "${unbound_conf}" "${tmp_unbound_conf}"
325 # Start unbound, unless requested not to. Stop immediately if
326 # it is not enabled so we don't end up with a resolv.conf that
327 # points into nothingness. We could "onestart" it, but it
330 if [ "${start_unbound}" = "no" ] ; then
332 elif ! service "${service}" enabled ; then
333 echo "Please enable $service in rc.conf(5) and try again."
335 elif ! service "${service}" restart ; then
336 echo "Failed to start $service."
341 # Rewrite resolvconf.conf so resolvconf updates forward.conf
342 # instead of resolv.conf.
344 local tmp_resolvconf_conf=$(mktemp -u "${resolvconf_conf}.XXXXX")
345 gen_resolvconf_conf >"${tmp_resolvconf_conf}"
346 replace "${resolvconf_conf}" "${tmp_resolvconf_conf}"
349 # Finally, rewrite resolv.conf.
351 local tmp_resolv_conf=$(mktemp -u "${resolv_conf}.XXXXX")
352 gen_resolv_conf <"${resolv_conf}" >"${tmp_resolv_conf}"
353 replace "${resolv_conf}" "${tmp_resolv_conf}"