Neuigkeiten:

Privates MODX und LINUX BLOG, User Registrierung ist deaktiviert! Fragen oder Tipps? Bitte per Matrix: @jolichter:tchncs.de

Hauptmenü

Pi-hole mit Unbound

Begonnen von Jo, 2022-05-28 | 00:39:02

« vorheriges - nächstes »

Jo

Pi-hole mit Unbound als zentraler DNS-Server mit Adblocker ohne Filternet

Update 2023-Dezember: Pi-hole mit Unbound und Manjaro
Ich lasse diesen Forum-Thread für Debian 11 (bullseye) stehen. Vieles davon kann auch auf das neue Debian 12 (bookworm) übertragen werden, jedoch müssen möglicherweise einige Anpassungen wegen systemd-Service vorgenommen werden.


Update 2023-April: FRITZ!OS mit DNSv4-Server/DNSv6-Server und Cron-Jobs

Vorwort: Der einfachste Weg einen DNS-Server als Tracking- und Werbeblocker ohne Pi-hole zu nutzen ist wahrscheinlich wie ich hier beschrieben habe. Dabei wird ein externer DNS-Resolver den ihr vertrauen müsst in der FritzBox oder eurem Smartphone eingerichtet.

Der größte Vorteil von Pi-hole ist, dass dieser auf DNS-Ebene für das gesamte Netzwerk Anfragen erst gar nicht lädt und nicht auf Programme (Apps) oder Geräten beschränkt ist. Damit blockt ihr nicht nur Werbebanner oder bösartige Webseiten im Browser, sondern auch viele andere Sachen, z.B. das Senden von Telemetriedaten, IoT-Geräten oder Smart TVs, wenn diese z.B. Nutzungsdaten an den Hersteller senden wollen.

Pi-hole ist eine freie Open Source Software mit der Funktion eines Tracking- und Werbeblockers für das ganze Heimnetzwerk. Eigentlich ist das kein Blocker, denn die Daten werden erst gar nicht geladen! Details und Installationsanleitungen findet ihr reichlich im www (Auswahl siehe unten), hier beschreibe ich meine Anpassungen auf einem Raspi und die Konfiguration in einer FritzBox.

Pi-hole mit Unbound ist schneller, sicherer und frei konfigurierbar. Die Standard Adlist von Pi-hole reicht oft schon aus und eine Whitelist oder Blacklist ist einfach zu konfigurieren, auch mit regulären Ausdrücken (RegEx), wie z.B.: \.zip$ (zip TLD ist eine ziemlich dumme Idee und wird für Phishing missbraucht) oder (^|\.)usercentrics\.eu$ Usercentrics in die Blacklist und nervige EU Cookie Meldungen per JavaScript werden von diesem Dienstanbieter nicht mehr geladen. Es gibt Firmen die solchen Anbieter dank EU dafür Geld bezahlen. Pi-hole funktioniert als DNS-Server und kann daher keine Cookie-Meldung von der gleichen Domain blockieren, dafür nutze ich weiterhin uBlock.

Am Anfang hatte mich die DoT oder DoH Verschlüsselung etwas verwirrt, warum macht Pi-hole das nicht? So wie ich das lese schaut das so aus:
ZitatDer DNS-Traffic besteht aus zwei Teilen, der erste ist zwischen dem Client (Gerät) und DNS-Resolver, der zweite ist zwischen DNS-Resolver und autoritativen Nameservern (Root-Servern, verantwortlich für bestimmte DNS-Zonen). Da die DNS Anfragen im Klartext per UDP erfolgt, selbst wenn die Website HTTPS verwendet, kann der DNS-Traffic mitgelesen oder sogar verändert werden. Immerhin wurden DNS-Protokoll-Erweiterungen wie z.B. DNSSEC, DoT und DoH eingeführt, jedoch kann DoT/DoH nur im ersten Teil genutzt werden (siehe Wiki: Sicherheitserweiterungen). Darum können externe DNS-Resolver den Transport nur zwischen dem Client und dem öffentlichen Resolver per DNS-Verschlüsselung schützen und prüfen die Daten von den autoritativen Nameservern per DNSSEC auf ihre Korrektheit (DNS Antworten werden signiert). Nur euer Internetprovider (ISP) sieht die DNS Anfragen nicht.

Seltsam, warum gibt es keine echte DNS Ende-zu-Ende-Verschlüsselung?

Eine mögliche Erklärung ist, dass DNS ursprünglich als offenes, leichtgewichtiges und schnelles Protokoll konzipiert wurde, das auf UDP basiert. Die Einführung von Ende-zu-Ende-Verschlüsselung könnte die Komplexität und die Latenz erhöhen, was die Leistungsfähigkeit des DNS-Systems beeinträchtigen könnte.

Ein weiterer Grund ist, dass autoritative DNS-Server häufig öffentlich zugänglich sind und von vielen Clients weltweit genutzt werden. Diese öffentliche Natur macht es schwierig, eine Ende-zu-Ende-Verschlüsselung zu implementieren, ohne die Skalierbarkeit, Effizienz und Offenheit des DNS-Systems zu beeinträchtigen.

Anstatt einen externen DNS-Resolver könnt ihr einen Pi-hole mit Unbound und DNSSEC nutzen, welcher die Daten auch unverschlüsselt direkt an entsprechende Root DNS-Server einmalig sendet. Das Durchlaufen des Netzwerks kann beim ersten Besuch einer Website langsamer sein, da hier rekursiv die Pfade durchlaufen werden, besonders da auch DNSSEC verwendet wird. Nachfolgende Anfragen an Domänen unter derselben TLD werden dank Cache superschnell in weniger als 0,1s abgeschlossen und wichtiger, von ausserhalb kann niemand mehr Anfragen mitlesen. Unbound übernimmt die DNSSEC-Funktion, so dass eine Aktivierung in Pi-hole nicht erforderlich ist und vermeidet dnsmasq-Fehler.



Ich habe Pi OS Lite (zu dem Zeitpunkt Debian 11 Bullseye) auf einem Raspberry mit einer SD-Karte Samsung PRO Endurance wie hier beschrieben installiert (rennt auch problemlos auf dem Gleichen Pi4 mit ioBroker und SSD). Pi-hole installieren:
curl -sSL https://install.pi-hole.net | bashdanach Unbound installieren:
sudo apt install unbound lm-sensorswie Dennis Schröder hier gut beschreibt.
(der lm-sensors ist, damit htop auch die CPU-Temperatur anzeigt)

Da der Zeitserver für DNSSEC sehr wichtig ist, nutze ich den von der FritzBox, z.B.:
sudoedit /etc/systemd/timesyncd.conf
ZitatNTP=192.168.178.1
(oder den Domainnamen: NTP=fritz.box)

Um die SD-Karte etwas zu schonen nutze ich dynamic RAMDisk (tmpfs) auch für System-Logs, diese sind dann nach einem Neustart verloren. Plane ohnehin nicht den Pi oft neu zu starten.
sudoedit /etc/fstab
ZitatPARTUUID=xxxxxxxx-xx  /boot          vfat    defaults,flush    0      2
PARTUUID=xxxxxxxx-xx  /              ext4    defaults,noatime,commit=60  0      1
# dynamic RAMDisk Pi-4GB
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=1000M,mode=1777 0 0
tmpfs /var/log tmpfs defaults,noatime,nosuid,size=500M,mode=0777 0 0

Long-term database settings (alle 60 anstatt 1 Min und 90 anstatt 365 Tage behalten), diese Zeilen hinzufügen, bzw. anpassen:
sudoedit /etc/pihole/pihole-FTL.conf
ZitatDBINTERVAL=60.0
MAXDBDAYS=90
PRIVACYLEVEL=0
(wenn gewünscht kann die Abfrageprotokollierung mit "PRIVACYLEVEL=3" deaktiviert werden)

Swap habe ich deaktiviert, 4GB reichen für Pi-hole mit Logs im Speicher problemlos, zumindest wenn sonst nichts anderes darauf rennt. Laut Htop benötigt das System nur 115 MB.

Alle 3 - 6 Monate mache ich manuell ein Update (oder nach Bedarf):
sudo apt update && sudo apt upgrade && sudo apt full-upgrade && pihole -up
sudo apt clean && sudo apt autoclean && sudo apt-get -f install && sudo apt clean && sudo apt autoremove --purge
sudo reboot

Wenn Unbound von einem Paketmanager installiert wurde, sollte dieser die Datei 'root.hints' automatisch mit der Abhängigkeit dns-root-data installieren. Die root hints werden dann automatisch vom Paketmanager aktualisiert. Überprüfen ob die Datei vorhanden ist:
ls -l /var/lib/unbound/root.hints
Wenn die Datei vorhanden ist, sollte eine Ausgabe ähnlich dieser erfolgenden:
Zitat-rw-r--r-- 1 root root 3314 18. Mär 13:48 /var/lib/unbound/root.hints

Das bedeutet, dass die 'root.hints'-Datei im Verzeichnis /var/lib/unbound/ vorhanden ist und von Unbound verwendet werden kann.

Ansonsten die 'root.hints'-Datei manuell aktualisieren:
wget https://www.internic.net/domain/named.root -qO- | sudo tee /var/lib/unbound/root.hints
Es ist wichtig, sicherzustellen, dass die Datei von einer vertrauenswürdigen Quelle heruntergeladen wird, um sicherzustellen, dass sie korrekt und unverfälscht ist. Es wird auch empfohlen, die 'root.hints'-Datei regelmäßig zu aktualisieren, um sicherzustellen, dass der DNS-Resolver auf die aktuellsten Informationen zugreifen kann. Eine monatliche Aktualisierung der 'root.hints'-Datei sollte in der Regel ausreichend sein. Wichtig ist allerdings sicherzustellen, dass bei wichtigen Änderungen an den Root-Server-IP-Adressen eine Aktualisierung unverzüglich durchgeführt wird, um sicherzustellen, dass dein DNS-Resolver immer auf dem neuesten Stand ist.

Lösung: Cron-Job einrichten und die 'root.hints'-Datei z.B. alle zwei Wochen aktualisieren:
sudo crontab -e
Füge den folgenden Eintrag am Ende der Datei hinzu (ohne sudo!):
0 0 */14 * * wget -qO /tmp/root.hints https://www.internic.net/domain/named.root && cp /var/lib/unbound/root.hints /var/lib/unbound/root.hints.bak && mv /tmp/root.hints /var/lib/unbound/root.hints && unbound-control reload >/dev/null 2>&1
Dieser Befehl wird die root.hints-Datei alle zwei Wochen um Mitternacht aktualisieren, die alte root.hints-Datei als Backup speichern und anschließend die Unbound-Konfiguration neu laden, um die aktualisierten Root-Hints zu verwenden.

Der Hauptgrund für die Verwendung der 'root'-Crontab ist der 'unbound-control reload'-Befehl, der Root-Berechtigungen erfordert. Das bedeutet, dass die 'root.hints'-Datei und die 'root.hints.bak'-Datei mit Root-Berechtigungen kopiert und verschoben werden. Dies sollte in der Regel kein Problem darstellen, solange Unbound selbst auch mit Root-Berechtigungen läuft (was in den meisten Fällen der Fall ist).

Hier ist, was dieser Befehl macht:

  • Die Datei 'named.root' wird mit 'wget' in das temporäre Verzeichnis '/tmp' heruntergeladen und als 'root.hints' gespeichert.
  • Wenn der Download erfolgreich ist (durch '&&'), wird die vorhandene '/var/lib/unbound/root.hints'-Datei als Backup-Datei in '/var/lib/unbound/root.hints.bak' gespeichert.
  • Anschließend wird die neue 'root.hints'-Datei aus dem temporären Verzeichnis /tmp in das Verzeichnis '/var/lib/unbound' verschoben und ersetzt die alte 'root.hints'-Datei.
  • Zuletzt wird die Unbound-Konfiguration neu geladen, nachdem die root.hints-Datei erfolgreich aktualisiert wurde. Dadurch wird sichergestellt, dass Unbound die neuesten Root-Hints verwendet.

Auf diese Weise wird die 'root.hints'-Datei nur aktualisiert, wenn der Download erfolgreich war, und die alte Datei wird als Backup gespeichert, um im Falle eines Problems wiederhergestellt zu werden.

Stellt sicher, dass unbound-control entsprechend konfiguriert ist, bevor ihr diesen Cron-Job ausführt! Andernfalls könnte der Befehl
sudo unbound-control reloadfehlschlagen, einfach testen, als Ausgabe sollte ein "OK" erscheinen.




DNSSEC-Validierung für eine bestimmte Domain per Terminal testen (benötigt das Paket 'dnsutils'), z.B. dnssec.works:
dig +dnssec +cd dnssec.works"+dnssec" fordert DNSSEC zur Authentifizierung von DNS-Daten an. "+cd" deaktiviert die DNSSEC-Validierung und gibt jede Antwort zurück, auch wenn sie nicht authentifiziert ist. Das Ergebnis sollte die DNS-Antwort für die Domain "dnssec.works" anzeigen, das diese erfolgreich mit DNSSEC signiert wurde (flags: ad):
Zitat...
;; flags: qr rd ra ad cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...

DNSSEC-Validierung mit Unbound testen (docs.pi-hole.net/guides/dns/unbound/#test-validation). Beachte jedoch, dass Unbound korrekt konfiguriert sein muss, um DNSSEC zu unterstützen und zu validieren:
dig fail01.dnssec.works @127.0.0.1 -p 5335
dig dnssec.works @127.0.0.1 -p 5335

Der erste Befehl testet die DNSSEC-Validierung mit Unbound, indem eine DNS-Anfrage für die Domain "fail01.dnssec.works" an den lokalen Unbound-DNS-Server gesendet wird, der auf Port 5335 lauscht. Da diese Domain absichtlich fehlerhaft signiert ist, sollte der Befehl einen Statusbericht von SERVFAIL liefern und keine IP-Adresse anzeigen.

Der zweite Befehl testet ebenfalls die DNSSEC-Validierung mit Unbound, indem eine DNS-Anfrage für die Domain "dnssec.works" an den lokalen Unbound-DNS-Server gesendet wird. Wenn Unbound richtig konfiguriert ist und der DNS-Server für die Domain DNSSEC unterstützt, sollte die DNS-Antwort signiert und gültig sein. Die Ausgabe des Befehls enthält auch DNS-Informationen für die Domain, einschließlich DNSSEC-Informationen. Wenn DNSSEC erfolgreich validiert, wird "ad" (authenticated data) in der Antwort angezeigt. Dieser Befehl sollte NOERROR und eine IP-Adresse anzeigen.


FritzBox Einstellungen
getestet mit 7390/7490 Firmware 7.29

Möglichkeit 1
Internet -> Zugangsdaten -> DNS-Server
Hier können zwei DNS-Server eingerichtet werden, z.B.:
  • Bevorzugter DNSv4-Server: 192.168.178.42 (euer Pi-hole)
  • Alternativer DNSv4-Server: 9.9.9.9 (Quad9)
Vorteil: Funktioniert mit VPN Clients und Clients im Gastnetz und als Fallback.
Leider kann es vorkommen, dass trotz Pi-hole die Anfragen über den Alternativen DNS-Server laufen. Wer das nicht will, sollte auf einem Fallback verzichten und die Gleiche IP des Pi-hole dort eintragen.
Nachteil: Im Pi-hole Log seht ihr nur die FritzBox und nicht, welche Clients welche Anfragen stellen.

Möglichkeit 2:
Heimnetz -> Netzwerk -> Netzwerkeinstellungen - IPv4-Einstellungen -> Lokaler DNS-Server: 192.168.178.42 (euer Pi-hole)
Vorteil: Clients im Log anstatt der FritzBox.
Nachteil: Damit ist leider nur ein DNS-Server möglich, also kein Fallback. Wenn der dann weg fällt, haben die Clients keinen DNS-Server mehr. VPN-Login in FritzBox ist natürlich ohne DNS-Server möglich. VPN Clients und Clients im Gastnetz fragen die FritzBox als DNS und nicht das Pi-hole.

Mozilla Firefox
DoH sollte dann im Firefox über die Verbindungs-Einstellungen deaktiviert werden (DNS über HTTPS NICHT aktivieren).



FRITZ!OS mit DNSv4-Server und DNSv6-Server
getestet mit 7490 Firmware 7.50

Das funktioniert genau wie auf docs.pi-hole.net/guides/dns/unbound beschrieben.

Beispiel pi-hole.conf mit forward-zone.
sudo nano /etc/unbound/unbound.conf.d/pi-hole.confserver:
    verbosity: 0

    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    do-ip6: yes
    prefer-ip6: yes
    root-hints: "/var/lib/unbound/root.hints"
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: no
    edns-buffer-size: 1232
    prefetch: yes
    num-threads: 1
    so-rcvbuf: 1m

    private-address: 192.178.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

    # ADD
    # maximum number of simultaneous DNS requests (default: 150)
    num-queries-per-thread: 300
    #
    # "forward-zone" directs specific domain queries to designated upstream DNS servers
    # Adjust your IP addresses!
    forward-zone:
      name: "fritz.box"
      forward-addr: 192.168.178.1@53

Diese Konfiguration unterstützt sowohl IPv4 als auch IPv6. Unbound wird IPv6 bevorzugen (prefer-ip6: yes), aber auch IPv4 verwenden, falls notwendig. Einige der anderen Optionen in der Konfigurationsdatei stellen sicher, dass Unbound sicher und effizient arbeitet. Zum Beispiel werden private Adressbereiche aus Datenschutzgründen blockiert.

Gut zu wissen: 127.0.0.1 ist derselbe Localhost wie ::1. AAAA-Datensätze funktionieren über IPv4 genauso gut wie über IPv6. Der Client kann Pi-hole nach wie vor über IPv6 befragen. Ob Pi-hole die Anfrage über IPv4 oder IPv6 weiterleitet, ist unerheblich und ein "interface: ::1" nicht notwendig.

Daher wird nur die IPv4-Adresse mit Port des Unbound-DNS-Servers (127.0.0.1#5335) in das Feld "Custom 1 (IPv4)" in den Einstellungen von Pi-hole eingetragen.

"do-ip6: yes" in unbound's Konfiguration steuert, ob unbound IPv6 für das Stellen von DNS- Anfragen an seine Upstream-Servern verwenden soll, und ob unbound über IPv6 eingehende DNS-Anfragen beantwortet.

Optional (# ADD): Wenn die Fehlermeldung "Maximum number of concurrent DNS queries reached (max: 150)" erscheint. Diese Fehlermeldung besagt, dass die maximale Anzahl gleichzeitiger DNS-Abfragen erreicht wurde. Das Standardlimit für gleichzeitige DNS-Abfragen in Unbound beträgt 150. Wenn dieses Limit erreicht ist, werden weitere Anfragen abgelehnt oder verzögert, bis einige der laufenden Anfragen abgeschlossen sind. Um dieses Problem zu beheben, kannst du die maximale Anzahl gleichzeitiger DNS-Abfragen in der Unbound-Konfigurationsdatei erhöhen, z.B. mit "num-queries-per-thread: 300".

Meine FritzBox ist so konfiguriert ist, dass "Nur DNS-Server zuweisen" im Abschnitt "DHCPv6-Server im Heimnetz" verwendet wird, und  im Pi-hole ist "Conditional Forwarding" aktiviert, mit der korrekter IPv4-Adresse der FritzBox sowie dem lokalen Domänennamen "fritz.box", dies sollte IPv6-Hostnamen in Pi-hole angezeigen. Tut es aber nicht! DSL-Router sollten IPv6-Adressen vergeben, entweder über SLAAC oder DHCPv6, abhängig von der Router-Konfiguration und den unterstützten Funktionen. Mein FritzBox-Router unterstützt in den Settings DHCPv6.

Die letzten 3 Zeilen der Unbound-Konfigurationsdatei (forward-zone) wird Unbound angewiesen, DNS-Anfragen für die Domain "fritz.box" an die IP-Adresse 192.168.178.1 auf Port 53 weiterzuleiten. Das bedeutet, dass alle DNS-Anfragen, die sich auf die Domain "fritz.box" beziehen, an den DNS-Server mit der IP-Adresse 192.168.178.1 gesendet werden.

Da Pi-hole als DNS-Filter und Unbound als DNS-Resolver in deinem Netzwerk fungieren und DNS-Anfragen von verschiedenen Geräten empfangen, ist es wichtig, die maximale Anzahl gleichzeitiger Anfragen in beiden Diensten auf denselben Wert einzustellen. Dies hilft, dass beide Dienste reibungslos zusammenarbeiten können. Um DNS-Anfragen effizient zu verarbeiten und möglicherweise die Warnung im Pi-Hole Webinterface "DNSMASQ_WARN - Warning in dnsmasq core: Maximum number of concurrent DNS queries reached (max: 150)" (siehe auch 'sudo less /var/log/pihole.log') zu verhindern, gibt es die Möglichkeit, diesen Wert zu erhöhen. Erstelle zunächst eine neue Datei, z.B.:
sudo nano /etc/dnsmasq.d/custom-dnsmasq.confDadurch wird sichergestellt, dass deine Änderungen nicht durch zukünftige Pi-hole-Updates in der Datei "01-pihole.conf" überschrieben werden. Füge die folgende Einstellung in die neu erstellte Datei ein:
Zitatdns-forward-max=300
Diese Einstellung erhöht die maximale Anzahl gleichzeitiger Anfragen auf 300.

Raspi Static IP Configuration

Dieser Befehl zeigt die IPv6-Adressen aller eth0 Netzwerkschnittstellen an. Wenn stattdessen eine andere Netzwerkschnittstelle verwendet wird, muss die entsprechende Schnittstellenbezeichnung im Befehl ersetzt werden:
ip -6 addr show dev eth0 | grep inet6 | awk '{print $2}'
Dieser Befehl zeigt die IPv4 und IPv6-Adressen aller Netzwerkschnittstellen an:
ip addr show dev eth0 | grep inet | awk '{print $2}'
Diese habe ich im Raspi als statische IP in /etc/dhcpcd.conf eingetragen:
# Example static IP configuration:
interface eth0
static ip_address=192.178.0.42/24
static ip6_address=fd00::2ae4:1fdf:ff25:114e/64
static routers=192.178.0.1
static domain_name_servers=192.178.0.1

IPv4, IPv6 lokal und IPv6 ULA Verbindungen testen, Beispiel:
ping 192.178.0.42
ping -6 fe80::2120:efbd:2138:b314%eth0
ping -6 fd00::2ae4:1fdf:ff25:114e
Bei der lokalen IPv6-Adresse muss das VLAN (Virtual LAN) mit angegeben werden.

Sollte es aus welchen Gründen auch immer nötig sein, die Konfiguration oder die IP-Adresse zu ändern, ist dies am besten über den Befehl zu machen:
pihole -r
Fritzbox

Setzt ein Häkchen bei "Diesem Netzwerkgerät immer die gleiche IPv4-Adresse zuweisen" und "Internetnutzung priorisiert" oder wenn ihr ein Zugangsprofi nutzt bei "Internetnutzung nach Zugangsprofil und priorisiert".
Fritzbox DNS-Server mit lokaler IPv6-Adresse einrichten (AVM Link).
Setzt ein Häkchen bei "ULA-Präfix manuell festlegen" und legt das so fest: fd 00 : [leer] : [leer] : [leer] /64
Aktiviere dafür die Option "DNSv6-Server auch über Router Advertisement bekanntgeben (RFC 5006)"

Hier wird der Lokale DNSv6-Server vom Raspi eingegeben, in diesem Beispiel: fe80::2120:efbd:2138:b314


Quellen: