Files
bpfire/src/initscripts/system/unbound
Michael Tremer f59bc0c55d unbound: Reload own hostname, too
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2020-01-13 20:55:32 +01:00

650 lines
13 KiB
Bash

#!/bin/sh
# Begin $rc_base/init.d/unbound
# Description : Unbound DNS resolver boot script for IPfire
# Author : Marcel Lorenz <marcel.lorenz@ipfire.org>
. /etc/sysconfig/rc
. ${rc_functions}
TEST_DOMAIN="ipfire.org"
# This domain will never validate
TEST_DOMAIN_FAIL="dnssec-failed.org"
# Cache any local zones for 60 seconds
LOCAL_TTL=60
# Load configuration
eval $(/usr/local/bin/readhash /var/ipfire/dns/settings)
eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
ip_address_revptr() {
local addr=${1}
local a1 a2 a3 a4
IFS=. read -r a1 a2 a3 a4 <<< ${addr}
echo "${a4}.${a3}.${a2}.${a1}.in-addr.arpa"
}
read_name_servers() {
# Read name servers from ISP
if [ "${USE_ISP_NAMESERVERS}" = "on" -a "${PROTO}" != "TLS" ]; then
local i
for i in 1 2; do
echo "$(</var/run/dns${i})"
done 2>/dev/null
fi
# Read configured name servers
local id address tls_hostname enabled remark
while IFS="," read -r id address tls_hostname enabled remark; do
[ "${enabled}" != "enabled" ] && continue
if [ "${PROTO}" = "TLS" ]; then
if [ -n "${tls_hostname}" ]; then
echo "${address}@853#${tls_hostname}"
fi
else
echo "${address}"
fi
done < /var/ipfire/dns/servers
}
config_header() {
echo "# This file is automatically generated and any changes"
echo "# will be overwritten. DO NOT EDIT!"
echo
}
own_hostname() {
local hostname=$(hostname -f)
# 1.1.1.1 is reserved for unused green, skip this
if [ -n "${GREEN_ADDRESS}" -a "${GREEN_ADDRESS}" != "1.1.1.1" ]; then
unbound-control -q local_data "${hostname} ${LOCAL_TTL} IN A ${GREEN_ADDRESS}"
fi
local address
for address in ${GREEN_ADDRESS} ${BLUE_ADDRESS} ${ORANGE_ADDRESS}; do
[ -n "${address}" ] || continue
[ "${address}" = "1.1.1.1" ] && continue
address=$(ip_address_revptr ${address})
unbound-control -q local_data "${address} ${LOCAL_TTL} IN PTR ${hostname}"
done
}
update_hosts() {
# Make own hostname resolveable
own_hostname
local enabled address hostname domainname generateptr
while IFS="," read -r enabled address hostname domainname generateptr; do
[ "${enabled}" = "on" ] || continue
# Build FQDN
local fqdn="${hostname}.${domainname}"
unbound-control -q local_data "${fqdn} ${LOCAL_TTL} IN A ${address}"
# Skip reverse resolution if the address equals the GREEN address
[ "${address}" = "${GREEN_ADDRESS}" ] && continue
# Skip reverse resolution if user requested not to do so
[ "${generateptr}" = "off" ] && continue
# Add RDNS
address=$(ip_address_revptr ${address})
unbound-control -q local_data "${address} ${LOCAL_TTL} IN PTR ${fqdn}"
done < /var/ipfire/main/hosts
}
write_forward_conf() {
(
config_header
# Enable strict QNAME minimisation
if [ "${QNAME_MIN}" = "strict" ]; then
echo "server:"
echo " qname-minimisation-strict: yes"
echo
fi
# Force using TCP for upstream servers only
if [ "${PROTO}" = "TCP" ]; then
echo "# Force using TCP for upstream servers only"
echo "server:"
echo " tcp-upstream: yes"
echo
fi
local insecure_zones=""
local enabled zone server servers remark disable_dnssec rest
while IFS="," read -r enabled zone servers remark disable_dnssec rest; do
# Line must be enabled.
[ "${enabled}" = "on" ] || continue
# Zones that end with .local are commonly used for internal
# zones and therefore not signed
case "${zone}" in
*.local)
insecure_zones="${insecure_zones} ${zone}"
;;
*)
if [ "${disable_dnssec}" = "on" ]; then
insecure_zones="${insecure_zones} ${zone}"
fi
;;
esac
echo "stub-zone:"
echo " name: ${zone}"
for server in ${servers//|/ }; do
if [[ ${server} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo " stub-addr: ${server}"
else
echo " stub-host: ${server}"
fi
done
echo
# Make all reverse lookup zones transparent
case "${zone}" in
*.in-addr.arpa)
echo "server:"
echo " local-zone: \"${zone}\" transparent"
echo
;;
esac
done < /var/ipfire/dnsforward/config
if [ -n "${insecure_zones}" ]; then
echo "server:"
for zone in ${insecure_zones}; do
echo " domain-insecure: ${zone}"
done
fi
echo "forward-zone:"
echo " name: \".\""
# Force using TLS only
if [ "${PROTO}" = "TLS" ]; then
echo " forward-tls-upstream: yes"
fi
# Add upstream name servers
local ns
for ns in $(read_name_servers); do
echo " forward-addr: ${ns}"
done
) > /etc/unbound/forward.conf
}
write_tuning_conf() {
# https://www.unbound.net/documentation/howto_optimise.html
# Determine number of online processors
local processors=$(getconf _NPROCESSORS_ONLN)
# Determine number of slabs
local slabs=1
while [ ${slabs} -lt ${processors} ]; do
slabs=$(( ${slabs} * 2 ))
done
# Determine amount of system memory
local mem=$(get_memory_amount)
# In the worst case scenario, unbound can use double the
# amount of memory allocated to a cache due to malloc overhead
# Even larger systems with more than 8GB of RAM
if [ ${mem} -ge 8192 ]; then
mem=1024
# Extra large systems with more than 4GB of RAM
elif [ ${mem} -ge 4096 ]; then
mem=512
# Large systems with more than 2GB of RAM
elif [ ${mem} -ge 2048 ]; then
mem=256
# Medium systems with more than 1GB of RAM
elif [ ${mem} -ge 1024 ]; then
mem=128
# Small systems with less than 256MB of RAM
elif [ ${mem} -le 256 ]; then
mem=16
# Everything else
else
mem=64
fi
(
config_header
# We run one thread per processor
echo "num-threads: ${processors}"
echo "so-reuseport: yes"
# Adjust number of slabs
echo "infra-cache-slabs: ${slabs}"
echo "key-cache-slabs: ${slabs}"
echo "msg-cache-slabs: ${slabs}"
echo "rrset-cache-slabs: ${slabs}"
# Slice up the cache
echo "rrset-cache-size: $(( ${mem} / 2 ))m"
echo "msg-cache-size: $(( ${mem} / 4 ))m"
echo "key-cache-size: $(( ${mem} / 4 ))m"
# Increase parallel queries
echo "outgoing-range: 8192"
echo "num-queries-per-thread: 4096"
# Use larger send/receive buffers
echo "so-sndbuf: 4m"
echo "so-rcvbuf: 4m"
) > /etc/unbound/tuning.conf
}
get_memory_amount() {
local key val unit
while read -r key val unit; do
case "${key}" in
MemTotal:*)
# Convert to MB
echo "$(( ${val} / 1024 ))"
break
;;
esac
done < /proc/meminfo
}
fix_time_if_dns_fails() {
# If DNS is working, everything is fine
if resolve "ping.ipfire.org" &>/dev/null; then
return 0
fi
# Try to sync time with a known time server
boot_mesg "DNS not functioning... Trying to sync time with ntp.ipfire.org (81.3.27.46)..."
loadproc /usr/local/bin/settime 81.3.27.46
}
resolve() {
local hostname="${1}"
local answer
for answer in $(dig +short A "${hostname}"); do
# Filter out non-IP addresses
if [[ ! "${answer}" =~ \.$ ]]; then
echo "${answer}"
fi
done
}
update_forwarders() {
# Do nothing when we do not use the ISP name servers
[ "${USE_ISP_NAMESERVERS}" != "on" ] && return 0
# We cannot update anything when using TLS
# Unbound will then try to connect to the servers using UDP on port 853
[ "${PROTO}" = "TLS" ] && return 0
# Update unbound about the new servers
local nameservers=( $(read_name_servers) )
if [ -n "${nameservers[*]}" ]; then
unbound-control -q forward "${nameservers[@]}"
else
unbound-control -q forward off
fi
}
# Sets up Safe Search for various search engines
update_safe_search() {
local google_tlds=(
google.ad
google.ae
google.al
google.am
google.as
google.at
google.az
google.ba
google.be
google.bf
google.bg
google.bi
google.bj
google.bs
google.bt
google.by
google.ca
google.cat
google.cd
google.cf
google.cg
google.ch
google.ci
google.cl
google.cm
google.cn
google.co.ao
google.co.bw
google.co.ck
google.co.cr
google.co.id
google.co.il
google.co.in
google.co.jp
google.co.ke
google.co.kr
google.co.ls
google.com
google.co.ma
google.com.af
google.com.ag
google.com.ai
google.com.ar
google.com.au
google.com.bd
google.com.bh
google.com.bn
google.com.bo
google.com.br
google.com.bz
google.com.co
google.com.cu
google.com.cy
google.com.do
google.com.ec
google.com.eg
google.com.et
google.com.fj
google.com.gh
google.com.gi
google.com.gt
google.com.hk
google.com.jm
google.com.kh
google.com.kw
google.com.lb
google.com.ly
google.com.mm
google.com.mt
google.com.mx
google.com.my
google.com.na
google.com.nf
google.com.ng
google.com.ni
google.com.np
google.com.om
google.com.pa
google.com.pe
google.com.pg
google.com.ph
google.com.pk
google.com.pr
google.com.py
google.com.qa
google.com.sa
google.com.sb
google.com.sg
google.com.sl
google.com.sv
google.com.tj
google.com.tr
google.com.tw
google.com.ua
google.com.uy
google.com.vc
google.com.vn
google.co.mz
google.co.nz
google.co.th
google.co.tz
google.co.ug
google.co.uk
google.co.uz
google.co.ve
google.co.vi
google.co.za
google.co.zm
google.co.zw
google.cv
google.cz
google.de
google.dj
google.dk
google.dm
google.dz
google.ee
google.es
google.fi
google.fm
google.fr
google.ga
google.ge
google.gg
google.gl
google.gm
google.gp
google.gr
google.gy
google.hn
google.hr
google.ht
google.hu
google.ie
google.im
google.iq
google.is
google.it
google.je
google.jo
google.kg
google.ki
google.kz
google.la
google.li
google.lk
google.lt
google.lu
google.lv
google.md
google.me
google.mg
google.mk
google.ml
google.mn
google.ms
google.mu
google.mv
google.mw
google.ne
google.nl
google.no
google.nr
google.nu
google.pl
google.pn
google.ps
google.pt
google.ro
google.rs
google.ru
google.rw
google.sc
google.se
google.sh
google.si
google.sk
google.sm
google.sn
google.so
google.sr
google.st
google.td
google.tg
google.tk
google.tl
google.tm
google.tn
google.to
google.tt
google.vg
google.vu
google.ws
)
# Cleanup previous settings
unbound-control local_zone_remove "bing.com" >/dev/null
unbound-control local_zone_remove "duckduckgo.com" >/dev/null
unbound-control local_zone_remove "yandex.com" >/dev/null
unbound-control local_zone_remove "yandex.ru" >/dev/null
unbound-control local_zone_remove "youtube.com" >/dev/null
local domain
for domain in ${google_tlds[@]}; do
unbound-control local_zone_remove "${domain}"
done >/dev/null
# Nothing to do if safe search is not enabled
if [ "${ENABLE_SAFE_SEARCH}" != "on" ]; then
return 0
fi
# Bing
unbound-control bing.com transparent >/dev/null
for address in $(resolve "strict.bing.com"); do
unbound-control local_data "www.bing.com ${LOCAL_TTL} IN A ${address}"
done >/dev/null
# DuckDuckGo
unbound-control local_zone duckduckgo.com typetransparent >/dev/null
for address in $(resolve "safe.duckduckgo.com"); do
unbound-control local_data "duckduckgo.com ${LOCAL_TTL} IN A ${address}"
done >/dev/null
# Google
local addresses="$(resolve "forcesafesearch.google.com")"
for domain in ${google_tlds[@]}; do
unbound-control local_zone "${domain}" transparent >/dev/null
for address in ${addresses}; do
unbound-control local_data: "www.${domain} ${LOCAL_TTL} IN A ${address}"
done >/dev/null
done
# Yandex
for domain in yandex.com yandex.ru; do
unbound-control local_zone "${domain}" typetransparent >/dev/null
for address in $(resolve "familysearch.${domain}"); do
unbound-control local_data "${domain} ${LOCAL_TTL} IN A ${address}"
done >/dev/null
done
# YouTube
unbound-control local_zone youtube.com transparent >/dev/null
for address in $(resolve "restrictmoderate.youtube.com"); do
unbound-control local_data "www.youtube.com ${LOCAL_TTL} IN A ${address}"
done >/dev/null
return 0
}
case "$1" in
start)
# Print a nicer messagen when unbound is already running
if pidofproc -s unbound; then
statusproc /usr/sbin/unbound
exit 0
fi
# Update configuration files
write_tuning_conf
write_forward_conf
boot_mesg "Starting Unbound DNS Proxy..."
loadproc /usr/sbin/unbound || exit $?
# Install Safe Search rules when the system is already online
if [ -e "/var/ipfire/red/active" ]; then
update_safe_search
fi
# Update hosts
update_hosts
;;
stop)
boot_mesg "Stopping Unbound DNS Proxy..."
killproc /usr/sbin/unbound
;;
restart)
$0 stop
sleep 1
$0 start
;;
reload)
# Update configuration files
write_tuning_conf
write_forward_conf
# Update Safe Search rules if the system is online.
if [ -e "/var/ipfire/red/active" ]; then
update_safe_search
fi
# Update hosts.
update_hosts
# Call unbound-control and perform the reload
/usr/sbin/unbound-control -q reload
;;
status)
statusproc /usr/sbin/unbound
;;
update-forwarders)
update_forwarders
# Make sure DNS works at this point
fix_time_if_dns_fails
# Update Safe Search settings
update_safe_search
;;
remove-forwarders)
update_forwarders
;;
resolve)
resolve "${2}"
;;
update-safe-search)
update_safe_search
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status|resolve|update-forwarders|remove-forwarders|update-safe-search}"
exit 1
;;
esac
# End $rc_base/init.d/unbound