Bind als Caching-Only-DNS-Resolver¶
| Stand: 03/2025 |
|---|
| Verwendete Software - Ubuntu 24.04 LTS - Bind9 9.18.30 |
| Weitere Dokumentationen: |
Vorwort¶
Diese Dokumentation beschreibt die Installation eines Caching-Only-DNS-Resolver mit Bind.
Ziel der Dokumentation ist es, die Einrichtung und Konfiguration eines Caching-Only-DNS-Resolvers zu beschreiben, der DNS-Anfragen effizient lokal zwischenspeichert und so die Namensauflösung beschleunigt, ohne selbst autoritative Zonen bereitzustellen.
Es sind Grundkenntnisse im Umgang mit Linux erforderlich, da die Vorgehensweise, wie sie hier beschrieben ist, in manchen Teilen abweichen kann. Kein System ist wie das Andere. Die Dokumentation wurde sorgfältig von mir geprüft. Dennoch kann ich keinerlei Haftung für Schäden an Ihrem System oder eine Gewährleistung übernehmen. Bitte verwenden Sie diese Dokumentation auf eigene Gefahr.
Server vorbereiten¶
Root-Rechte einräumen¶
Während der gesamten Dokumentation werden Root-Rechte benötigt. Um auf das Voranstellen von sudo zu verzichten, verschaffen Sie sich für die gesamte Sitzung erhöhte Rechte mit:
sudo -i
Update durchführen¶
Bringen Sie den Server auf den aktuellen Patchstand:
apt update && apt upgrade
Software installieren¶
Laden Sie Bind aus dem offiziellen Ubuntu-Repository herunter:
apt install bind9
Bind einrichten¶
Bind9 konfigurieren¶
Hinweis!
Wenn Sie den DNS-Resolver an einem Internet-Anschluss ohne Dual-Stack (ohne IPv6) betreiben, muss IPv6 in Bind deaktiviert werden, da Bind ansonsten versucht, die Namensauflösung über die IPv6-Adressen der Root-Server durchzuführen.
Editieren Sie die dazu die Datei /etc/default/named und ändern Sie folgenden Parameter:
nano /etc/default/named
OPTIONS="-u bind -4"
Fügen Sie der Datei
/etc/bind/named.conf.options folgendes hinzu, damit IPv6-Adressen bei der DNS-Abfrage ausgeblendet werden:
nano /etc/bind/named.conf.options
plugin query "filter-aaaa.so" {
filter-aaaa-on-v4 yes;
};
Benennen Sie zunächst die /etc/bind/named.conf.options um, damit Sie eine Sicherheitskopie der Original-Datei haben:
mv /etc/bind/named.conf.options /etc/bind/named.conf.options.bak
Erstellen Sie eine neue Datei
/etc/bind/named.conf.options:
nano /etc/bind/named.conf.options
options {
directory "/var/cache/bind";
dnssec-validation auto;
auth-nxdomain no;
recursion yes;
listen-on {
127.0.0.1;
};
allow-query {
127.0.0.1;
};
allow-transfer { none; };
allow-update { none; };
version none;
hostname none;
server-id none;
};
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; };
};
Editieren Sie die Date
/etc/bind/named.conf.default-zones und ändern Sie folgenden Parameter:
nano /etc/bind/named.conf.default-zones
zone "." {
type hint;
file "/etc/bind/db.root";
};
Root-Hints und DNSSEC-Keys aktualisieren¶
Laden Sie die Liste der Root-DNS-Server /etc/bind/db.root herunter:
dig +bufsize=1200 +norec NS . @a.root-servers.net > /etc/bind/db.root
Laden Sie die Liste der dazugehörigen DNSSEC-Keys
/etc/bind/bind.keys herunter:
wget "https://ftp.isc.org/isc/bind9/keys/9.11/bind.keys.v9_11" -q -O /etc/bind/bind.keys
Löschen Sie eventuell vorhandene Cache-Dateien:
rm /var/cache/bind/managed-keys.bind*
Starten Sie Bind neu, damit die Konfiguration angewendet wird:
service bind9 restart
Cron-Job einrichten¶
Info
Die Liste der Root-Nameserver und die dazugehörigen DNSSEC-Keys können sich in unregelmäßigen Abständen ändern. Damit unser DNS-Resolver reibungslos DNS-Abfragen durchführen kann, müssen die Listen immer auf dem neuesten Stand gehalten werden.
Dieser Cron-Job aktualisiert wöchentlich beide Listen und versendet einen Status-Report per E-Mail.
Erstellen Sie die Datei/etc/cron.weekly/twilight-bind-roothints mit folgendem Inhalt:
nano /etc/cron.weekly/twilight-bind-roothints
#!/bin/sh
#
# ___________ .__.__ .__ .__ __
# \__ ___/_ _ _|__| | |__| ____ | |___/ |_
# | | \ \/ \/ / | | | |/ ___\| | \ __\
# | | \ /| | |_| / /_/ > Y \ |
# |____| \/\_/ |__|____/__\___ /|___| /__|
# /_____/ \/
#
# Twilight-Networks ∙ est. 2k1 ∙ fxp ∙ h4x ∙ nfo ∙ scene ∙ legacy lives
# Keep it lean, keep it silent. Code like it's 2002.
#
##########################################################################
# Script Name : twilight-bind-roothints
# Description : Updates BIND9 root hints (db.root) and DNSSEC keys
# (bind.keys) from official sources. Automatically
# creates backups and sends status notifications
# via email. Designed for use in cron environments.
#
# Version : 1.01
# Last Update : 2025-03-28
# Author : Twilight
# Contact : [email protected]
# Web : https://www.twilight-networks.com
#
# Getestet mit : Ubuntu 24.04 LTS
# Bind 9.18.30
##########################################################################
# Config
BINDDIR='/etc/bind'
ROOTHINTS='db.root'
ROOTHINTSKEYS='bind.keys'
CHECKONLINE='1.1.1.1'
MAILTO='[email protected]'
MAILFROM='[email protected]'
DNSSEC_URL="https://ftp.isc.org/isc/bind9/keys/9.11/bind.keys.v9_11"
EMAILREPORT=true
# Below this line: scene code. You break it, you bought it.
#########################################################################
# Internal
TMPDIR=$(mktemp -d /tmp/bindupdate.XXXXXX)
ROOTHINTS_NEW="${TMPDIR}/${ROOTHINTS}.new"
ROOTHINTSKEYS_NEW="${TMPDIR}/${ROOTHINTSKEYS}.new"
ERRORLOG_ROOT="${TMPDIR}/errors_roothints"
ERRORLOG_KEYS="${TMPDIR}/errors_keys"
HOSTNAME_SHORT=$(hostname -s)
cleanup() {
rm -rf "$TMPDIR"
}
trap cleanup EXIT
# Check BIND
check_bind_status() {
if ! rndc status 2>/dev/null | grep -q "server is"; then
log_error "[ERROR] Bind ist nicht aktiv oder rndc verweigert Zugriff."
exit 1
fi
}
# Check Internet
check_network() {
if ! ping -qnc 1 "$CHECKONLINE" >/dev/null 2>&1; then
log_error "[ERROR] Keine Internetverbindung zu $CHECKONLINE."
exit 1
fi
}
# Download root hints
download_roothints() {
dig +bufsize=1200 +norec NS . @a.root-servers.net >"$ROOTHINTS_NEW" 2>"$ERRORLOG_ROOT"
grep -q 'NOERROR' "$ROOTHINTS_NEW" || {
log_error "[ERROR] Fehler beim Download der Root-Hints."
cat "$ERRORLOG_ROOT"
exit 1
}
}
# Download DNSSEC keys
download_dnssec_keys() {
wget "$DNSSEC_URL" -q -O "$ROOTHINTSKEYS_NEW" 2>"$ERRORLOG_KEYS"
grep -q 'managed-keys' "$ROOTHINTSKEYS_NEW" || {
log_error "[ERROR] Fehler beim Download der DNSSEC-Keys."
cat "$ERRORLOG_KEYS"
exit 1
}
}
# Vergleichsfunktion, die auch bei fehlenden Altdateien sauber arbeitet
filtered_sha256() {
grep -vE '^\s*(;|$)' "$1" | sha256sum | awk '{print $1}'
}
files_differ() {
[ ! -f "$2" ] && return 0
old_hash=$(filtered_sha256 "$2")
new_hash=$(filtered_sha256 "$1")
[ "$old_hash" != "$new_hash" ]
}
# Logging
log_info() {
logger -t bind-update "$1"
echo "$1"
}
log_error() {
logger -t bind-update "$1"
echo "$1" >&2
$EMAILREPORT && report_error "$1" "$(tail -n 50 "$ERRORLOG_ROOT" "$ERRORLOG_KEYS" 2>/dev/null | grep -v '^$' || echo "Keine weiteren Details verfügbar.")"
}
# Report-E-Mail
report_success() {
{
echo "From: $MAILFROM"
echo "To: $MAILTO"
echo "Subject: [bind] [OK] ${HOSTNAME_SHORT} Root-Hints und DNSSEC-Keys aktualisiert"
echo "MIME-Version: 1.0"
echo "Content-Type: text/html; charset=UTF-8"
echo
echo "<html><body><pre style=\"font-family: monospace; font-size: 13px; color: #333; background: #f9f9f9; padding: 1em; border: 1px solid #ccc;\">"
echo "Aktualisierung erfolgreich:"
echo "- $BINDDIR/$ROOTHINTS"
echo "- $BINDDIR/$ROOTHINTSKEYS"
echo
echo "Backups unter:"
echo "- $BINDDIR/${ROOTHINTS}.bak"
echo "- $BINDDIR/${ROOTHINTSKEYS}.bak"
echo "</pre></body></html>"
} | /usr/sbin/sendmail -t
}
report_nochange() {
{
echo "From: $MAILFROM"
echo "To: $MAILTO"
echo "Subject: [bind] [OK] ${HOSTNAME_SHORT} Root-Hints und DNSSEC-Keys unverändert"
echo "MIME-Version: 1.0"
echo "Content-Type: text/html; charset=UTF-8"
echo
echo "<html><body><pre style=\"font-family: monospace; font-size: 13px; color: #333; background: #f9f9f9; padding: 1em; border: 1px solid #ccc;\">"
echo "Es waren keine Änderungen erforderlich. Bind wurde nicht neugestartet."
echo "</pre></body></html>"
} | /usr/sbin/sendmail -t
}
report_error() {
local subject="$1"
local message="$2"
{
echo "From: $MAILFROM"
echo "To: $MAILTO"
echo "Subject: [bind] [ERROR] ${HOSTNAME_SHORT} $subject"
echo "MIME-Version: 1.0"
echo "Content-Type: text/html; charset=UTF-8"
echo
echo "<html><body><pre style=\"font-family: monospace; font-size: 13px; color: #333; background: #f9f9f9; padding: 1em; border: 1px solid #ccc;\">"
echo "$message"
echo "</pre></body></html>"
} | /usr/sbin/sendmail -t
}
perform_update() {
log_info "[INFO] Änderungen erkannt – Update wird durchgeführt."
cp "$BINDDIR/$ROOTHINTS" "$BINDDIR/${ROOTHINTS}.bak" 2>/dev/null || true
cp "$BINDDIR/$ROOTHINTSKEYS" "$BINDDIR/${ROOTHINTSKEYS}.bak" 2>/dev/null || true
install -o root -g root -m 444 "$ROOTHINTS_NEW" "$BINDDIR/$ROOTHINTS"
install -o root -g root -m 444 "$ROOTHINTSKEYS_NEW" "$BINDDIR/$ROOTHINTSKEYS"
rndc reload
log_info "[INFO] Bind wurde neu geladen."
$EMAILREPORT && report_success
}
main() {
check_bind_status
check_network
cd "$BINDDIR" || {
log_error "[ERROR] Zugriff auf $BINDDIR nicht möglich."
exit 1
}
download_roothints
download_dnssec_keys
if files_differ "$ROOTHINTS_NEW" "$ROOTHINTS" || files_differ "$ROOTHINTSKEYS_NEW" "$ROOTHINTSKEYS"; then
perform_update
else
log_info "[INFO] Keine Änderungen erkannt – kein Update notwendig."
$EMAILREPORT && report_nochange
fi
}
main
#end
[...]
# Reports are sent to
MAILTO='[email protected]'
# Reports are sent by
MAILFROM='[email protected]'
[...]
Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:
chmod +x /etc/cron.weekly/twilight-bind-roothints
DNS-Resolver via Netplan bekanntgeben¶
Editieren Sie die Datei /etc/netplan/50-cloud-init.yaml und tragen Sie 127.0.0.1 als Nameserver ein:
Ersetzen Sie 50-cloud-init.yaml durch die Datei, die auf Ihrem System verwendet wird.
nano /etc/netplan/50-cloud-init.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
nameservers:
search: [example.com]
addresses:
- "127.0.0.1"
Wenden Sie die neue Konfiguration an:
netplan apply
Kontrollieren Sie, ob der lokale DNS-Resolver (
127.0.0.1) als Nameserver verwendet wird:
resolvectl status
[...]
Link 2 (eth0)
Current Scopes: DNS
DefaultRoute setting: yes
LLMNR setting: yes
MulticastDNS setting: no
DNSOverTLS setting: no
DNSSEC setting: no
DNSSEC supported: no
Current DNS Server: 127.0.0.1
DNS Servers: 127.0.0.1
DNS Domain: example.com
Inbetriebnahme und Test¶
DNS-Resolver testen¶
Fragen Sie einen Hostnamen (z. B. heise.de) ab und kontrollieren Sie die Ausgabe:
nslookup heise.de
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: heise.de
Address: 193.99.144.80
Abschluss¶
Wenn die DNS-Abfrage erfolgreich verlief und Sie keine Fehlermeldungen erhalten haben, ist Ihr DNS-Resolver einsatzbereit.
