PiHole Teil 3: Unbound
- PiHole Teil 1: PiHole auf dem Raspberry Pi einrichten
- PiHole Teil 2: Verschlüsselung mit DNSCrypt
- PiHole Teil 3: Unbound
Im dritten Teil meiner Artikelreihe zum Thema PiHole zeige ich dir wie du die Open-Source Software Unbound nutzen kannst. Unbound beantwortet die DNS-Anfragen aller Geräte in deinem Heimnetz lokal auf dem Raspberry Pi. PiHole leitet dafür alle Anfragen intern direkt an Unbound weiter anstatt an einen externen DNS-Server im Internet. Langfristig sind die DNS-Antworten für Endgeräte dadurch schneller, da die Anfrage nicht mehr ins Internet gesendet werden muss.
Inhaltsverzeichnis
Was ist Unbound?
Unbound ist ein DNS-Server und ist damit in der Lage die DNS-Anfragen im Heimnetz von allen Endgeräten selbstständig zu beantworten. Damit müssen DNS-Anfragen nicht mehr zu den eingestellten Upstream-Servern in PiHole weitergeleitet werden, sondern werden lokal auf dem Raspberry Pi beantwortet. Zu einer Anfrage einer Domain wie creativeturtle.de erhält der Browser die IP-Adresse also nicht mehr von einem Server im Internet, sondern von Unbound auf deinem Raspberry Pi.
Damit dies möglich ist hat Unbound sogenannte Rootlisten hinterlegt. In diesen sind die Rootnameserver definiert, die vereinfacht gesagt alle IPs des Internets gespeichert haben. Die Rootnameserver sind also so etwas wie die vollständigen Adressbücher des Internets. Unbound befragt diese Rootnameserver bei einer Anfrage nach der richtigen IP und speichert diese danach im Cache ab. Bei der ersten Anfrage einer Domain, die Unbound bisher noch nicht beantwortet hat, fällt die Antwortzeit daher etwa genauso lang aus wie bei einer Anfrage an einen „normalen“ DNS-Server im Internet. Bei jeder weiteren Anfrage ist die Antwortzeit jedoch sehr viel geringer, da Unbound die zugehörige IP der Domain abgespeichert hat. Dadurch ist Unbound langfristig schneller als ein klassischer DNS-Server, da viele Anfragen nicht an einen externen Server weitergeleitet werden müssen. Der Vorteil ist mehr Privatsphäre und Sicherheit da DNS-Anfragen seltener an die Rootnameserver gestellt werden müssen. Um Manipulationen der DNS-Antworten vorzubeugen solltest du DNSSEC nutzen.
Gut zu wissen ist außerdem, dass auch die „normalen“ DNS-Server im Internet die Rootnameserver befragen, wenn sie die IP zu einer Domain selbst nicht gespeichert haben. Durch Unbound wird dieser Umweg über einen dritten DNS-Server vermieden und die Rootnameserver direkt befragt.
Damit Unbound die aktuellen Rootnameserver kennt, wird die Liste der Rootnameserver regelmäßig automatisch aktualisiert.
Voraussetzung
Diese Anleitung geht davon aus, dass du Raspbian 10 (Buster) verwendest. Damit wird Unbound Version 1.9 installiert. Ältere Raspbian bzw. Debian Versionen installieren Unbound in Version 1.6 oder niedriger. Die älteren Versionen unterstützen kein DNS-over-TLS/DNSSEC, wodurch diese Sicherheitsfeatures nicht genutzt werden können. Ich habe Unbound Version 1.6 auf Raspbian 9 nicht zum Laufen bringen können. Des Weiteren empfehle ich Raspbian 10 neu aufzusetzen und nicht von Raspbian 9 upzugraden. Dies ist zwar mit einigem Aufwand möglich, aber nicht empfehlenswert, da es häufig zu Problemen führt.
Installation von Unbound
Zunächst installieren wir die Software Unbound.
sudo apt install unbound
Danach laden wir uns die Root-Namensliste herunter und verschieben sie in den von Unbound referenzierten Ordner.
sudo wget -O root.hints https://www.internic.net/domain/named.root
sudo mv root.hints /var/lib/unbound/
Anschließend legen wir die Konfigurationsdatei pi-hole.conf neu an.
sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf
Die Datei füllen wir dann mit folgendem Inhalt. Solltest du kein IPv6 verwenden, kannst du diese Einstellung auch mit „no“ deaktivieren. Solltest du Probleme haben, kannst du das logfile in Zeile 3 aktivieren, indem du das # am Zeilenanfang entfernst.
server:
# If no logfile is specified, syslog is used
# logfile: "/var/log/unbound/unbound.log"
verbosity: 0
# Port for Usage in Pi-Hole as 127.0.0.1#5353
port: 5353
do-ip4: yes
do-udp: yes
do-tcp: yes
# May be set to yes if you have IPv6 connectivity
do-ip6: yes
# Use this only when you downloaded the list of primary root servers!
root-hints: "/var/lib/unbound/root.hints"
# Trust glue only if it is within the servers authority
harden-glue: yes
# Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS
harden-dnssec-stripped: yes
# Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
# see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details
use-caps-for-id: no
# Reduce EDNS reassembly buffer size.
# Suggested by the unbound man page to reduce fragmentation reassembly problems
edns-buffer-size: 1472
# TTL bounds for cache
cache-min-ttl: 3600
cache-max-ttl: 86400
# Perform prefetching of close to expired message cache entries
# This only applies to domains that have been frequently queried
prefetch: yes
# One thread should be sufficient, can be increased on beefy machines
num-threads: 1
# Cache Memory rrset should have double size as msg
msg-cache-size: 50m
rrset-cache-size: 100m
# Accelerate UDP with multithreading
so-reuseport: yes
# Ensure kernel buffer is large enough to not loose messages in traffic spikes
so-rcvbuf: 1m
# Ensure privacy of local IP ranges
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
Speichere und schließe die Datei mit [STRG+X], bestätige mit [Y] und dann mit [Enter].
Anschließend muss der Unbound-Service noch gestartet und aktiviert werden, sodass er auch automatisch bei einem Reboot neustartet.
sudo systemctl start unbound.service
sudo systemctl enable unbound.service
Konfiguration testen
Den Status von Unbound kannst du jetzt überprüfen.
sudo systemctl status unbound.service
Anschließend testen wir, ob die Konfiguration funktioniert.
sudo dig creativeturtle.de @127.0.0.1 -p 5353
Dabei sollte eine Ausgabe erfolgen, die anzeigt wie lange die Antwort der DNS-Anfrage gebraucht hat. Die Zeit fällt beim erstmaligem Aufruf mit Unbound etwas länger aus, da Unbound einen der hinterlegten Rootserver befragen muss. Wenn du die Anfrage jedoch erneut stellst wird ein Rückgabewert von 0 ms ausgegeben. Unbound hat die benötigte IP-Adresse abgespeichert und „weiß“ ab jetzt, welche IP zur angeforderten Domain gehört.
Nun überprüfen wir noch, ob DNSSEC auch funktioniert.
sudo dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5353
sudo dig sigok.verteiltesysteme.net @127.0.0.1 -p 5353
Eine der Anfragen liefert dabei einen Fehler zurück. Dies ist so beabsichtigt und auch richtig. Die andere Anfrage antwortet erfolgreich.
Automatische Updates
Erstelle dir ein neues Updateskript und speichere es in einem beliebigen Ordner.
sudo nano /home/pi/update_unbound_root_dns.sh
Füge folgende Zeilen ein und speichere die Datei anschließend mit [STRG+X], bestätige mit [Y] und dann mit [Enter].
#!/bin/bash
wget -O root.hints https://www.internic.net/domain/named.root &&
(
mv -fv root.hints /var/lib/unbound/
service unbound restart
)
Das Skript muss nun noch ausführbar gemacht werden.
sudo chmod +x /home/pi/update_unbound_root_dns.sh
Für automatische Updates öffnen wir die Cronjobliste.
sudo nano /etc/crontab
Anschließend legen wir einen Cronjob an, der die DNS-Rootdatei alle vier Monate aktualisiert. Dieses Intervall ist ausreichend, da die Rootlisten auf den Servern etwa zwei Mal im Jahr aktualisiert werden.
0 0 0 */4 * root /home/pi/update_unbound_root_dns.sh >/dev/null 2>&1
Unbound in PiHole angeben
Abschließend loggen wir uns in der Oberfläche von PiHole ein und tragen unter Settings > DNS die lokale IP-Adresse und den Port aus der Konfigurationsdatei von oben ein. Solltest du kein IPv6 verwenden, kannst du das Feld auch einfach leer lassen. Achte darauf, dass du alle Upstream DNS Server auf der linken Seite deaktivierst, da PiHole sonst diese verwendet.
ipv4: 127.0.0.1#5353
ipv6: ::1#5353
Der Weg einer DNS-Anfrage ist mit Unbound dann folgendermaßen. Der Router steht in Klammern, da dieser bei Variante 3 der DNS-Einrichtung im Router übersprungen wird und daher nur bei Variante 1 und 2 an der Weiterleitung beteiligt ist (siehe Teil 1 der Artikelserie).
Endgerät (PC, Smartphone etc.) > (Router) > PiHole > Unbound <--> DNS-Root-Server (Internet, bei erstmaliger Anfrage)
Vielen Dank für die wirklich gelungene Tutorial-Reihe zum Pi-Hole auf Raspberry Pi.
Das war sehr gut nachvollziehbar und hat direkt funktioniert.
Frühere Versuche, Pi-Hole aufzusetzen, haben deutlich länger gedauert und mehr Nacharbeit bedeutet.
Dennoch erklärst du alles gut, so dass ich das Gefühl hatte, verstanden zu haben, was ich hier mache.
Großes Dankeschön und PayPal-Spende gehen raus!
Viele Grüße,
Ben
Kurze Frage:
Der Cronjob mit dem Format * * * */4 * wird, wenn ich das richtig interpretiere, nicht alle 4 Monate ausgeführt sondern alle 4 Monate, jede Stunde, jede Minute?
Müsste das korrekte Format nicht so aussehen: 0 0 0 */4 *
0 statt *
Das Stimmt. Danke für den Hinweis.
Es müsste glaube 0 0 1 */4 * heißen, denn Tag 0 gibt es nicht.
Hallo
Die Wochentagzählung beginnt bei Linuxsystemen bei Sonntag=0 und endet mit Samstag=7. Daher ist 0 ein Event am Sonntag. Wenn du 1 nutzt, dann wird dein Event montags ausgelöst, was natürlich auch völlig okay ist. 🙂
Muss man nicht in der Unbound Conf den Dnscrypt server angeben?
Hier wird im Schritt 5 darauf eingegangen:
https://linoxide.com/install-dnscrypt-unbound-archlinux/
Hallo Andi
Wie ich in meiner Artikelserie erwähne nutze ich Unbound standalone und ohne DNSCrypt. Meine Artikelserie ist so gedacht, dass du entweder DNSCrypt nutzt oder eben Unbound. Meines Wissens nach war es bislang auch nicht möglich, die Anfragen an die Root-Server via Unbound mit DNSCrypt zu verschlüsseln.
Ich hätte noch eine Frage zu deinem sehr guten Tutorial:
Wie kann ich hier jetzt noch die Option für DoT aktivieren? Bzw. wie kann ich mir das vorstellen? Denn im Moment verstehe ich das Setup wie folgt:
In deinem config-file sind die Rootlisten, mit den Rootnameservern unter folgendem Pfad hinterlegt: /var/lib/unbound/root.hints. (die haben wir ja runtergeladen)
Heißt das, dass unbound nun nicht mehr bei einem DNS Server, wie den von digitale-gesellschaft.ch die IP eines Servers abfragen muss, sondern das alles lokal geschieht und man daher keine Verschlüsselung, wie DoT braucht? Das kann ich mir jedoch kaum vorstellen, weil das ja eine sehr große Datenmenge ist. Irgendwo muss unbound die IP des angefragten Servers für unseren Client erstmalig ermitteln. Und genau diesen Traffic würde ich gerne verschlüsseln.
Beste Grüße
Hallo Jannik
Unbound befragt die DNS Root-Server nach einer IP-Adresse und speichert die Antwort im Cache. So werden Anfragen nur einmal bzw. seltener ins Internet direkt geleitet. Unbound übernimmt daher die Antwort auf DNS-Anfragen lokal. Die Antwort von den Rootservern wird dabei bereits mit der gezeigten Konfiguration mit DNSSEC gesichert. Es ist meines Wissens leider bisher nicht möglich, die Anfragen mit DNS-over-TLS (DoT) abzusichern. DoT kannst du nur nutzen, wenn du eine forward-zone einrichtest und Anfragen wiederrum an öffentliche DNS-Server wie digitale-gesellschaft.ch weiterleitest. Damit hast du dann aber leider nichts gewonnen, da du dann einfach PiHole ohne Unbound nutzen könntest. Ich bevorzuge die Nutzung von Unbound trotz fehlendem DoT dennoch, da Anfragen sehr viel seltener ins Inernet gelangen und vor allem die öffentlichen DNS-Server nichts von meinem Datenverkehr mitbekommen sollten.
Hallo Philipp,
vielen Dank für die Anleitung – hat mir also Noob echt geholfen!
Jetzt möchte ich noch mehr über Linux lernen…
Grüße
Christoph
Danke für die klasse Anleitung. 🙂
Bezüglich Unbound habe ich eine Frage zu dem Port.
Hier wird Port 5353 genannt und in der Pihole Hilfe steht 5335.
https://docs.pi-hole.net/guides/unbound/
Wie ist es denn nun richtig?
Mit freundlichen Grüßen Matthias
Hallo Matthias
Vielen Dank, ich gebe mir Mühe :).
Es gibt hier, denke ich, keinen „richtigen“ Port. Du kannst sowohl 5353 als auch 5335 benutzen. Oder auch einen anderen Port deiner Wahl. Du musst dabei nur sicherstellen, dass der Port noch frei ist und von keinem anderen Dienst benutzt wird. Auf Wikipedia gibt es eine Liste von Standardports. Diese kannst du z. B. nutzen, um Doppelbelegungen auszuschließen. Wenn du in der Konfigurationsdatei den Port definiert hast, musst du anschließend nur sicherstellen, dass du in PiHole den gleichen Port beim Verweis auf Unbound benutzt. Sonst funktioniert die Kommunikation nicht.
Ich hoffe, das hilft dir weiter.
Beste Grüße