Pi-hole + Unbound: DNS ohne externen Mittelsmann
Werbung blocken ist gut. Aber selbst mit Pi-hole sehen externe DNS-Anbieter jeden Domainnamen, den Ihr Netzwerk auflöst. Dieser Guide zeigt, wie Unbound als rekursiver Resolver diesen letzten Datentransfer eliminiert — und warum sich das nicht nur für das Homelab lohnt.
Das DNS-Privacy-Problem
Jedes Mal, wenn ein Gerät in Ihrem Netzwerk eine Website aufruft, fragt es zuerst einen DNS-Server: "Welche IP-Adresse hat diese Domain?" Diese Anfragen verraten mehr als es auf den ersten Blick scheint.
Selbst ohne den eigentlichen Seiteninhalt zu kennen, entsteht aus DNS-Logs ein detailliertes Profil: welche Dienste genutzt werden, zu welchen Zeiten, wie häufig. Das betrifft Privatpersonen — und Unternehmen noch mehr.
Wer seinen DNS-Verkehr über externe Resolver wie 8.8.8.8 (Google), 9.9.9.9 (Quad9) oder 1.1.1.1 (Cloudflare) laufen lässt, gibt diesen Drittanbietern Einblick in alle aufgerufenen Domains — inklusive interner Dienste, Cloud-Anbieter, Partner-APIs und geschaeftlicher Recherchen. Ein Raspberry Pi 4 kostet rund 70 Euro und reicht als DNS-Server für kleine Netzwerke bis zu etwa 50 Geräten problemlos aus. Die Investition ist überschaubar, der Datenschutzgewinn erheblich.
Die häufig empfohlene Lösung — Pi-hole — löst einen Teil des Problems, nicht das Ganze.
Pi-hole allein: gut, aber nicht vollständig
Pi-hole ist ein DNS-Filter: Es empfängt alle DNS-Anfragen aus dem Netzwerk und blockiert bekannte Werbe- und Tracking-Domains, bevor eine Verbindung zustande kommt. Das ist wirksam und empfehlenswert.
Pi-hole löst DNS-Anfragen selbst aber nicht auf. Es leitet nicht blockierte Anfragen an einen konfigurierten Upstream-Resolver weiter — zum Beispiel Quad9 oder Cloudflare. Dieser externe Resolver sieht dann alle Anfragen, die Pi-hole durchlässt.
Google DNS (8.8.8.8) ist der meistgenutzte öffentliche Resolver — und
einer der datenschutzfeindlichsten. Wenn überhaupt ein externer Resolver verwendet
wird: Quad9 (9.9.9.9) mit DNSSEC-Validierung oder Cloudflare
(1.1.1.1) sind deutlich bessere Alternativen. Besser noch: Unbound.
Das grundsätzliche Problem bleibt: Ein Dritter im Loop sieht Ihren DNS-Verkehr. Unbound löst das.
Unbound: die elegante Lösung
Unbound ist ein validierender, rekursiver DNS-Resolver. Statt eine Anfrage an einen externen Anbieter weiterzuleiten, fragt Unbound selbst bei den autoritativen Nameservern nach — beginnend bei den DNS-Root-Servern.
Der Ablauf: Unbound fragt zuerst einen Root-Server (a.root-servers.net etc.),
der antwortet mit dem zuständigen TLD-Nameserver (z.B. für .de). Dieser
verweist auf den autoritativen Nameserver der Domain. Unbound löst die Anfrage vollständig
auf, ohne jemals eine vollständige Anfrage an einen einzelnen externen Anbieter zu stellen.
Das Ergebnis wird gecacht.
Kein externer DNS-Anbieter sieht damit den vollständigen DNS-Verkehr Ihres Netzwerks.
Architektur und Datenpfad
Der Datenpfad nach diesem Setup:
Pi-hole ist der einzige DNS-Listener im Netzwerk (Port 53). Sein Upstream zeigt
ausschliesslich auf 127.0.0.1#5533 — Unbound auf demselben Gerät.
Unbound selbst ist nur über Localhost und das lokale Netz erreichbar, nicht öffentlich.
Installation
Pi-hole installieren
Falls Pi-hole noch nicht installiert ist, verwendet das offizielle Installer-Skript den bewährten Weg:
Terminalcurl -sSL https://install.pi-hole.net | bash
Während der Installation bei der Upstream-DNS-Konfiguration einen beliebigen Wert auswählen — dieser wird im naechsten Schritt durch Unbound ersetzt. Pi-hole kann auch nachträglich über die Admin-Oberfläche umkonfiguriert werden.
Unbound installieren
Unbound ist in den Standard-Repositories aller gängigen Debian-basierten Systeme enthalten:
Terminalsudo apt update
sudo apt install unbound
Nach der Installation prüfe den Status:
Terminalsudo systemctl status unbound
Unbound startet nach der Installation mit einer minimalen Standardkonfiguration. Diese wird im naechsten Schritt durch eine gehärtete Konfiguration ersetzt.
Root-Hints aktualisieren
Unbound benötigt eine Liste der DNS-Root-Server. Diese Datei sollte gelegentlich aktualisiert werden:
Terminalsudo wget -O /etc/unbound/named.root \
https://www.internic.net/domain/named.root
Die Datei enthält die aktuellen IP-Adressen der 13 Root-Server-Gruppen.
Unbound konfigurieren
Die folgende Konfiguration basiert auf einem produktiven Homelab-Setup. Alle sicherheitsrelevanten Optionen sind aktiviert und kommentiert. Erstellen oder ersetzen Sie die Konfigurationsdatei:
/etc/unbound/unbound.conf.d/pi-hole.confserver:
# ──────────────────────────────────────────────
# Netzwerk: nur auf Localhost hören
# Pi-hole leitet intern weiter, externe Geräte
# sprechen Unbound nie direkt an.
# ──────────────────────────────────────────────
interface: 127.0.0.1
port: 5533
do-ip4: yes
do-ip6: no
prefer-ip4: yes
# Zugriffskontrolle:
# Standardmäßig alles ablehnen, dann selektiv freigeben.
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 192.168.1.0/24 allow # LAN-Subnetz anpassen
# ──────────────────────────────────────────────
# Identität verbergen
# Niemand soll erfahren, welche Software oder
# Version hier laeuft.
# ──────────────────────────────────────────────
hide-identity: yes
hide-version: yes
# ──────────────────────────────────────────────
# QNAME-Minimierung (RFC 7816)
# Unbound sendet pro Anfrage nur den minimal
# nötigen Teil des Domainnamens an jeden
# Nameserver — kein Server sieht die vollständige
# Anfrage ausser dem autoritativen Nameserver.
# ──────────────────────────────────────────────
qname-minimisation: yes
qname-minimisation-strict: yes
# ──────────────────────────────────────────────
# DNSSEC-Härtung
# Antworten werden kryptografisch validiert.
# Manipulierte oder gefälschte Antworten werden
# erkannt und verworfen.
# ──────────────────────────────────────────────
harden-glue: yes
harden-dnssec-stripped: yes
harden-below-nxdomain: yes
harden-referral-path: yes
harden-algo-downgrade: yes
harden-large-queries: yes
harden-short-bufsize: yes
# DNSSEC Trust Anchor (automatisch aktualisiert)
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# ──────────────────────────────────────────────
# Performance
# prefetch: nahezu ablaufende Cache-Einträge
# werden vorab erneuert, bevor sie ablaufen.
# serve-expired: während der Aktualisierung
# wird der abgelaufene Eintrag noch geliefert
# statt den Client warten zu lassen.
# cache-min-ttl: verhindert, dass Einträge mit
# sehr kurzer TTL den Cache unnötig belasten.
# ──────────────────────────────────────────────
prefetch: yes
serve-expired: yes
cache-min-ttl: 4400
edns-buffer-size: 1232
# ──────────────────────────────────────────────
# Weitere Sicherheitsoptionen
# use-caps-for-id: 0x20-Encoding als Schutz
# gegen Cache-Poisoning-Angriffe.
# aggressive-nsec: DNSSEC NSEC-Records werden
# genutzt um negative Antworten zu bestätigen,
# ohne den autoritativen Server erneut anzufragen.
# ──────────────────────────────────────────────
use-caps-for-id: yes
aggressive-nsec: yes
unwanted-reply-threshold: 10000
# ──────────────────────────────────────────────
# Root-Hints und lokale Zonen
# ──────────────────────────────────────────────
root-hints: "named.root"
do-not-query-localhost: no
insecure-lan-zones: yes
local-zone: "168.192.in-addr.arpa." nodefault
# ──────────────────────────────────────────────
# Systempfade
# ──────────────────────────────────────────────
tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
username: "unbound"
directory: "/etc/unbound"
Konfiguration testen und Dienst neu starten:
Terminalsudo unbound-checkconf
sudo systemctl restart unbound
sudo systemctl enable unbound
Den Wert bei access-control auf das eigene LAN-Subnetz setzen,
z.B. 10.0.0.0/24 oder 192.168.0.0/24. Alles andere
wird von Unbound mit refuse abgewiesen.
Pi-hole auf Unbound zeigen
Damit Pi-hole Unbound als Upstream verwendet, muss der benutzerdefinierte DNS-Server in Pi-hole eingetragen werden.
Pi-hole v6 (pihole.toml)
In Pi-hole v6 wird die Konfiguration über /etc/pihole/pihole.toml
verwaltet. Den Upstream-DNS-Abschnitt anpassen:
[dns]
# Unbound auf demselben Gerät, Port 5533
upstreams = [ "127.0.0.1#5533" ]
Pi-hole v5 (Admin-Oberfläche)
In Pi-hole v5 über die Admin-Oberfläche: Settings → DNS → Upstream DNS Servers.
Alle vorhandenen Haken entfernen, unter "Custom 1 (IPv4)" den Wert
127.0.0.1#5533 eintragen und speichern.
Sicherstellen, dass keine anderen Upstream-DNS-Server konfiguriert sind (weder Quad9 noch Cloudflare). Pi-hole soll ausschliesslich Unbound verwenden — sonst gehen Anfragen weiterhin teilweise an externe Resolver.
Pi-hole neu starten, damit die Änderung wirksam wird:
Terminalsudo systemctl restart pihole-FTL
Netzwerk-Härtung: UFW und TCP Wrappers
Pi-hole und Unbound sollten nur aus dem eigenen Netzwerk erreichbar sein. Die folgenden Regeln zeigen eine typische Konfiguration, die nur LAN-Zugriff erlaubt.
UFW Firewall
UFW (Uncomplicated Firewall) auf Debian/Ubuntu setzt iptables-Regeln ohne komplexe Syntax. Ziel: alle eingehenden Verbindungen verweigern, nur LAN explizit erlauben.
Terminal# Standardregeln
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH nur aus dem LAN (Subnetz anpassen)
sudo ufw allow from 192.168.1.0/24 to any port 22
# DNS: Pi-hole auf Port 53
sudo ufw allow from 192.168.1.0/24 to any port 53
# Unbound direkt (optional, falls Debugging benötigt)
sudo ufw allow from 192.168.1.0/24 to any port 5533
# Pi-hole Admin-Oberfläche (Port 80/443)
sudo ufw allow from 192.168.1.0/24 to any port 80,443 proto tcp
# UFW aktivieren
sudo ufw enable
sudo ufw status verbose
Port 5533 muss nicht zwingend via UFW erreichbar sein, da Pi-hole Unbound nur
über Localhost (127.0.0.1) anspricht. Die Regel ist optional und
kann für gelegentliches Debugging von anderen Geräten aus nützlich sein.
In einem hochgehärteten Setup kann sie entfallen.
TCP Wrappers (hosts.allow / hosts.deny)
TCP Wrappers ist eine weitere Zugriffskontrollschicht, die unabhängig von der Firewall arbeitet. Die Kombination aus beiden erhöht die Sicherheitstiefe.
/etc/hosts.allow# Alle Dienste: Zugriff nur aus dem LAN erlaubt
ALL: 192.168.1.0/24
/etc/hosts.deny
# PARANOID: Hosts ablehnen, deren Hostname nicht
# zur aufgelösten IP-Adresse passt (Reverse-DNS-Prüfung).
# Schützt vor Spoofing-Versuchen.
ALL: PARANOID
ALL: PARANOID lehnt Verbindungen ab, bei denen der Hostname nicht
zur IP-Adresse passt — ein Schutz gegen DNS-Spoofing. ALL: ALL
wäre strenger (blockiert alle, die nicht in hosts.allow stehen),
aber PARANOID ist in den meisten Homelab-Szenarien der sinnvollere
Kompromiss.
Verifikation
Nach der Konfiguration prüfen, ob alles wie erwartet funktioniert.
Unbound direkt testen
Auf dem Pi selbst eine Anfrage direkt an Unbound stellen:
Terminal (auf dem Pi)dig google.com @127.0.0.1 -p 5533
Die Antwort enthält status: NOERROR und aufgelöste IP-Adressen
im ANSWER SECTION. Das Flag ad (Authenticated Data)
zeigt an, dass DNSSEC-Validierung erfolgreich war.
Pi-hole als DNS testen
Von einem Gerät im Netzwerk die Pi-hole-IP als DNS verwenden:
Terminal (von anderem Gerät im LAN)# IP des Pi anpassen
dig google.com @192.168.1.x
Unbound-Status prüfen
Terminalsudo systemctl status unbound
sudo journalctl -u unbound -n 50 --no-pager
DNSSEC-Validierung testen
Diese Domain ist absichtlich mit einem fehlerhaften DNSSEC-Record signiert und sollte von einem korrekten Resolver nicht aufgelöst werden:
Terminaldig sigfail.verteiltesysteme.net @127.0.0.1 -p 5533
status: SERVFAIL — Unbound hat die fehlerhafte Signatur erkannt
und die Antwort verworfen. Das ist das korrekte Verhalten.
Wenn beide Tests bestehen — erfolgreiche Auflösung normaler Domains und
SERVFAIL für die DNSSEC-Testdomain — funktioniert Pi-hole +
Unbound mit DNSSEC-Validierung korrekt.
Bonus: WireGuard als weitere Schutzschicht
Auch mit Unbound sieht der Internet Service Provider (ISP) den DNS-Verkehr, den Unbound nach außen schickt — inklusive der angefragten Domainnamen im Klartext. DNS ist standardmäßig unverschlüsselt.
WireGuard löst auch das: Wenn der DNS-Datenverkehr über einen WireGuard-Tunnel geleitet wird, sieht der ISP nur verschlüsselten WireGuard-Traffic, nicht die DNS-Anfragen selbst. Der VPN-Endpunkt (z.B. ein VPS in einem Rechenzentrum) wird zum sichtbaren Absender der DNS-Anfragen.
Fur die meisten Heimnetzwerke und kleinen Büros bietet Unbound allein schon erheblichen Datenschutzgewinn — kein DNS-Anbieter sieht mehr den vollständigen Verkehr. WireGuard ist eine optionale weitere Schicht für Anwendungsfälle, bei denen auch die Verbindungsmetadaten gegenüber dem ISP verborgen bleiben sollen. Ein dedizierter WireGuard-Guide folgt in dieser Reihe.
Fazit
Pi-hole ohne Unbound ist wie ein Briefkasten mit Schloss, dessen Schlüssel bei der Post liegt. Erst Unbound macht das System vollständig.
Was dieser Setup konkret bringt
- Kein externer Resolver: Kein DNS-Anbieter sieht den vollständigen Netzwerkverkehr. Pi-hole filtert, Unbound löst selbst auf.
- DNSSEC-Validierung: DNS-Antworten werden kryptografisch geprüft. Manipulierte Antworten (DNS-Spoofing, Cache-Poisoning) werden erkannt und verworfen.
- QNAME-Minimierung: Jeder Nameserver entlang der Auflösung erhält nur den Teil des Namens, den er sehen muss — kein Server kennt die vollständige angefragte Domain.
- Gehärtete Netzwerkschicht: UFW und TCP Wrappers stellen sicher, dass Pi-hole und Unbound nur aus dem eigenen Netzwerk erreichbar sind.
- Günstiges Setup: Ein Raspberry Pi 4 (~70 Euro) trägt diesen Stack problemlos für kleine Netzwerke mit bis zu 50 Geräten. Keine Cloud, keine Abonnements, keine Abhängigkeiten von Drittanbietern.
- Erweiterbar: Mit WireGuard lässt sich der DNS-Verkehr verschlüsseln und die Domainnamen vor dem ISP verbergen.