aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/setup
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/unbound/setup')
-rw-r--r--usr.sbin/unbound/setup/Makefile4
-rw-r--r--usr.sbin/unbound/setup/Makefile.depend10
-rwxr-xr-xusr.sbin/unbound/setup/local-unbound-setup.sh498
3 files changed, 512 insertions, 0 deletions
diff --git a/usr.sbin/unbound/setup/Makefile b/usr.sbin/unbound/setup/Makefile
new file mode 100644
index 000000000000..e7c8ea914d69
--- /dev/null
+++ b/usr.sbin/unbound/setup/Makefile
@@ -0,0 +1,4 @@
+SCRIPTS= local-unbound-setup.sh
+MAN= #
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/unbound/setup/Makefile.depend b/usr.sbin/unbound/setup/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.sbin/unbound/setup/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.sbin/unbound/setup/local-unbound-setup.sh b/usr.sbin/unbound/setup/local-unbound-setup.sh
new file mode 100755
index 000000000000..25cfef48b6f0
--- /dev/null
+++ b/usr.sbin/unbound/setup/local-unbound-setup.sh
@@ -0,0 +1,498 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2013 Dag-Erling Smørgrav
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+
+D="${DESTDIR}"
+echo "destination: ${D}"
+
+#
+# Configuration variables
+#
+user=""
+unbound_conf=""
+forward_conf=""
+lanzones_conf=""
+control_conf=""
+control_socket=""
+workdir=""
+confdir=""
+chrootdir=""
+anchor=""
+pidfile=""
+resolv_conf=""
+resolvconf_conf=""
+service=""
+start_unbound=""
+use_tls=""
+forwarders=""
+
+#
+# Global variables
+#
+self=$(basename $(realpath "$0"))
+bkdir=/var/backups
+bkext=$(date "+%Y%m%d.%H%M%S")
+
+#
+# Regular expressions
+#
+RE_octet="([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
+RE_ipv4="(${RE_octet}(\\.${RE_octet}){3})"
+RE_word="([0-9A-Fa-f]{1,4})"
+RE_ipv6="((${RE_word}:){1,}(:|${RE_word}?(:${RE_word})*)|::1)"
+RE_port="([1-9][0-9]{0,3}|[1-5][0-9]{4,4}|6([0-4][0-9]{3}|5([0-4][0-9]{2}|5([0-2][0-9]|3[0-5]))))"
+RE_dnsname="([0-9A-Za-z-]{1,}(\\.[0-9A-Za-z-]{1,})*\\.?)"
+RE_forward_addr="((${RE_ipv4}|${RE_ipv6})(@${RE_port})?)"
+RE_forward_name="(${RE_dnsname}(@${RE_port})?)"
+RE_forward_tls="(${RE_forward_addr}(#${RE_dnsname})?)"
+
+#
+# Set default values for unset configuration variables.
+#
+set_defaults() {
+ : ${user:=unbound}
+ : ${workdir:=/var/unbound}
+ : ${confdir:=${workdir}/conf.d}
+ : ${unbound_conf:=${workdir}/unbound.conf}
+ : ${forward_conf:=${workdir}/forward.conf}
+ : ${lanzones_conf:=${workdir}/lan-zones.conf}
+ : ${control_conf:=${workdir}/control.conf}
+ : ${control_socket:=/var/run/local_unbound.ctl}
+ : ${anchor:=${workdir}/root.key}
+ : ${pidfile:=/var/run/local_unbound.pid}
+ : ${resolv_conf:=/etc/resolv.conf}
+ : ${resolvconf_conf:=/etc/resolvconf.conf}
+ : ${service:=local_unbound}
+ : ${start_unbound:=yes}
+ : ${use_tls:=no}
+}
+
+#
+# Verify that the configuration files are inside the working
+# directory, and if so, set the chroot directory accordingly.
+#
+set_chrootdir() {
+ chrootdir="${workdir}"
+ for file in "${unbound_conf}" "${forward_conf}" \
+ "${lanzones_conf}" "${control_conf}" "${anchor}" ; do
+ if [ "${file#${workdir%/}/}" = "${file}" ] ; then
+ echo "warning: ${file} is outside ${workdir}" >&2
+ chrootdir=""
+ fi
+ done
+ if [ -z "${chrootdir}" ] ; then
+ echo "warning: disabling chroot" >&2
+ fi
+}
+
+#
+# Scan through /etc/resolv.conf looking for uncommented nameserver
+# lines that don't point to localhost and return their values.
+#
+get_nameservers() {
+ while read line ; do
+ local bareline=${line%%\#*}
+ local key=${bareline%% *}
+ local value=${bareline#* }
+ case ${key} in
+ nameserver)
+ case ${value} in
+ 127.0.0.1|::1|localhost|localhost.*)
+ ;;
+ *)
+ echo "${value}"
+ ;;
+ esac
+ ;;
+ esac
+ done
+}
+
+#
+# Scan through /etc/resolv.conf looking for uncommented nameserver
+# lines. Comment out any that don't point to localhost. Finally,
+# append a nameserver line that points to localhost, if there wasn't
+# one already, and enable the edns0 option.
+#
+gen_resolv_conf() {
+ local localhost=no
+ local edns0=no
+ while read line ; do
+ local bareline=${line%%\#*}
+ local key=${bareline%% *}
+ local value=${bareline#* }
+ case ${key} in
+ nameserver)
+ case ${value} in
+ 127.0.0.1|::1|localhost|localhost.*)
+ localhost=yes
+ ;;
+ *)
+ echo -n "# "
+ ;;
+ esac
+ ;;
+ options)
+ case ${value} in
+ *edns0*)
+ edns0=yes
+ ;;
+ esac
+ ;;
+ esac
+ echo "${line}"
+ done
+ if [ "${localhost}" = "no" ] ; then
+ echo "nameserver 127.0.0.1"
+ fi
+ if [ "${edns0}" = "no" ] ; then
+ echo "options edns0"
+ fi
+}
+
+#
+# Boilerplate
+#
+do_not_edit() {
+ echo "# This file was generated by $self."
+ echo "# Modifications will be overwritten."
+}
+
+#
+# Generate resolvconf.conf so it updates forward.conf in addition to
+# resolv.conf. Note "in addition to" rather than "instead of",
+# because we still want it to update the domain name and search path
+# if they change. Setting name_servers to "127.0.0.1" ensures that
+# the libc resolver will try unbound first.
+#
+gen_resolvconf_conf() {
+ local style="$1"
+ do_not_edit
+ echo "libc=\"NO\""
+ if [ "${style}" = "dynamic" ] ; then
+ echo "unbound_conf=\"${forward_conf}\""
+ echo "unbound_pid=\"${pidfile}\""
+ echo "unbound_service=\"${service}\""
+ # resolvconf(8) likes to restart rather than reload
+ echo "unbound_restart=\"service ${service} reload\""
+ else
+ echo "# Static DNS configuration"
+ fi
+}
+
+#
+# Generate forward.conf
+#
+gen_forward_conf() {
+ do_not_edit
+ echo "forward-zone:"
+ echo " name: ."
+ for forwarder ; do echo "${forwarder}" ; done |
+ if [ "${use_tls}" = "yes" ] ; then
+ echo " forward-tls-upstream: yes"
+ sed -nE \
+ -e "s/^${RE_forward_tls}\$/ forward-addr: \\1/p"
+ else
+ sed -nE \
+ -e "s/^${RE_forward_addr}\$/ forward-addr: \\1/p" \
+ -e "s/^${RE_forward_name}\$/ forward-host: \\1/p"
+ fi
+}
+
+#
+# Generate lan-zones.conf
+#
+gen_lanzones_conf() {
+ do_not_edit
+ echo "server:"
+ echo " # Unblock reverse lookups for LAN addresses"
+ echo " unblock-lan-zones: yes"
+ echo " insecure-lan-zones: yes"
+}
+
+#
+# Generate control.conf
+#
+gen_control_conf() {
+ do_not_edit
+ echo "remote-control:"
+ echo " control-enable: yes"
+ echo " control-interface: ${control_socket}"
+ echo " control-use-cert: no"
+}
+
+#
+# Generate unbound.conf
+#
+gen_unbound_conf() {
+ do_not_edit
+ echo "server:"
+ echo " username: ${user}"
+ echo " directory: ${workdir}"
+ echo " chroot: ${chrootdir}"
+ echo " pidfile: ${pidfile}"
+ echo " auto-trust-anchor-file: ${anchor}"
+ if [ "${use_tls}" = "yes" ] ; then
+ echo " tls-cert-bundle: /etc/ssl/cert.pem"
+ fi
+ echo " so-sndbuf: 0"
+ echo ""
+ if [ -f "${forward_conf}" ] ; then
+ echo "include: ${forward_conf}"
+ fi
+ if [ -f "${lanzones_conf}" ] ; then
+ echo "include: ${lanzones_conf}"
+ fi
+ if [ -f "${control_conf}" ] ; then
+ echo "include: ${control_conf}"
+ fi
+ if [ -d "${confdir}" ] ; then
+ echo "include: ${confdir}/*.conf"
+ fi
+}
+
+#
+# Rename a file we are about to replace.
+#
+backup() {
+ local file="$1"
+ if [ -f "${D}${file}" ] ; then
+ local bkfile="${bkdir}/${file##*/}.${bkext}"
+ echo "Original ${file} saved as ${bkfile}"
+ mv "${D}${file}" "${D}${bkfile}"
+ fi
+}
+
+#
+# Wrapper for mktemp which respects DESTDIR
+#
+tmp() {
+ local file="$1"
+ mktemp -u "${D}${file}.XXXXX"
+}
+
+#
+# Replace one file with another, making a backup copy of the first,
+# but only if the new file is different from the old.
+#
+replace() {
+ local file="$1"
+ local newfile="$2"
+ if [ ! -f "${D}${file}" ] ; then
+ echo "${file} created"
+ mv "${newfile}" "${D}${file}"
+ elif ! cmp -s "${D}${file}" "${newfile}" ; then
+ backup "${file}"
+ mv "${newfile}" "${D}${file}"
+ else
+ echo "${file} not modified"
+ rm "${newfile}"
+ fi
+}
+
+#
+# Print usage message and exit
+#
+usage() {
+ exec >&2
+ echo "usage: $self [options] [forwarder ...]"
+ echo "options:"
+ echo " -n do not start unbound"
+ echo " -a path full path to trust anchor file"
+ echo " -C path full path to additional configuration directory"
+ echo " -c path full path to unbound configuration file"
+ echo " -f path full path to forwarding configuration"
+ echo " -O path full path to remote control socket"
+ echo " -o path full path to remote control configuration"
+ echo " -p path full path to pid file"
+ echo " -R path full path to resolvconf.conf"
+ echo " -r path full path to resolv.conf"
+ echo " -s service name of unbound service"
+ echo " -u user user to run unbound as"
+ echo " -w path full path to working directory"
+ exit 1
+}
+
+#
+# Main
+#
+main() {
+ umask 022
+
+ #
+ # Parse and validate command-line options
+ #
+ while getopts "a:C:c:f:no:p:R:r:s:tu:w:" option ; do
+ case $option in
+ a)
+ anchor="$OPTARG"
+ ;;
+ C)
+ confdir="$OPTARG"
+ ;;
+ c)
+ unbound_conf="$OPTARG"
+ ;;
+ f)
+ forward_conf="$OPTARG"
+ ;;
+ n)
+ start_unbound="no"
+ ;;
+ O)
+ control_socket="$OPTARG"
+ ;;
+ o)
+ control_conf="$OPTARG"
+ ;;
+ p)
+ pidfile="$OPTARG"
+ ;;
+ R)
+ resolvconf_conf="$OPTARG"
+ ;;
+ r)
+ resolv_conf="$OPTARG"
+ ;;
+ s)
+ service="$OPTARG"
+ ;;
+ t)
+ use_tls="yes"
+ ;;
+ u)
+ user="$OPTARG"
+ ;;
+ w)
+ workdir="$OPTARG"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+ done
+ shift $((OPTIND-1))
+ set_defaults
+
+ #
+ # Get the list of forwarders, either from the command line or
+ # from resolv.conf.
+ #
+ forwarders="$@"
+ case "${forwarders}" in
+ [Nn][Oo][Nn][Ee])
+ forwarders="none"
+ style=recursing
+ ;;
+ "")
+ if [ -f "${D}${resolv_conf}" ] ; then
+ echo "Extracting forwarders from ${resolv_conf}."
+ forwarders=$(get_nameservers <"${D}${resolv_conf}")
+ fi
+ style=dynamic
+ ;;
+ *)
+ style=static
+ ;;
+ esac
+
+ #
+ # Generate forward.conf.
+ #
+ if [ -z "${forwarders}" ] ; then
+ echo -n "No forwarders found in ${resolv_conf##*/}, "
+ if [ -f "${forward_conf}" ] ; then
+ echo "using existing ${forward_conf##*/}."
+ else
+ echo "unbound will recurse."
+ fi
+ elif [ "${forwarders}" = "none" ] ; then
+ echo "Forwarding disabled, unbound will recurse."
+ backup "${forward_conf}"
+ else
+ local tmp_forward_conf=$(tmp "${forward_conf}")
+ gen_forward_conf ${forwarders} | unexpand >"${tmp_forward_conf}"
+ replace "${forward_conf}" "${tmp_forward_conf}"
+ fi
+
+ #
+ # Generate lan-zones.conf.
+ #
+ local tmp_lanzones_conf=$(tmp "${lanzones_conf}")
+ gen_lanzones_conf | unexpand >"${tmp_lanzones_conf}"
+ replace "${lanzones_conf}" "${tmp_lanzones_conf}"
+
+ #
+ # Generate control.conf.
+ #
+ local tmp_control_conf=$(tmp "${control_conf}")
+ gen_control_conf | unexpand >"${tmp_control_conf}"
+ replace "${control_conf}" "${tmp_control_conf}"
+
+ #
+ # Generate unbound.conf.
+ #
+ local tmp_unbound_conf=$(tmp "${unbound_conf}")
+ set_chrootdir
+ gen_unbound_conf | unexpand >"${tmp_unbound_conf}"
+ replace "${unbound_conf}" "${tmp_unbound_conf}"
+
+ #
+ # Start unbound, unless requested not to. Stop immediately if
+ # it is not enabled so we don't end up with a resolv.conf that
+ # points into nothingness. We could "onestart" it, but it
+ # wouldn't stick.
+ #
+ if [ "${start_unbound}" = "no" ] ; then
+ # skip
+ elif ! service "${service}" enabled ; then
+ echo "Please enable $service in rc.conf(5) and try again."
+ return 1
+ elif ! service "${service}" restart ; then
+ echo "Failed to start $service."
+ return 1
+ fi
+
+ #
+ # Rewrite resolvconf.conf so resolvconf updates forward.conf
+ # instead of resolv.conf.
+ #
+ local tmp_resolvconf_conf=$(tmp "${resolvconf_conf}")
+ gen_resolvconf_conf "${style}" | unexpand >"${tmp_resolvconf_conf}"
+ replace "${resolvconf_conf}" "${tmp_resolvconf_conf}"
+
+ #
+ # Finally, rewrite resolv.conf.
+ #
+ local tmp_resolv_conf=$(tmp "${resolv_conf}")
+ gen_resolv_conf <"${D}${resolv_conf}" | unexpand >"${tmp_resolv_conf}"
+ replace "${resolv_conf}" "${tmp_resolv_conf}"
+}
+
+main "$@"