diff --git a/management/dns_update.py b/management/dns_update.py index 08ec4e3b..fc8ee5c2 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -271,6 +271,7 @@ $TTL 86400 ; default time to live ######################################################################## def write_nsd_conf(zonefiles): + # Basic header. nsdconf = """ server: hide-version: yes @@ -280,10 +281,19 @@ server: # The directory for zonefile: files. zonesdir: "/etc/nsd/zones" - -# ZONES """ + + # Since we have bind9 listening on localhost for locally-generated + # DNS queries that require a recursive nameserver, we must have + # nsd listen only on public network interfaces. Those interfaces + # may have addresses different from the public IP address that the + # Internet sees this machine on. Get those interface addresses + # from `hostname -i` (which omits all localhost addresses). + for ipaddr in shell("check_output", ["/bin/hostname", "-I"]).strip().split(" "): + nsdconf += "ip-address: %s\n" % ipaddr + + # Append the zones. for domain, zonefile in sorted(zonefiles): nsdconf += """ zone: diff --git a/setup/system.sh b/setup/system.sh index 70e56a38..38c6a6e9 100755 --- a/setup/system.sh +++ b/setup/system.sh @@ -30,3 +30,34 @@ if [ -z "$DISABLE_FIREWALL" ]; then ufw_allow ssh; ufw --force enable; fi + +# Resolve DNS using bind9 locally, rather than whatever DNS server is supplied +# by the machine's network configuration. We do this to ensure that DNS queries +# that *we* make (i.e. looking up other external domains) perform DNSSEC checks. +# We could use Google's Public DNS, but we don't want to create a dependency on +# Google per our goals of decentralization. bind9, as packaged for Ubuntu, has +# DNSSEC enabled by default via "dnssec-validation auto". +# +# So we'll be running bind9 bound to 127.0.0.1 for locally-issued DNS queries +# and nsd bound to the public ethernet interface for remote DNS queries asking +# about our domain names. nsd is configured in dns.sh. +# +# About the settings: +# +# * RESOLVCONF=yes will have bind9 take over /etc/resolv.conf to tell +# local services that DNS queries are handled on localhost. +# * 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. +apt_install bind9 +tools/editconf.py /etc/default/bind9 \ + RESOLVCONF=yes \ + "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 + +service bind9 restart