From 954828904b8c8968796d083ae3a1b17433739540 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Thu, 3 Nov 2022 09:02:10 +0100 Subject: [PATCH] replace bind9 with unbound --- conf/unbound.conf | 68 +++++++++++++++++++++++++++++++++++++ management/dns_update.py | 4 +-- management/status_checks.py | 15 ++++---- setup/dns.sh | 4 +-- setup/system.sh | 57 +++++++++++++++---------------- 5 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 conf/unbound.conf diff --git a/conf/unbound.conf b/conf/unbound.conf new file mode 100644 index 00000000..30880afe --- /dev/null +++ b/conf/unbound.conf @@ -0,0 +1,68 @@ +server: + # the working directory. + directory: "/etc/unbound" + + # run as the unbound user + username: unbound + + verbosity: 0 # uncomment and increase to get more logging. + # logfile: "/var/log/unbound.log" # won't work due to apparmor + # use-syslog: no + + # By default listen only to localhost + #interface: ::1 + #interface: 127.0.0.1 + port: 53 + + # Only allow localhost to use this Unbound instance. + access-control: 127.0.0.1/8 allow + access-control: ::1/128 allow + + # Private IP ranges, which shall never be returned or forwarded as public DNS response. + private-address: 10.0.0.0/8 + private-address: 172.16.0.0/12 + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + private-address: fd00::/8 + private-address: fe80::/10 + + # Functionality + do-ip4: yes + do-ip6: yes + do-udp: yes + do-tcp: yes + + # Performance + num-threads: 2 + cache-min-ttl: 300 + cache-max-ttl: 86400 + serve-expired: yes + neg-cache-size: 4M + msg-cache-size: 50m + rrset-cache-size: 100m + + so-reuseport: yes + so-rcvbuf: 4m + so-sndbuf: 4m + + # Privacy / hardening + # hide server info from clients + hide-identity: yes + hide-version: yes + harden-glue: yes + harden-dnssec-stripped: yes + harden-algo-downgrade: yes + harden-large-queries: yes + harden-short-bufsize: yes + + rrset-roundrobin: yes + minimal-responses: yes + identity: "Server" + + # Include possible white/blacklists + include: /etc/unbound/lists.d/*.conf + +remote-control: + control-enable: yes + control-port: 953 + diff --git a/management/dns_update.py b/management/dns_update.py index 2bfc104f..5505ff2a 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -118,9 +118,9 @@ def do_dns_update(env, force=False): # If this is the only thing that changed? updated_domains.append("OpenDKIM configuration") - # Clear bind9's DNS cache so our own DNS resolver is up to date. + # Clear unbound's DNS cache so our own DNS resolver is up to date. # (ignore errors with trap=True) - shell('check_call', ["/usr/sbin/rndc", "flush"], trap=True) + shell('check_call', ["/usr/sbin/unbound-control", "flush_zone", "."], trap=True) if len(updated_domains) == 0: # if nothing was updated (except maybe OpenDKIM's files), don't show any output diff --git a/management/status_checks.py b/management/status_checks.py index 0d555441..f59042f8 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -22,9 +22,8 @@ from utils import shell, sort_domains, load_env_vars_from_file, load_settings def get_services(): return [ - { "name": "Local DNS (bind9)", "port": 53, "public": False, }, - #{ "name": "NSD Control", "port": 8952, "public": False, }, - { "name": "Local DNS Control (bind9/rndc)", "port": 953, "public": False, }, + { "name": "Local DNS (unbound)", "port": 53, "public": False, }, + { "name": "Local DNS Control (unbound)", "port": 953, "public": False, }, { "name": "Dovecot LMTP LDA", "port": 10026, "public": False, }, { "name": "Postgrey", "port": 10023, "public": False, }, { "name": "Spamassassin", "port": 10025, "public": False, }, @@ -49,15 +48,15 @@ def run_checks(rounded_values, env, output, pool, domains_to_check=None): # check that services are running if not run_services_checks(env, output, pool): - # If critical services are not running, stop. If bind9 isn't running, + # If critical services are not running, stop. If unbound isn't running, # all later DNS checks will timeout and that will take forever to # go through, and if running over the web will cause a fastcgi timeout. return - # clear bind9's DNS cache so our DNS checks are up to date - # (ignore errors; if bind9/rndc isn't running we'd already report + # clear unbound's DNS cache so our DNS checks are up to date + # (ignore errors; if unbound isn't running we'd already report # that in run_services checks.) - shell('check_call', ["/usr/sbin/rndc", "flush"], trap=True) + shell('check_call', ["/usr/sbin/unbound-control", "flush_zone", "."], trap=True) run_system_checks(rounded_values, env, output) @@ -785,7 +784,7 @@ def query_dns(qname, rtype, nxdomain='[Not Set]', at=None, as_list=False): qname += "." # Use the default nameservers (as defined by the system, which is our locally - # running bind server), or if the 'at' argument is specified, use that host + # running unbound server), or if the 'at' argument is specified, use that host # as the nameserver. resolver = dns.resolver.get_default_resolver() if at: diff --git a/setup/dns.sh b/setup/dns.sh index 9b9b1b0a..59420d8b 100755 --- a/setup/dns.sh +++ b/setup/dns.sh @@ -12,7 +12,7 @@ source /etc/mailinabox.conf # load global vars # Prepare nsd's configuration. # We configure nsd before installation as we only want it to bind to some addresses -# and it otherwise will have port / bind conflicts with bind9 used as the local resolver +# and it otherwise will have port / bind conflicts with unbound used as the local resolver mkdir -p /var/run/nsd mkdir -p /etc/nsd mkdir -p /etc/nsd/zones @@ -38,7 +38,7 @@ server: EOF -# Since we have bind9 listening on localhost for locally-generated +# Since we have unbound listening on localhost for locally-generated # DNS queries that require a recursive nameserver, and the system # might have other network interfaces for e.g. tunnelling, we have # to be specific about the network interfaces that nsd binds to. diff --git a/setup/system.sh b/setup/system.sh index d0003f9c..3994484b 100755 --- a/setup/system.sh +++ b/setup/system.sh @@ -314,45 +314,42 @@ fi #NODOC # DNS server, which won't work for RBLs. So we really need a local recursive # nameserver. # -# We'll install `bind9`, which as packaged for Ubuntu, has DNSSEC enabled by default via "dnssec-validation auto". +# We'll install unbound, which as packaged for Ubuntu, has DNSSEC enabled by default. # We'll have it be bound to 127.0.0.1 so that it does not interfere with # the public, recursive nameserver `nsd` bound to the public ethernet interfaces. -# -# About the settings: -# -# * Adding -4 to OPTIONS will have `bind9` not listen on IPv6 addresses -# so that we're sure there's no conflict with nsd, our public domain -# name server, on IPV6. -# * The listen-on directive in named.conf.options restricts `bind9` to -# binding to the loopback interface instead of all interfaces. -# * The max-recursion-queries directive increases the maximum number of iterative queries. -# If more queries than specified are sent, bind9 returns SERVFAIL. After flushing the cache during system checks, -# we ran into the limit thus we are increasing it from 75 (default value) to 100. -apt_install bind9 -tools/editconf.py /etc/default/named \ - "OPTIONS=\"-u bind -4\"" -if ! grep -q "listen-on " /etc/bind/named.conf.options; then - # Add a listen-on directive if it doesn't exist inside the options block. - sed -i "s/^}/\n\tlisten-on { 127.0.0.1; };\n}/" /etc/bind/named.conf.options -fi -if ! grep -q "max-recursion-queries " /etc/bind/named.conf.options; then - # Add a max-recursion-queries directive if it doesn't exist inside the options block. - sed -i "s/^}/\n\tmax-recursion-queries 100;\n}/" /etc/bind/named.conf.options + +# remove bind9 in case it is still there +apt-get purge -qq -y bind9 bind9-utils + +# Install unbound and dns utils (e.g. dig) +apt_install unbound python3-unbound bind9-dnsutils + +# Configure unbound +cp -f conf/unbound.conf /etc/unbound/unbound.conf.d/miabunbound.conf + +mkdir -p /etc/unbound/lists.d + +systemctl restart unbound + +unbound-control -q status + +# Only reset the local dns settings if unbound server is running, otherwise we'll +# up with a system with an unusable internet connection +if [ $? -ne 0 ]; then + echo "Recursive DNS server not active" + exit 1 fi -# First we'll disable systemd-resolved's management of resolv.conf and its stub server. -# Breaking the symlink to /run/systemd/resolve/stub-resolv.conf means -# systemd-resolved will read it for DNS servers to use. Put in 127.0.0.1, -# which is where bind9 will be running. Obviously don't do this before -# installing bind9 or else apt won't be able to resolve a server to -# download bind9 from. +# Modify systemd settings rm -f /etc/resolv.conf -tools/editconf.py /etc/systemd/resolved.conf DNSStubListener=no +tools/editconf.py /etc/systemd/resolved.conf \ + DNS=127.0.0.1 \ + DNSSEC=yes \ + DNSStubListener=no echo "nameserver 127.0.0.1" > /etc/resolv.conf # Restart the DNS services. -restart_service bind9 systemctl restart systemd-resolved # ### Fail2Ban Service