wren-linux / lib / secure-dns.sh
# shellcheck shell=bash
# lib/secure-dns.sh: the DNS-over-TLS resolvers parts/secure-dns.sh offers,
# and the files it writes. Sourced after lib.sh (by the extra, status.sh and
# the tests). The addresses are pinned in pins.sh (DOT_*). Where the files are
# is in lib/net.sh (SECURE_DNS_CONF), since wifi.sh needs to know too.
# In the order they are offered
DNS_PROVIDERS=(quad9 digiges appliedprivacy)
# dns_pin NAME: "TLS-NAME ADDRESS..." from pins.sh
dns_pin() {
case $1 in
quad9) echo "$DOT_QUAD9" ;;
digiges) echo "$DOT_DIGIGES" ;;
appliedprivacy) echo "$DOT_APPLIEDPRIVACY" ;;
*) return 1 ;;
esac
}
# dns_describe NAME: one line on who it is
dns_describe() {
case $1 in
quad9) echo "Quad9 (Switzerland, the Quad9 Foundation): also blocks known malware sites" ;;
digiges) echo "Digitale Gesellschaft (Switzerland, an association): no filtering, says it logs no queries" ;;
appliedprivacy) echo "Applied Privacy (Austria, the Foundation for Applied Privacy): no filtering, one server" ;;
*) return 1 ;;
esac
}
# dns_tls_name NAME: the name the resolver's certificate must carry
dns_tls_name() { local p; p=$(dns_pin "$1") || return 1; echo "${p%% *}"; }
# dns_unbound_conf NAME: Unbound's settings for that resolver. Debian's own
# root-auto-trust-anchor-file.conf already turns DNSSEC checking on; this adds
# where Unbound listens and where it asks.
dns_unbound_conf() {
local name=$1 pin tls a
pin=$(dns_pin "$name") || return 1
tls=${pin%% *}
cat <<EOF
# Written by Wren Linux parts/secure-dns.sh. Run it again to change the resolver.
# provider: $name
# Unbound answers this computer only, checks every answer with DNSSEC, and asks
# $tls, encrypted (DNS over TLS on port 853); its certificate has to be
# for that name. Nothing goes out unencrypted, and nothing falls back.
server:
interface: 127.0.0.1
access-control: 127.0.0.0/8 allow
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
hide-identity: yes
hide-version: yes
harden-dnssec-stripped: yes
val-permissive-mode: no
prefetch: yes
forward-zone:
name: "."
forward-tls-upstream: yes
forward-first: no
EOF
for a in ${pin#* }; do
printf ' forward-addr: %s@853#%s\n' "$a" "$tls"
done
}
# dns_current: the resolver in use (from SECURE_DNS_CONF), or nothing. Always
# succeeds: on a first run there is no file, and under pipefail sed's error
# would end the script that asked (current=$(dns_current)) without a word.
dns_current() {
{ sed -n 's/^# provider: //p' "${WREN_ETC:-/etc}/unbound/unbound.conf.d/wren-secure-dns.conf" 2>/dev/null || true; } | head -1
}
# dns_status: one line for status.sh
dns_status() {
local name tls
if secure_dns_on && name=$(dns_current) && tls=$(dns_tls_name "$name"); then
echo "DNS: encrypted to $tls, checked with DNSSEC (secure DNS on; the Wren menu switches it)"
elif secure_dns_installed; then
echo "DNS: unencrypted for now, to the network's DNS server: secure DNS is switched off (secure-dns on)"
else
echo "DNS: unencrypted, to the network's DNS server (parts/secure-dns.sh encrypts it)"
fi
}