Pi-hole, Unbound & Hyperlocal: Keine Werbung – Größtmögliche Unabhängigkeit

1. EinführungPi-hole, Unbound & Hyperlocal

Das Internet ist dezentral – zumindest wünsche ich mir das. Viele kleine vernetzte Einheiten und man kann sich überall etwas holen, je nachdem, was man gerade braucht. Doch wir haben zunehmend mit immer größer werdenden, zentralen Entitäten mit Vormacht- und Monopolstellung zu kämpfen. Diese kumulieren immer mehr Daten, was gelinde gesagt sehr gefährlich werden kann. Auf dem Kuketz-Blog und im Kuketz-Forum gibt es schon viele Informationen dazu, wie man sich dagegen schützen kann. Eine Möglichkeit ist, einen vertrauenswürdigen Nameserver oder DNS-Server zu verwenden. Das ist ein erster Schritt, jedoch bleibt es weiterhin ein wunder Punkt.

Alle Stellen, die wir im Internet kontaktieren (Webseiten, E-Mail, Online-Spiele etc.), bekommen immer nur einen kleineren Abriss von uns zu sehen. Der Nameserver jedoch bekommt jegliche Kontaktanfrage mit, die wir ins Internet absetzen (mal von Tor abgesehen) – vertrauenswürdiger Betreiber hin oder her. Wir wollen uns im Folgenden nun auch dieser zentralen Stelle entledigen und uns ein Stück freier und das Internet ein Stück dezentraler machen.

Gastbeitrag

Ein Gastbeitrag von Maximilian Ernst.

2. Was wir erreichen wollen

Dies ist eine Schritt-für-Schritt-Anleitung von der ersten Einrichtung eines Raspberry Pis bis zu dem Punkt, an welchem der Pi alle DNS-Anfragen aus unserem Netzwerk selbstständig für uns beantwortet, ohne dabei von einem einzelnen, nicht-autoritativen Nameserver abhängig zu sein. Dabei sollen ausgehende DNS-Anfragen an Werbe- und Tracking-Domains geblockt werden. Neben der Problemstellung ist eine grundsätzliche Erklärung gegeben und auch jeder einzelne Schritt kommentiert. Denn das Ganze soll nicht nur nachgeahmt, sondern auch verstanden werden.

Die IT-Kenntnisse sind bei jedem verschieden. Ich habe daher einfach beim Urschleim angefangen und alle Schritte erklärt. Wer schon weiter ist, kann natürlich Schritte überspringen. Über grundlegende Kenntnisse im Umgang mit dem Terminal solltest du allerdings verfügen.

2.1 Wie muss man sich das vorstellen?

Schematisch könnte man eine DNS-Anfrage z. B. an www.kuketz-blog.de so darstellen (hier ein ausführlicheres Bild auf Wikipedia):

        PC: "IP-Adresse für www.kuketz-blog.de?" → Nameserver: "Moment."
Nameserver: "IP-Adresse für .de?"                → autoritativer Root-Nameserver: "Frag autoritativen Nameserver XY!"
Nameserver: "IP-Adresse für kuketz-blog.de?"     → autoritativer Nameserver XY: "Frag Netcup-Nameserver!"
Nameserver: "IP-Adresse für www.kuketz-blog.de?" → Netcup-Nameserver: "123.45.67.89!"
Nameserver: "123.45.67.89!"                      → PC

Wenn wir fertig sind, wird das Ganze so aussehen:

PC: "IP-Adresse für www.kuketz-blog.de?" → Pi: "Moment."
Pi: "IP-Adresse für kuketz-blog.de?"     → autoritativer Nameserver XY: "Frag Netcup-Nameserver!"
Pi: "IP-Adresse für www.kuketz-blog.de?" → Netcup-Nameserver "123.45.67.89!"
Pi: "123.45.67.89!"                      → PC

Wie wir sehen, treten hier überhaupt nur noch zwei externe Stellen auf – das ist derzeit das maximal Mögliche. Und je nachdem, welche URI es ist, die wir erfragen, kontaktiert unser Pi bzw. genauer Unbound anschließend nur die wenigen passenden, untergeordneten autoritativen Nameserver direkt. Je nach Anfrage können sich die angerufenen Instanzen unterscheiden – somit sind wir nicht mehr von einem einzigen Nameserver abhängig. Zusätzlich wird der Pi nach dem Tutorial DNS-Auflösungen zwischenspeichern, das sogenannte Caching. Die zu den Adressen gehörigen IP-Adressen werden dabei eine gewisse Zeit auf dem Pi vorgehalten, da es wahrscheinlich ist, dass sie zeitnah nochmalig erfragt werden. So wird die Anzahl der Anfragen an nicht unter unserer Kontrolle stehende Instanzen noch weiter verringert und damit unsere Unabhängigkeit vergrößert.

2.2 Fragen, bevor wir loslegen?

[F] Aber beim dismail.de-Nameserver ist alles mit DNS-over-TLS (DoT) verschlüsselt und keiner sieht meine Anfragen. Hier ist alles unverschlüsselt!
[A] Auch beim dismail.de-Nameserver sind die Anfragen nur bis zu selbigem verschlüsselt. Der Server entschlüsselt die Anfragen und hat diese im Klartext vorliegen. Die zentrale Instanz mit der kompletten Kenntnis aller Anfragen bleibt also. Andere Entitäten dazwischen, bspw. der Internetprovider (ISP), sehen allerdings die DNS-Anfragen nicht mehr, soweit richtig. Allerdings kontaktieren wir direkt nach der DNS-Anfrage logischerweise direkt die entsprechende Stelle. Selbst wenn dies TLS-verschlüsselt ist, steht die Ziel-IP-Adresse im Klartext in den Kopf-Daten der Pakete. Da können wir DNS-Anfragen verschlüsseln wie wir wollen, wir Posaunen unser Ziel anschließend sowieso raus. Hier ist also kein Blumentopf zu gewinnen. Es ist derzeit auch schlicht nicht möglich, die Anfragen an die autoritativen Nameserver zu verschlüsseln.

Der zweite Punkt, den DoT sicherstellt, ist die Authentizität und Integrität der DNS-Anfragen – sind die Daten echt und unverändert? Dies wird auch bei uns durch DNSSEC sichergestellt.

[F] Ist diese Anleitung auch nach einer Einrichtung des Pi-hole laut Anleitung auf dem Kuketz-Blog noch durchführbar?
[A] Selbstverständlich. Lies bitte noch den Teil »3.1 Vorab« und steige dann direkt bei »5. Unbound« ein.

3. Inbetriebnahme Raspberry Pi

3.1 Vorab

Diese Anleitung ist mit einem Pi 3 Model B erfolgreich getestet. Ein Pi 2 sollte funktionieren. Mit einem Pi 1 klappt es definitiv nicht.
Vermutung: Ihr benötigt mindestens die Architektur ARMv7 – dieser Tabelle zu entnehmen.

Hinweis

Terminal-Befehlen ist immer ein $ vorangestellt. Ich verwende außerdem aptitude statt apt-get.

3.2 Betriebssystem installieren

Zuerst laden wir das aktuelle »Raspbian Stretch Lite« herunter. Das ist im »neuesten« Ordner das Image 2018-11-13-raspbian-stretch-lite.zip. Das Datum kann natürlich variieren, aber ich möchte ein konkretes Beispiel verwenden. Zusätzlich die sig-Datei herunterladen. Bei mir nach ~/Downloads/. Quelle für das Image:

https://downloads.raspberrypi.org/raspbian_lite/images/

In dem Verzeichnis öffnen wir einen Terminal. Nun überprüfen wir die Echtheit des Images:

$ gpg --receive-keys 0x8738CD6B956F460C
$ gpg --verify 2018-11-13-raspbian-stretch-lite.zip.sig

Das Image wird entpackt.

$ unzip 2018-11-13-raspbian-stretch-lite.zip

oder

$ 7z e 2018-11-13-raspbian-stretch-lite.zip

Jetzt müssen wir herausfinden, welche Bezeichnung die SD-Karte hat. Das Image schreiben wir anschließend auf die SD-Karte, sdX ersetzen wir entsprechend durch die Bezeichnung der SD-Karte. Bei mir ist es der Bezeichner sdd.

$ lsblk
$ sudo dd bs=4M if=2018-11-13-raspbian-stretch-lite.img of=/dev/sdd conv=fsync

Um SSH vorab auf dem Pi verfügbar zu machen, mounten wir die Boot-Partition, legen eine leere Datei »ssh« darauf an und unmounten die Partition wieder – <benutzer> entsprechend dem Nutzernamen ersetzen.

$ sudo mkdir -p /run/media/SD
$ sudo mount /dev/sdd2 /run/media/SD
$ sudo touch /run/media/SD/ssh
$ sudo umount /dev/sdd2

Karte abziehen, in den Pi stecken, Pi anstöpseln und los.

3.3 Erste Einrichtung des PIs

Im Router geben wir dem Pi per DHCP eine feste IP-Adresse. Ich wähle als Beispiel die 192.168.1.5, je nach eurem Heimnetz müsst ihr da evtl. eine andere IP-Adresse wählen. Das kann ich an dieser Stelle nicht abschließend erklären, weil das bei jedem Router verschieden ist – Es gibt einfach zu viele Möglichkeiten. Im Webinterface einer Fritz!Box bspw. ist das unter »Heimnetz → Netzwerk« zu finden, wenn ihr die Details des Geräts aufruft (Bleistift-Symbol). Dort aber nur die letzte Zahl, sprich hinter dem dritten Punkt ändern und einen Haken setzen bei immer die gleiche IPv4-Adresse zuweisen. Die hier verwendete IP-Adresse müsst ihr in der Folge dann immer entsprechend mit eurer selbst vergebenen ersetzen.

IP-Adresse

Netzwerkkabel ziehen und wieder anstecken, damit das wirksam wird. Falls das nicht klappt, Router oder Pi neustarten. Im Terminal starten wir eine SSH-Sitzung auf dem Pi. Die Abfrage bestätigen wir mit yes – Wir wollen in der SSH-known_hosts den neuen Host als bekannten aufnehmen. Das Standard-Passwort ist »raspberry«. Wir starten zunächst das Pi-eigene Einrichtungs-Skript.

$ ssh pi@192.168.1.5
$ sudo raspi-config

Dort erweitern wir die zu Beginn kleine Partition auf die Größe der kompletten SD-Karte und stellen die Zeitzone auf unsere um.

Advanced Options → Expand Filesystem
Localisation Options → Change Timezone → Europe → Berlin
Finish, Reboot

Wir aktualisieren die Paketdatenbank und bringen erst einmal die vorinstallierte Software auf den neuesten Stand. Da viel verändert wird, führen wir hinterher einen Neustart durch.

$ ssh pi@192.168.1.5
$ sudo aptitude update && sudo aptitude upgrade
$ sudo reboot

3.4 Sicherheit erhöhen

So, jetzt machen wir den Pi etwas sicherer. Erst vergeben wir ein starkes Passwort. Dann erstellen wir eine weitere Benutzerin, denn den Standard-Nutzer »pi« wollen wir nicht beibehalten. Auch diese bekommt ein starkes Passwort, aber ein anderes! Ihr könnt selbstverständlich auch einen anderen Namen vergeben. Alice müsst ihr dann im Verlauf der Anleitung stets durch euren selbstgewählten Namen ersetzen.

$ ssh pi@192.168.1.5
$ passwd
$ sudo adduser alice
$ sudo adduser alice sudo

Die SSH-Verbindung trennen wir kurz, um uns als die neu angelegte Nutzerin einzuloggen.

$ exit
$ ssh alice@192.168.1.5

Damit der sudo-Befehl ein Passwort benötigt, editieren wir die entsprechende Sudoer-Datei und ändern einen Wert.

$ sudo nano /etc/sudoers.d/010_pi-nopasswd

»NOPASSWD« ersetzen durch »PASSWD«

Mit Strg+X beenden wir nano und mit Y speichern wir die Änderungen. Wenn man stattdessen nur »pi« zu »alice« ändert, dann braucht alice kein sudo-Passwort mehr, pi jedoch schon. Aber wir wollen ein sudo-Passwort haben.

$ exit

3.5 Hardening: SSH-Key-Authentisierung

Zuerst erstellen wir uns auf dem Desktop-Rechner ein SSH-Schlüsselpaar. Den Standard-Namen behalten wir bei. Solltet ihr mehrere SSH-Schlüssel haben, könnt ihr auch gerne einen eindeutigeren Namen vergeben. Wieder vergeben wir dank Passwort-Manager ein sehr starkes Passwort.

$ ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_pi1

Den Schlüssel bringen wir auf den Pi (noch brauchen wir nur das Benutzer-Passwort). In der Datei SSH-Config geben wir an, dass wir uns auf dieser IP-Adresse per SSH nun immer mit dem Schlüssel authentisieren wollen.

$ ssh-copy-id -i ~/.ssh/id_ed25519_pi1.pub alice@192.168.1.5
$ nano ~/.ssh/config

Folgendes fügen wir ein, danach speichern und schließen.

#Pi1
Host 192.168.1.5
   IdentitiesOnly yes
   IdentityFile ~/.ssh/id_ed25519_pi1

Die Anmeldung ist nun schon mit SSH-Schlüssel und dessen Passwort möglich, ist aber noch kein wirksamer Schutz, da die Anmeldung mit Benutzer-Passwort immer noch möglich ist. Die SSH-Sitzung mit dem Pi initiieren wir nun immer folgendermaßen:

$ ssh alice@192.168.1.5
$ sudo nano /etc/ssh/sshd_config

In der Datei sshd_config suchen und ändern wir folgende Werte, um die Anmeldung dementsprechend abzusichern. Alles, was nicht zu finden ist, fügt man ganz unten manuell ein.
Achtung: Habt ihr euch vorher nicht alice genannt, müsst ihr hinter »AllowUsers« euren korrekten Namen eintragen!

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PrintMotd yes
# Allow specific users only - only alice in this case
AllowUsers alice

# Sicherheit und Allgemeines
LoginGraceTime 2m
ClientAliveInterval 600
PermitRootLogin no
StrictModes yes
AllowTcpForwarding no
AllowStreamLocalForwarding no
X11Forwarding no

Das schließen und speichern wir wieder und, damit es auch wirksam wird:

$ sudo reboot

Nun können wir uns nicht mehr als Nutzer »pi« einloggen, nur noch als »alice« und mit dem privaten Schlüssel.

Hinweis

Das ist keine vollständige Anleitung, wie man einen Pi komplett absichert. Ebenso ist Sicherheit ein Prozess, der u. A. regelmäßige Wartung erfordert (z. B. Updates!). Für einen Pi, der hinter einem Router hängt und von außen nicht zu erreichen ist, soll dies jedoch erst einmal genügen. Denn für unseren DNS-Server-Pi brauchen wir keine Ports am Router zu öffnen, da der Pi sämtliche benötigten Verbindungen nach außen selbst initiiert. Wenn wir mal theoretisch von einem idealen, sicheren Router ausgehen (sichert euren Router!), ist der Pi aus dem Internet bzw. »von außen« also nicht erreichbar. Der Pi selbst hat jedoch offene Ports, die für alle im lokalen Netzwerk erreichbar sind, dessen solltet ihr euch bewusst sein – das sind 22 (SSH), 53 (DNS-Anfragen) und 80 (Web-Interface des Pi-holes).

3.6 Anpassung des NTP-Servers zu dismail.de

Wir loggen uns wieder per SSH auf dem Pi ein. Damit die Zeit des Pis via NTP mit dismail.de synchronisiert wird, müssen wir nur eine Zeile in einer Datei ändern. Die Zeile (unten) sieht dann folgendermaßen aus:

$ ssh alice@192.168.1.5
$ sudo nano /etc/systemd/timesyncd.conf
NTP=ntp1.dismail.de ntp2.dismail.de ntp3.dismail.de

4. Pi-hole

Zunächst installieren wir Pi-hole. Das machen wir wieder in einer SSH-Sitzung auf dem Pi. Die vorzunehmenden Einstellungen folgen direkt darunter.

$ curl -sSL https://install.pi-hole.net | bash

Upstream DNS Provider: Custom
IP-Adressen davon (Digitalcourage & SecureDNS): 46.182.19.48, 146.185.167.43
Ruhig alle Listen aktiviert lassen
IPv4/IPv6? Je nach Bedarf, ich deaktiviere IPv6
Ja, die aktuellen Einstellungen passen so
Webinterface: On; Web Server: On; Log: On; Privacy Mode: 0 Show everything (Das ist schließlich nur für uns privat.)

Für das Web-Interface stellen wir ein sichereres Passwort ein.

$ pihole -a -p

Nun machen wir über das Web-Interface weiter. Wir geben im Browser folgende Adresse ein und loggen uns unter Login mit dem eben vergebenen Passwort ein.

192.168.1.5/admin

Hier nehmen wir ein paar kurze Einstellungen vor.

  • Settings → DNS → DNSSEC: Häkchen setzen.
  • Settings → Blocklists: Das kann man je nach gewünschtem Blocking variieren. Ich füge hier die Non-crossed-Liste der Blocklisten hinzu. Alle Listen markieren und in das Textfeld kopieren, anschließend ein Klick auf Save and Update.

Auf dem Dashboard sollten wir ca. 1M Domains in der Blockliste sehen. Nun können wir den Pi auch schon als lokalen Nameserver benutzen. Dazu öffnen wir die Router-Einstellungen und stellen beim DHCP(-Server) ein, dass alle Geräte den Pi bzw. dessen IP-Adresse für DNS-Anfragen genutzt werden soll (192.168.1.5). Das Vorgehen hierbei variiert wieder je nach Router, daher hier keine genauere Erklärung dazu.

In einer Fritz!Box z. B. muss man dies an zwei Stellen tun: Einmal unter »Heimnetz → Netzwerk → Netzwerkeinstellungen → IPv4-Adressen → Lokaler DNS-Server«, dort die IP-Adresse des Pi eintragen (192.168.1.5). Zudem tragen wir die IP-Adresse zweimal unter »Internet → Zugangsart → DNS-Server« ein und wählen Andere DNSv4-Server verwenden.

5. Unbound

Da wir für den letzten Punkt, die lokale Root-Zone, eine neuere Version von Unbound brauchen als die, die in den Standard-Paketquellen von Raspbian Stretch dabei ist, müssen wir einen »Trick« namens Apt-Pinning anwenden. Wir können damit Software aus dem Testing-Zweig von Debian über die offizielle Paketverwaltung beziehen.

Wir sind wieder per SSH mit dem Pi verbunden. Wir installieren das Paket dirmngr, zusätzlich müssen wir uns einen GPG-Schlüssel holen, um die Echtheit der Pakete aus dem Testing-Zweig verifizieren zu können.

$ sudo aptitude install dirmngr
$ sudo apt-key adv --keyserver pool.sks-keyservers.net --receive-keys 0x7638D0442B90D010

Jetzt editieren wir die sources.list und hängen das Folgende an. Wir geben damit der Paketverwaltung den Link zu einer Quelle für die Testing-Pakete.

$ sudo nano /etc/apt/sources.list
#Testing
deb http://ftp.de.debian.org/debian/ testing main non-free contrib

In den Einstellungen von apt sagen wir der Paketverwaltung, dass wir den Testing-Zweig zwar verfügbar haben möchten, aber die Pakete aus Stable eine höhere Priorität haben und daher nach Möglichkeit bevorzugt verwendet werden sollen.

$ sudo nano /etc/apt/preferences
Package: *
Pin: release a=stable
Pin-Priority: 600
Package: *
Pin: release a=testing
Pin-Priority: 400

Nach einem Update der Paketdatenbank installieren wir Unbound aus dem Testing-Zweig.

$ sudo aptitude update
$ sudo aptitude install unbound/testing

Raspbian macht uns nun einen Vorschlag, wie es die Abhängigkeiten auflösen soll. Der erste Vorschlag ist, Unbound einfach gar nicht zu installieren. Daher sagen wir einmalig n. Im zweiten Vorschlag sollen dann alle veralteten Abhängigkeiten aus dem Testing-Zweig aktualisiert werden. Das wollen wir: Y (zweimal). Die Dienste/Services lassen wir ungefragt neustarten während der Konfiguration. Macht euch keine Gedanke über eine evtl. auftretende rote Fehlermeldung, das klärt sich gleich.

Während der Installation wird euch diese Abfrage begegnen:

Configuration file '/etc/lighttpd/lighttpd.conf'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.

Bestätigt diese Abfrage bitte mit einem N, um die von Pi-hole installierte Lighttpd-Konfiguration zu behalten.

Manchmal hakt danach bei einem Neustart die Netzwerk-Verbindung per DHCP. Um diesem Fehler zuvorzukommen, fügen wir an die folgende Datei noch das Untenstehende an.

$ sudo nano /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

Nun stellen wir Unbound noch eine Datei zur Verfügung, die Namen und IP-Adressen der DNS-Root-Server enthält.

$ wget -O root.hints https://www.internic.net/domain/named.root
$ sudo mv root.hints /var/lib/unbound/

Wir übernehmen die von Pi-hole zur Verfügung gestellte Zusatz-Konfigurationsdatei für Unbound.

$ sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf
server:
# If no logfile is specified, syslog is used
# logfile: "/var/log/unbound/unbound.log"
verbosity: 0

port: 5353
do-ip4: yes
do-udp: yes
do-tcp: yes

# May be set to yes if you have IPv6 connectivity
do-ip6: no

# 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

# Ensure kernel buffer is large enough to not lose 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

Nachdem wir Unbound neugestartet haben – dies sollte nun fehlerfrei klappen, wollen wir das Ganze natürlich auch mal auf Funktionalität überprüfen – erst einfache DNS-Anfragen, dann DNSSEC.

$ sudo systemctl restart unbound
$ dig kuketz-blog.de @127.0.0.1 -p 5353
$ dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5353
$ dig sigok.verteiltesysteme.net @127.0.0.1 -p 5353

Die mittlere Anfrage soll »status: SERVFAIL« liefern, die letzte »status: NOERROR«. Nun loggen wir uns wieder im Pi-hole-Webinterface ein und stellen Unbound als DNS-Resolver im Feld Custom 1 unter Settings → DNS ein. Custom 2 wird gelöscht und das Häkchen entfernt.

127.0.0.1#5353

Unterstütze den Blog mit einem Dauerauftrag!

Unabhängig. Kritisch. Informativ. Praxisnah. Verständlich.

Die Arbeit von kuketz-blog.de wird vollständig durch Spenden unserer Leserschaft finanziert. Sei Teil unserer Community und unterstütze unsere Arbeit mit einer Spende.

Mitmachen ➡

5.1 Pi-hole lighttpd Workaround

Das Upgrade des Debian Buster Packages (Testing) von Unbound (v. 1.9.0-2) aktualisiert ebenfalls das Lighttpd-Webserver-Package von Version 1.4.45-1 (now, stable) -> 1.4.53-3 (testing). Aktuell ist Pi-hole mit der neuen Lighttpd-Syntax noch nicht kompatibel. Nach dem Upgrade auf die neue Version, startet der Lighttpd-Webserver nicht mehr und das Pi-hole Web-Interface ist nicht mehr erreichbar. Um das zu beheben gibt es aktuell folgenden Workaround:

$ sudo nano /etc/lighttpd/lighttpd.conf

Dort muss folgende Zeile kommentiert werden:

#include_shell "/usr/share/lighttpd/create-mime.assign.pl"

Darunter könnt ihr folgende Zeile einfach einfügen:

include_shell "/usr/share/lighttpd/create-mime.conf.pl"

Anschließend lässt sich der lighttpd-Service wieder starten bzw. neustarten:

service lighttpd start
service lighttpd restart

Da manche Nutzer über Startprobleme des Lighttpd-Webservers klagen, kann es zusätzlich notwendig sein, die folgende Zeile zu kommentieren:

#include_shell "cat external.conf 2>/dev/null"

6. Hyperlocal

Damit wir uns die erste DNS-Anfrage an die DNS-Root-Server durch Unbound sparen, stellen wir letzterem eine entsprechende Konfiguration zur Verfügung. Auch diese muss ab und zu aktualisiert werden, da selbst die DNS-Root-Server doch gelegentlichen Änderungen unterliegen – so z. B. deren IP-Adressen. Da wir nicht immer alles per Hand aktualisieren wollen, richten wir uns einfach zwei Dinge ein:

  • Einen Mechanismus, der uns automatisch über Updates informiert
  • und ein Skript, was uns das Einsetzen neuer Konfigurationsdateien erleichtert.

Für den ersten Part richten wir uns eine dynamische Message of the day (MOTD) ein. Das ist eine Meldung, die immer erscheinen soll, wenn wir uns per SSH auf dem Pi einloggen. Wir sind wieder per SSH auf dem Pi angemeldet. Die statische MOTD löschen wir, damit dann ausschließlich unsere dynamische angezeigt wird.

$ sudo rm /etc/motd

Wir bearbeiten nun eine Datei in dem Ordner, der für die MOTD-Erstellung ausgewertet wird. Dies wird uns dann stets über die Aktualität der Hyperlocal-Konfiguration informieren, wenn wir uns per SSH auf dem Pi einloggen.

$ sudo nano /etc/update-motd.d/20-info

Die Befehle in dieser Datei werden ausgeführt und die dabei entstehenden Ausgaben in die MOTD übermittelt. Wir fügen hier das Folgende ein. Ersetzt bitte NUTZERNAME mit eurem SSH-Login-Namen (z. B. alice).

#!/bin/bash

echo
echo -e "\e[1mUptime:\e[m		$(uptime)"
echo -e "\e[1mDate:\e[m		 $(date)"
echo -e "\e[1mHyperlocal conf:\e[m $(cat /home/NUTZERNAME/.unbound/update.txt)"
echo

Im Ordner für Nutzer-Skripte erstellen wir ein neues Skript, dieses wird die Update-Benachrichtigung übernehmen.

$ sudo nano /usr/local/bin/autoupdatelocalroot
#!/bin/bash

## VARIABLES ##

DIR=$HOME/.unbound

hints=/var/lib/unbound/root.hints
conf=/etc/unbound/unbound.conf.d/localroot.conf
infile=${DIR}/root.hints
outfile=${DIR}/localroot.conf
update=${DIR}/update.txt

## SCRIPT ##

# check for existence of update.txt file and .unbound directory
if [[ ! -d $HOME/.unbound ]]; then
	mkdir ${DIR}
fi
if [[ ! -e $HOME/.unbound/update.txt ]]; then
	echo "up to date" > ${update}
fi

# get the file with the root servers and save as "root.hints"
wget --timeout=30 -O ${infile} https://www.internic.net/domain/named.root

# extract name and IP addresses (A + AAAA) of root servers and nicely put them into the file for unbound
awk '\
	BEGIN\
	{
		print "auth-zone:\n\tname: \".\""
	}
	{
		if($0 ~ /[ 	]NS[ 	]/)
		{
			print "\t# "$NF
		}
		if($0 ~ /[ 	]A[ 	]/)
		{
			print "\tmaster: "$NF
		}
		if($0 ~ /[ 	]AAAA[ 	]/)
		{
			print "\tmaster: "$NF
		}
	}
	END\
	{
		print "\tfallback-enabled: yes\n\tfor-downstream: no\n\tfor-upstream: yes\n\tzonefile: \"/var/lib/unbound/root.zone\"\n"
	}\
' ${infile} > ${outfile}

#update the motd update notification if neither outfile nor diff file empty
if [[ -e ${outfile} && "$(diff -Niw ${conf} ${outfile})" != "" ]] || [[ -e ${infile} && "$(diff -Niw ${hints} ${infile})" != "" ]]; then
	echo "Update available – please run: sudo updateunboundconf" > ${update}
else
	echo "up to date" > ${update}
fi

#print update status
cat ${update}
echo

Das Ganze machen wir für alle Benutzer ausführbar. Anschließend tragen wir es in den Crontab zur regelmäßigen Ausführung ein – Falls dabei nach einem Editor gefragt wird, mit dem der Crontab bearbeitet werden soll, könnt ihr ruhig wieder nano benutzen.

$ sudo chmod 755 /usr/local/bin/autoupdatelocalroot
$ crontab -e

Wir sagen dem System, dass das Skript um 4:20 Uhr am Sonntagmorgen ausgeführt werden soll, dazu fügen wir dies an:

20 4 * * 0 /usr/local/bin/autoupdatelocalroot

Nun legen wir das zweite Skript an, dass uns die Aktualisierung der Konfigurationsdateien für Unbound erheblich erleichtern wird. Dies wird nicht automatisch ausgeführt, sondern nur nach manuellem Starten, da wir erstens nicht unkontrolliert Dateien aus dem Netz mit sudo-Rechten einsetzen wollen und zweitens, damit wir bei der Aktualisierung anwesend sind und auf Unvorhergesehenes sofort reagieren können.

$ sudo nano /usr/local/sbin/updateunboundconf
#!/bin/bash

## VARIABLES ##

DIR=/home/$(logname)/.unbound

hints=/var/lib/unbound/root.hints
conf=/etc/unbound/unbound.conf.d/localroot.conf
infile=${DIR}/root.hints
outfile=${DIR}/localroot.conf
update=${DIR}/update.txt

PLSUPDATE="Please run 'autoupdatelocalroot' first."
NOTHING="Update skipped, nothing done."

## SCRIPT ##

#update root.hints file
if [[ -e ${infile} ]] && [[ "$(diff -Niw ${hints} ${infile})" != "" ]]; then
	input=r
	echo "Install new root.hints file for Unbound (overwrites old file)?"
	echo "Yes / No / Re-Read differences?"
	while [[ "$input" =~ [rR] ]]; do
		diff -Niw ${hints} ${infile} | less
		read -e -p "	[Default = no]	(y/n/r): " input
	done

	if [[ "$input" =~ [yY] ]]; then
		mv -fv ${infile} ${hints}
		chown unbound:unbound ${hints}
		chmod 644 ${hints}
		yes1=TRUE
	else
		echo
		echo $NOTHING
		echo
	fi
else
	if [[ ! -e ${infile} ]]; then
		echo
		echo $PLSUPDATE
		echo
		exit 1
	else
		yes1=TRUE
	fi
fi

#update localroot.conf file
if [[ -e ${outfile} ]] && [[ "$(diff -Niw ${conf} ${outfile})" != "" ]]; then
	input=r
	echo "Install new localroot.conf file for Unbound (overwrites old file)?"
	echo "Yes / No / Re-Read differences?"	
	while [[ "$input" =~ [rR] ]]; do
		diff -Niw ${conf} ${outfile} | less
		read -e -p "	[Default = no]	(y/n/r): " input
	done

	if [[ "$input" =~ [yY] ]]; then
		mv -fv ${outfile} ${conf}
		yes2=TRUE
	else
		echo
		echo $NOTHING
		echo
	fi
else
	if [[ ! -e ${outfile} ]]; then
		echo
		echo $PLSUPDATE
		echo
		exit 1
	else
		yes2=TRUE
	fi
fi

#update motd update notification
if [[ "$yes1" == TRUE ]] && [[ "$yes2" == TRUE ]]; then
	echo "up to date" > ${update}
	echo
	echo "Unbound's local root config is up to date!"
	echo
else
	echo
	echo "Entire or partial Update still pending."
	echo
fi

Dieses Skript machen wir auch ausführbar, allerdings nur für Root-Berechtigte.

$ sudo chmod 744 /usr/local/sbin/updateunboundconf

Das Ganze testen wir nun einmal und legen damit auch gleich die aktuellen Konfigurationsdateien an.

$ autoupdatelocalroot

Beim zweiten Skript werden wir mit dem Tool diff arbeiten, welches Unterschiede zwischen Dateien veranschaulicht. Ein „<“ am Zeilenanfang bedeutet, dass diese Zeile bei der zweiten Datei – also der neuen Konfiguration – nicht mehr zu finden sein wird, sie wird sozusagen herausgenommen, während „>“ heißt, dass diese Zeile hinzukommt. Wenn wir mit diff die Unterschieden inspizieren, können wir mit den Pfeiltasten und Bild auf / ab navigieren und mit einem Druck auf q beenden. Zur Installation der neuen Dateien müssen wir anschließend mit y bestätigen.

$ sudo updateunboundconf

7. Fazit

Geschafft! Du hast nun die derzeit größtmögliche Unabhängigkeit und Freiheit in Bezug auf DNS.

Fassen wir noch mal zusammen, was wir erreicht haben: Unsere Geräte im Heimnetzwerk fragen nun stets unseren Raspberry Pi nach den IP-Adressen, die sich hinter Domain-Namen wie »www.kuketz-blog.de« verbergen. Der Pi filtert zunächst Anfragen an Werbe-Domains heraus. Für alle anderen Anfragen kontaktiert unser Pi nur noch die entsprechenden autoritativen Nameserver. Davon gibt es mehrere, sodass wir nicht (mehr) von einer einzigen zentralen Instanz abhängig sind. Unbound unternimmt für uns außerdem weitere Schritte, um Anfragen nach außen zu minimieren – so zum Beispiel das Zwischenspeichern von Antworten auf DNS-Anfragen.

Mitte des Jahres 2019 wird das derzeit noch im Test („testing“) befindliche Debian Buster als stabile („stable“) Version übernommen und damit Debian Stretch ablösen. Die Installation der von uns benötigten Unbound-Version wird damit erheblich einfacher, da wir es ohne Umwege mit nur einem Befehl über die Paketverwaltung installieren können. Spannend bleibt außerdem, was aus den Bestrebungen der IETF wird, die Verschlüsselung der DNS-Anfragen zu ermöglichen. Auch wenn die Entwicklung noch nicht abzuschätzen ist, werden wir diese verfolgen und entsprechende Schritte in die Tat umsetzen, sobald die Möglichkeit dazu besteht.

Bildquellen:

IP: Freepik from www.flaticon.com is licensed by CC 3.0 BY

Über den Autor | Gastbeitrag

Gastbeiträge werden von Autoren verfasst, die nicht zum festen Redaktionsteam des Kuketz-Blogs gehören. Bevor ein Gastbeitrag veröffentlicht wird, findet eine inhaltliche Abstimmung mit mir statt. Dabei übernehme ich die redaktionelle Bearbeitung des Textes, prüfe den Inhalt und bereite den Beitrag sorgfältig für die Veröffentlichung im Blog vor.

Gastbeitrag ➡

SpendeUnterstützen

Die Arbeit von kuketz-blog.de wird zu 100% durch Spenden unserer Leserinnen und Leser finanziert. Werde Teil dieser Community und unterstütze auch du unsere Arbeit mit deiner Spende.

Folge dem Blog

Wenn du über aktuelle Beiträge informiert werden möchtest, hast du verschiedene Möglichkeiten, dem Blog zu folgen:

Bleib aktuell ➡


Diskussion

77 Ergänzungen zu “Pi-hole, Unbound & Hyperlocal: Keine Werbung – Größtmögliche Unabhängigkeit”

  1. Comment Avatar Andreas sagt:

    Hallo,

    vielleicht habe ich es nur überlesen, aber sollte man beim absichern des PI’s nicht als erste Amtshandlung die SSH Schlüssel neu erstellen lassen? Falls es doch schon erwähnt wurde, einfach meinen Kommentar weg moderieren😉

    Gruß von dem sonnigen Lanzarote

    Andreas

    • Comment Avatar Max sagt:

      Nicht die allererste Amtshandlung, aber zumindest weit vorne mit dabei:

      3.5 Hardening: SSH-Key-Authentisierung

  2. Comment Avatar ava86 sagt:

    Vielen Dank für den tollen Beitrag. Ich werde pihole, unbound und homebridge auf einem Pi 2 B ohne Probleme. Ich wollte das updatelocalroot.sh, aber das klappt nicht so recht.

    Wenn ich das Skript erstmals ausführe, startet unbound nach einem reboot nicht mehr. Ich erhalte folgende Fehlerausgabe:

    pi@raspberrypi:/etc/unbound/unbound.conf.d $ unbound -d
    /etc/unbound/unbound.conf.d/localroot.conf:1: error: unknown keyword ‚auth-zone‘
    /etc/unbound/unbound.conf.d/localroot.conf:1: error: stray ‚:‘
    /etc/unbound/unbound.conf.d/localroot.conf:2: error: syntax error
    read /etc/unbound/unbound.conf failed: 3 errors in configuration file
    [1552391678] unbound[2937:0] fatal error: Could not read config file: /etc/unbound/unbound.conf

    Ist hier ein Fehler in dem Skript?

    • Comment Avatar Max sagt:

      Du brauchst von Unbound mindestens die Version 1.7, sonst klappt das nicht. Daher auch das ganze Prozedere mit dem Apt-Pinning. In Debian Stretch (stable) ist es nur die Version 1.6, diese beherrscht das Feature noch nicht.
      Welche Version von Unbound läuft denn bei dir?

  3. Comment Avatar Wolfgang sagt:

    Ich sage von ganzem Herzen DANKE für diesen absolut informativen Blog. Das Tolle hier, die Tür steht offen und im leeren Kassenhäuschen steht nur ein Schild mit der Aufschrift „Hereinspaziert“.

  4. Comment Avatar Patrick sagt:

    Hallo,

    hab selber auch einen Pi-Hole im Einsatz. Was ich bisher noch nicht hinbekommen habe ist die saubere Blockierung von https Adressen. Offenbar werden die zwar geblockt, aber der Browser erhält keine Fehlermeldung bzw wird nicht auf den PiHole internen Webserver umgeleitet und wartet extrem lange.

    Gruss

    • Comment Avatar Max sagt:

      Im Forum meinte gerade jemand, dass ab Pi-hole-Version 4.x das Blocken schnell geschieht. Dies kann ich bestätigen, die Fehlermeldung erscheint sofort, jedoch ohne Hinweis bzw. ohne Umleitung auf eine Pi-hole-Meldung. Das ist aber auch gut so, denn es ist ja httpS. :-)

  5. Comment Avatar Jannicke sagt:

    Danke für den informativen Beitrag. Bei Gelegenheit werde ich mein DOT Setup mit pihole wohl gegen die Hyperlocal Variante ersetzen.

    An welcher Stelle ist die unbound Version aus dem Testing Zweig erforderlich? Ich nutze unbound aus dem stable Repo und meine Config sieht gleich aus.

    • Comment Avatar Max sagt:

      Für den letzten Punkt, Hyperlocal, ist das neuere Unbound erforderlich. Dazu braucht es mindestens Version 1.7, stable ist erst bei 1.6.

  6. Comment Avatar Anonymous sagt:

    Hallo,

    vielen Dank für diesen interessanten Beitrag :) .
    Ich hätte eine Frage:

    Ich betreibe einen Raspberry Pi 3B+ mit DietPI und darauf läuft mein pi-hole. Kann ich einfach mit dieser Anleitung daran anknüpfen, oder muss ich von vorne anfangen?

    Liebe Grüße

  7. Comment Avatar Pierre91 sagt:

    Das ist doch die Anleitung von Tschaeggaer aus dem Forum.

  8. Comment Avatar Herbert sagt:

    Vielen, vielen Dank für die tolle Einleitung.
    Ich habe schon länger den Pi in Betrieb, aber ohne Hardening.
    Leider hänge ich schon sehr frühzeitg dort fest.
    Muss man die folgenden Zeilen alle auf einmal im Terminal eingeben:

    $ ssh-keygen -t ed25519 -a 100
    $ mv ~/.ssh/id_ed25519.pub ~/.ssh/id_ed25519_pi1.pub
    $ mv ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_pi1

    oder nacheinader?
    gebe ich sie nacheinander ein, kommt nach der 1. Zeile die Frage in wlecher Datei gespeichert werden soll. Gebe ich dann die 2. Zeile gleich ein, erfolgt die Passwortabfrage. Nach dessen 2-maliger Eingabe unter Bestätigung des Speicherns heißt es aber „No such file or directory“.
    Gebe ich alle Befehel auf einmal ein, so passen die Passwörter natürlich nicht, da ja nach der 2.Zeile bereits die Abfrage erfolgt und kein Passwort dann vorausgesetzt wird, was mit dem eingegebenen Passwort natürlich nicht zusammen passt.

    Kann mir bitte jemand sagen wie ich da weiter kommen kann?

    Vielen Dank.

    • Comment Avatar Sebastian sagt:

      Nacheinander

      beim 1. Befehl kommt bei mir:
      $ ssh-keygen -t ed25519 -a 100

      Generating public/private ed25519 key pair.
      Enter file in which to save the key (/home//.ssh/id_ed25519):

      Da dann Enter drücken oder eigenen Dateinamen angeben.

      Grüße

  9. Comment Avatar Passwort123 sagt:

    Die Hyperlocal Lösung finde ich sehr attraktiv, danke für den Anstoß!

    ABER: das Skript zur Umsetzung bereitet mir Bauchschmerzen. wget + root + automatisiert möchte ich auf einem Produktivsystem nicht einsetzen. Vielleicht lässt sich hier eine andere Möglichkeit finden. Ich denke nicht, dass sich in der root Zone so häufig etwas ändert, dass eine wöchtenliche Aktualisierung notwendig ist. Ein Zeitraum von 6 Monaten erscheint mir dazu immer noch ausreichend. Und auch 4 Mal im Jahr kann man das händisch machen.

    • Comment Avatar Mike Kuketz sagt:

      Ja, das Skirpt können wir mit Hilfe der Community noch optimieren. Ich teile deine Bedenken.

    • Comment Avatar Max sagt:

      Guter Hinweis. Das ist inzwischen auch umgesetzt bzw. der Artikel überarbeitet (insb. der Hyperlocal-Teil). Es gibt nun ein Skript, was (ohne Root-Rechte) auf Updates prüft und eins, das manuell und mit sudo gestartet werden muss und dann beim übernehmen neuer Konfigurations-Dateien assistiert.

  10. Comment Avatar Pat sagt:

    Ist es empfehlenswert, immer über die root Server auflösen zu lassen? Früher sagte man mir einmal, ich solle immer einen forwarder definieren.
    Aber dann habe ich wieder eine einzige zentrale Instanz. Richtig?

    • Comment Avatar Max sagt:

      Richtig. Die zentrale Instanz will man eigentlich nicht haben. Außerdem fragen wir die Root-Server gar nicht ab, dafür gibt es ja Hyperlocal. Es werden immer nur die autoritativen Nameserver eine Ebene darunter kontaktiert. Und weil es da pro Zuständigkeitsbereich einen anderen gibt, haben wir nicht „die eine“ Instanz.

  11. Comment Avatar Unschlüssiger sagt:

    Danke für diese Anleitung! Allerdings habe ich noch nicht ganz verstanden, worin der Unterschied zu dieser Anleitung in der Pi-hole Documentation besteht:

    https://docs.pi-hole.net/guides/unbound/

    bzw.

    https://pi-hole.net/2018/06/09/ftldns-and-unbound-combined-for-your-own-all-around-dns-solution/

    • Comment Avatar Max sagt:

      Dein erster Link war eine wichtige Quelle für den Unbound-Part. Es steht z. B. auch da, dass wir die bei Pi-hole bereitgestellte Konfigurationsdatei übernehmen.
      Man könnte es so sehen, dass die Artikel bei Pi-hole eine Teilmenge hiervon sind. Es kommt das Gleiche dabei heraus, aber diese Anleitung hier hat noch mehr Vorlauf, die Einrichtung von der lokal vorgehaltenen Root-Zone am Ende zusätzlich und bearbeitet die Sache Schritt für Schritt von Anfang bis Ende.

  12. Comment Avatar Per sagt:

    Ich liebe diese Anleitung! – Punkt – ;-)

  13. Comment Avatar user sagt:

    Vielen dank für die gut verständliche und ausführlich beschriebene Anleitung!

    Eine Frage noch:

    Kann ich in Anschluss die PiVPN-Anleitung von Mike duruhführen, um auch von unterwegs vom PiHole (und unbound) zu profitieren?

    Vielen Dank im Voraus!
    Grüße!

  14. Comment Avatar Anonymous sagt:

    Vielen Dank für die Anleitung. Nur eins ist komisch, im pi hole stehen fast bei jeder Seite anstatt der richtigen Domain der Website die man besucht, nur fritz.box?

    • Comment Avatar Max sagt:

      Sicher, dass das bei Domain steht und nicht in der Spalte eins daneben – Client? Letzteres wäre schon eher ein normales Verhalten. Falls es wirklich die Domain ist, muss wohl irgendetwas anderes versuchen, deine Fritz!Box zu kontaktieren.

      • Comment Avatar Anonymous sagt:

        Nein es ist wirklich die Domain in der fritz.box steht. Allerdings macht das lediglich ein Gerät im Netzwerk. Sehr komisch…

  15. Comment Avatar Koch sagt:

    Leider habe ich meinen „Pi-hole“ mit der Anleitung total zerschossen. Liegt wohl daran, dass ich mir Arbeit sparen wollte und im laufenden System die „Korrekturen“ einfgefügt habe. Glücklicherweise läuft der openVPN noch. Also auf ein Neues getreu dem Motto: never touch a running System.
    Trotzdem möchte ich aber konstatieren: sehr gute Anleitung!
    Viele Grüße aus Köln

  16. Comment Avatar frankenpfalz sagt:

    Danke erstmal für die neue Anleitung. Hatte es mit der alten schon mal am laufen aber nachdem ipv6 mit den meisten Routern nicht auf den pihole umgeleitet werden kann und AndroidGeräte nunmal ipv6 nutzen hab ich es wieder abgeschaltet. Gibt es da mittlerweile Fortschritte?

  17. Comment Avatar Dennis sagt:

    Hallo,

    danke für die ganz tolle Arbeit!

    Zitat: „Die mittlere Anfrage soll »status: SERVFAIL« liefern, die letzte »status: NOERROR«.“ Ist bei mir der Fall, also läuft es wie gewünscht?

    Ich kann die Pi-hole Admin Console nicht mehr aufrufen. Hat jemand das gleiche Problem und schon eine Lösung?

    • Comment Avatar Alex sagt:

      Hallo,

      ich habe exakt das gleiche Problem, leider aber auch noch keine Lösung. So wie es aussieht, ist bei der Installation von unbound der Webserver (lighttpd) zerschossen worden.
      Der Befehl „sudo systemctl status lighttpd“ liefert u.a. die Fehlermeldung „Failed to start lighttpd ..“ zurück.

      Würde mich ebenfalls über Lösungsvorschläge freuen!

      • Comment Avatar Frank sagt:

        genau an der Stelle bin ich auch hängen geblieben. Das Einloggen im Pi-hole-Webinterface funktioniert nicht mehr. Der Pi läuft und Login über ssh geht auch.

        Ein Lösung wäre klasse, zumal ich die Anleitung wirklich toll und hilfreich finde.

      • Comment Avatar Mike Kuketz sagt:

        Ich habe Ziffer 5.1 ergänzt. Dort wird ein Fix bzw. Workaround dargestellt.

        • Comment Avatar Frank sagt:

          Ich habe die entsprechende Zeile auskommentiert und lighttpd neu gestartet. Bei mir stellt sich hiernach das Pi-hole Webinterface wieder in gewohnter Weise dar und hat auch alle Icons. Ich konnte anschließend den DNS Eintrag auf den Pi-hole unter Custom1 setzen und auch die Hyperlocal Konfiguration fehlerfrei durchführen.

        • Comment Avatar duke sagt:

          „Bestätigt diese Abfrage bitte mit einem N, um die von Pi-hole installierte Lighttpd-Konfiguration zu behalten.“

          Nachdem mein Web-Interface nach der Unbound Installation (genau nach diesem Schritt) nicht
          mehr aufrufbar war, habe ich es beim zweiten Versuch mit einem Y probiert.

          Das Web-Interface funktioniert nun wieder und Unbound + Pi-Hole laufen ohne (für mich feststellbare) Probleme.

        • Comment Avatar Dennis sagt:

          Danke für den Fix!

  18. Comment Avatar klaus sagt:

    Hi,
    vielen Dank für den Beitrag! Sehr informativ!
    Verändert sich die Internetgeschwindigkeit durch Unbound?

    • Comment Avatar Max sagt:

      Ich sage es mal so: Die ersten wenigen Anfragen des Tages dauern schon etwas länger (~1 Sekunde), aber ich finde das keineswegs störend. Danach flutscht es wie am Schnürchen. Und gerade, wenn du länger auf einer Seite rumsurfst bzw. öfter hintereinander dieselbe Seite besuchst, geht es durch das Zwischenspeichern sogar einige Millisekunden schneller.
      Die reine Geschwindigkeit – z. B. bei Downloads – wird davon gar nicht beeinflusst.

  19. Comment Avatar Anonymous sagt:

    Kann man das ganze auch auf einen Router mit openwrt/dd-wrt bekommen?

  20. Comment Avatar volker sagt:

    Hi! Wollte mal ein fettes Danke hier lassen. Deine Anleitungen kann man echt 100% copy&paste übernehmen!
    Das freie Internet lebt von Leuten wie dir :)

  21. Comment Avatar Anonymous sagt:

    Hi,
    zur Frage welche Rasberrypi benötigt werden
    auf dem Rasberrypi 2B läuft es auch.
    Grüße
    Jo

  22. Comment Avatar Zuttt sagt:

    Vielen Dank! Funktioniert dfies auch mit ipfire? (Mit einem APU systerm)

  23. Comment Avatar TVB sagt:

    Danke. Funktioniert wunderbar, nach lighttpd-Fix ;)

  24. Comment Avatar Peter sagt:

    Hallo,

    guter Artikel. Ich frage mich allerdings, ob man wirklich eine Pi-Hole braucht wenn man eine IPFire hat. Nein, ich hab keine IPFire überlege aber gerade eine zu kaufen. Laut deinem Artikel (https://www.kuketz-blog.de/dns-adblocker-skript-fuer-ipfire-ipfire-teil2/) ist eine PI-Hole nicht notwendig, da die IPFire auch DNS-Blocking kann. Auf der IPFire kann man auch unbound installieren. Aber kann man auch diesen Artikel hier auf der IP-Fire umsetzen? Wenn ja, wäre doch eine Konsolidierung der Software auf einem Gerät sinnvoll?! Oder hat eine PI-Hole irgendwas was man auf der IPFire nicht umsetzen kann? DNS-Verschlüsselung zb?

    Danke für Feedback.

    Grüße
    Peter

    • Comment Avatar Anonymous sagt:

      Hallo Peter und Zutt,

      zumindest einen größeren Teil kann auch IPFire auf einer APU von Haus aus. Bei der aktuellen IPFire ist z.B. unbound schon dabei. Zusammen mit dem dns-adblocker-Skript steht man schon ganz gut da. Du hast kein Webserver-Problem („lighthttpd“). Ich schätze das man den Hyperlocal-Teil nicht braucht (wer es besser weiß bitte hier korrigieren). Auch das „Updaten der anchor-Server per root“ ist unproblematisch, denn in meiner crontab steht:

      # Update DNS trust anchor
      %daily,random * * @runas(nobody) /usr/sbin/unbound-anchor -a /var/lib/unbound/root.key -c /etc/unbound/icannbundle.pem

      „nobody“ sollte keine Probleme machen.

      Was ich auf der APU/IPFIre-Kombi noch nicht umgesetzt habe, ist indirekte Erreichbarkeit meines Netzwerks per VPN (hinter der Fritzbox, die steht bezogen auf das Internet vor der APU).
      Wer eine APU/IPFire im Einsatz hat, sollte also keinen separaten PI-Hole brauchen, wenn einem sonst die Leistung der APU ausreicht.

      zooni

  25. Comment Avatar Maxxim sagt:

    Hervorragende Anleitung. Einziger Kritikpunkt: die Skripte sind recht komplex und mir persönlich damit zu anfällig. Das vorherige, einfach gehaltene Skript sagte mir mehr zu.

    Ich musste wegen eines Fehlers noch eine Anpassung vornehmen:
    [1552775248] unbound[853:0] error: could not open root.zone.tmp853: Permission denied

    Änderung:
    zonefile: „/var/lib/unbound/root.zone“

    • Comment Avatar Elker sagt:

      Ich würde auch gerne ohne die Skripte arbeiten. Wie sieht denn die fertige Konfiguration aus, die das Skript generiert? Wieso kann man die nicht einfach direkt aufsetzen und nutzen?

    • Comment Avatar Mike Kuketz sagt:

      Wenn dir das Skript schon zu komplex ist, solltest du deine alltäglich benutzte Software aber auch äußerst kritisch beäugen.
      Hier ist, was man zum manuellen Update erldigen müsste:

      $ wget -O root.hints https://www.internic.net/domain/named.root
      (→ Datei auf Korrektheit prüfen)
      $ sudo chown unbound:unbound root.hints
      $ sudo chmod 644 root.hints
      $ sudo mv -f root.hints /var/lib/unbound/
      $ sudo awk 'BEGIN {print "auth-zone:\n\tname: \".\""} {if ($0 ~ /[ ]NS[ ]/) {print "\t# "$NF} if ($0 ~ /[ ]A[ ]/) {print "\tmaster: "$NF} if ($0 ~ /[ ]AAAA[ ]/) {print "\tmaster: "$NF}} END {print"\tfallback-enabled: yes\n\tfor-downstream: no\n\tfor-upstream: yes\n\tzonefile: \"root.zone\"\n"}' /var/lib/unbound/root.hints > /etc/unbound/unbound.conf.d/localroot.conf

      (→ /etc/unbound/unbound.conf.d/localroot.conf überprüfen, Unbound neustarten.)

      Der letzte Befehl überschreibt direkt die alte Konfigurations-Datei. Alternativ kann man natürlich auch unverbindlich ohne sudo erst mal mit Ausgabe im Home-Verzeichnis testen, wie die Konfiguration aussehen soll. Man kann sich die Datei auch per Hand erstellen, indem man sich an den Appendizes B.2 und B.4 des IETF-Entwurfs entlanghangelt und aus der „root.hints“ die entsprechende Datei – hier localroot.conf – baut. Hier der Link: https://datatracker.ietf.org/doc/draft-ietf-dnsop-7706bis/?include_text=1

      Danke für den Hinweis mit dem Fehler!

  26. Comment Avatar Herbert sagt:

    Hallo,

    erstmal vielen Dank Mike für einen weiteren tollen Artikel!

    Ich betreibe schon den Pi nach deiner früheren Anleitung und wollte ihn jetzt mit dieser neuen Anleitung aufpeppen.
    Leider hänge ich jetzt nach dem Hardening bei 3.5. fest.
    Nach dem „sudo reboot“ kann ich mich nicht mehr einloggen. Vielleicht habe ich etwas falsch verstanden. Ich gebe im Terminal „ssh meinLoginname@IPdesPis“ ein und erhalte keine Abfrage sondern „Permission denied (publickey)“.
    Habe ich da etwas falsch verstanden? Ich meine mich genau an die Anleitung gehalten zu haben, v.a. auch mit den Eingaben in die sshd_config.
    Wie kann ich da jetzt weiter kommen?

    • Comment Avatar Max sagt:

      Die zwei naheliegendsten Fehler, die ich sehe, sind:
      Erstens in deiner ~/.ssh/config auf dem Desktop-PC. Schau noch mal mit nano rein, ob die IP-Adresse mit dem des Pi übereinstimmt und ob sich hinter dem bei „IdentityFile“ angegebenen Dateinamen wirklich der korrekte Schlüssel verbirgt.
      Zweitens die Datei /etc/ssh/sshd_config auf dem Pi. Dort musst du hinter „AllowUsers“ deinen SSH-Anmeldenamen für den Pi angeben, evtl. hast du hier fälschlich „alice“ kopiert oder dich verschrieben? Du kannst dazu die SD-Karte noch mal per Kartenleser an den PC hängen, mounten und dann dort diese Datei bearbeiten.

  27. Comment Avatar Thomas sagt:

    Hallo!
    Was denkst du über eine Erweiterung von Pi-hole + Unbound mit Stubby?
    (https://dnsprivacy.org/wiki/display/DP/About+Stubby)

    Es gibt hier Informationen zu „Unbound als Cache + Stubby als TLS Forwarder“:
    https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Clients#DNSPrivacyClients-Unbound

    • Comment Avatar Anonymous sagt:

      Bei Variante 2 hättest du auf deinem System mit Pi-Hole 2 DNS-Cacher laufen (Unbound und FTL) und 1 TLS-Forwarder. Ist eventuell 1 DNS-Cacher zu viel? Die c’t hat dies so ähnlich in einem Artikel beschrieben, welcher die Installation von Stubby mit Pi-Hole erklärt.

    • Comment Avatar Max sagt:

      Davon halte ich wenig, da Stubby zwar TLS-verschlüsseln kann, aber dazu wieder an die zentrale Instanz zur Namens-Auflösung gebunden ist – und diese loszuwerden ist das erklärte Ziel des Beitrags. Ich denke, dies ist in den Teilen „1. Einführung“ und „2.2 Fragen, bevor wir loslegen?“ zur Genüge dargelegt.
      Okay, es ist natürlich „besser als nichts“, aber wenn man sich sowieso die Arbeit mit Unbound macht und dann offensichtlich auch das technische Verständnis und Wissen hat, finde ich den Weg der Names-Auflösung mittels Unbound über die autoritativen Server wesentlich eleganter und natürlich unabhängiger.

      • Comment Avatar Klaus sagt:

        Auch von mir Danke für den Artikel!!!
        Ich hatte den gleichen Gedanken wie Thomas. Ich wiederhole nur einmal, was oben schon geschrieben steht zum allgemeinen Verständnis:
        1. eine Verschlüsselung zu den autoritativen DNS servern ist aktuell noch nicht möglich und
        2. eine direkte Adressierung der autoritativen DNS-Server über Unbound ist einem verschlüsselten DNS-Server vorzuziehen.

        Soweit richtig?

  28. Comment Avatar Koch sagt:

    Hallo, zusammen!

    Auf der Such nach einen Ad-Blocker für Spotify, bin ich auf diese Doktorarbeit (Dr.jur.) bei der Uni Köln gestoßen. Es geht inhaltlich um die Wertung von Werbeblocker im Allgemeinen und Pi-hole im Besonderen (https://kups.ub.uni-koeln.de/8209/1/Dissertation_Kiersch.pdf). Die Arbeit ist aus dem Jahre 2018, also recht frisch. Man muss nicht die 200 Seiten durchlesen, sondern kann sich die interessanten Abschnitte heraussuchen. Das auch vor dem Hintergrund, dass Spotify seine Nutzungsbedingungen vor ca. 4 Wochen dahingehend geändert hat, dass der Einsatz von Ad-Blocker nicht gestattet wird, zumindest in der kostenfreien Version. Bei Google heisst es des öfteren: Sie behindern unser Geschäftsmodell! – – Alles richtig gemacht!
    Schöne Grüße

    • Comment Avatar Tobi sagt:

      Wobei die deutschen Spotify-AGBs Werbeblocker schon seit dem 15.08.2018 als nicht zulässig ansehen… die Änderung betraf nur USA.
      Aber Pi-Hole ist ja schließlich auch kein „Werbeblocker“ ;-)

  29. Comment Avatar Chris sagt:

    Erzeuge ich bei Punkt 3.5 Hardening das Schlüsselpaar unter Win10 mit PuTTYgen? Und wenn ja wie bekomm ich es aufs Pi (Kartenleser?) und wohin genau muss es (boot?)

  30. Comment Avatar Thomas sagt:

    Hallo!
    Ich habe folgende Fragen im Zusammenhang mit Anfragen an int./ext. Domains:
    Wie erreiche ich, dass alle Client-Anfragen an interne Server, die zur Subdomain local.example.com gehören, über einen internen DNS (FreeIPA) beantwortet werden?
    Wie erreiche ich, dass alle Client-Anfragen an externe Server, z.B. google.com, über den DNS von Pi-hole beantwortet werden?
    Welche Konfiguration des DNS auf Pi-hole (Bind) ist hierfür notwendig?

  31. Comment Avatar Andreas sagt:

    Hallo zusammen,
    ich habe unbound nach der anleitung installiert.

    Nach dem ich sudo updateunboundconf ausgeführt habe läst sich unbound nicht mehr starten er sagt mir immer:

    /etc/unbound/unbound.conf.d/localroot.conf:1: error: unknown keyword 'auth-zone'
    /etc/unbound/unbound.conf.d/localroot.conf:1: error: stray ':'
    /etc/unbound/unbound.conf.d/localroot.conf:2: error: syntax error
    read /etc/unbound/unbound.conf failed: 3 errors in configuration file
    [1553699868] unbound[1900:0] fatal error: Could not read config file: /etc/unbound/unbound.conf

    Wenn ich die localroot.conf lösche startet unbound ohne probleme.

    Kann mir jemand sagen wo hier das Problem ist?

    Danke

    • Comment Avatar Izzy sagt:

      Siehe weiter oben, gleich der dritte Kommentar (von ava86) – und lies dann die Antwort von Max dazu. Kurz: Deine Unbound-Version ist zu alt. Lang: siehe oben :)

  32. Comment Avatar Manuel sagt:

    Hallo,
    vielen Dank für eure Arbeit und für deinen Blog!

    Ich habe alles nach der Anleitung installiert und es funktioniert auch.
    Aber wenn ich einen DNS leak Test durchführe wird mir als DNS Server immer der Server meines ISP angezeigt.
    Ich habe zum Testen im Pihole Webinterface den DNS Server auf zb. Google gestellt und der Leak Test liefert wieder Google als DNS Server.
    Hab ich was falsch gemacht oder ist das normal?

    Danke im Vorhinein!

    • Comment Avatar Max sagt:

      Ist es wirklich ein ISP-Server oder ist es deine eigene öffentlich IP-Adresse? :-) Letzteres wäre das richtige und wünschenswerte Ergebnis. Und da deine Adresse natürlich im Adressbereich des ISPs liegt, wird dieser folgerichtig angezeigt.
      Z. B. auf dieser Seite wird dir deine IPv4-Adresse angezeigt, zum Vergleich: https://www.nsupdate.info/myip

      • Comment Avatar Anonymous sagt:

        Habs gerade überprüft und ja du hast recht es ist meine öffentliche IP-Adresse. :-)
        Danke für deine Antwort!

  33. Comment Avatar Klaus sagt:

    Danke für den Artikel!
    Ich habe mein Pihole auf einem Server als Docker-Container laufen. Funktioniert eine Kombination mit Unbound (ggfs. ebenfalls gedockert) auch mit Containern?

  34. Comment Avatar Florian sagt:

    Sehr schön noch in Kombination mit der piVPN Anleitung und dieser hier (getestet): https://github.com/rajannpatel/Pi-Hole-PiVPN-on-Google-Compute-Engine-Free-Tier-with-Full-Tunnel-and-Split-Tunnel-OpenVPN-Configs. Unterwegs mit min. Datenverbrauch Werbefrei surfen.

    • Comment Avatar Max sagt:

      Schön, dass es dabei geholfen hat.
      ABER: Wenn das Angebot erstens kostenlos und zweitens von Google ist, würde ich mir Gedanken darüber machen, wie man hier eigentlich bezahlt. Und das Ziel dieser Anleitung ist ja gerade, zentrale Entitäten, zu denen auch Google gehört, loszuwerden.

  35. Comment Avatar Klaus Rüdiger sagt:

    Am Ende des Abschnitts über den Pi – Hole steht: „Settings → DNS → DNSSEC: Häkchen setzen.“ Das sind dann die Server von Quad 9 , die Du in einem anderen Artikel als nicht vertrauenswürdig einstufst. An anderer Stellen wird hier der lokale Upstreamserver 127.0.0.1/5353 vorgeschlagen, der dann die Anfragen an die hinterlegten Rootserver weiterleitet.
    ???

    • Comment Avatar Max sagt:

      Zugegeben, das ist wohl nicht ganz eindeutig. Es müsste lauten:
      „Use DNSSEC“: Häkchen setzen.
      Quad9 ist selbstverständlich nicht gemeint – wenn überhaupt, dann hätte das schon so dagestanden. Nein, das meint die Option weiter unten. Dazu musst du ein Stück runterscrollen, dann siehst du unter der Überschrift „Advanced DNS settings“ die Option „Use DNSSEC“. Die ist gemeint!

  36. Comment Avatar Tobi sagt:

    Vielen Dank auch von mir für dieses tolle Tutorial! Eine ganz grundsätzliche Frage dazu: wie halte ich sowohl Pi-Hole als auch Unbound auf dem neusten Stand, bzw. update am besten beide Packages? Geht dies über ein spezielles Kommando wenn ich dieser Installation folge?

    Oder wäre es von Vorteil Pi-Hole und Unbound als Dockerimages auf dem Raspi laufen zu lassen, weil sich Dockerimages besser updaten lassen?

    Man liest ja in diversen Kommentaren, dass die Unbound Version veraltet war – und Unbound wird auch regelmäßigt aktualisiert von den Entwicklern.

    • Comment Avatar Max sagt:

      Das Update erfolgt dann mit

      sudo aptitude update && sudo aptitude full-upgrade

      Allerdings musst du vorsichtig sein. Möglicherweise werden durch die Testing-Pakete auch mal wieder neuere Abhängigkeiten erforderlich. Beim Update werden meiner Erfahrung nach dann gern mal Optionen angeboten, die Pakete einfach deinstallieren möchten. Pass also auf, dass du hier nichts zerstörst. Mit Glück werden solche Updates aber nicht noch mal erforderlich, bis in wenigen Monaten Buster Debian stable wird. Dann wird alles viel einfacher. :-)

      Ich habe keine Erfahrung mit Docker, sehe allerdings auch nicht, welche großartigen Vorteile das bringen würde. Gerade im Testing-Zweig wird Unbound auch noch aktualisiert. Und mit dem Upgrade auf Buster haben wir dann auch die denkbar einfachsten Updates zurück. Dann gibt es zwar keine neuen Features mehr, aber die Sicherheitspatches werden nach wie vor eingepflegt. Und solang wir die neuen Features nicht benötigen, ist das auch gut so.

  37. Comment Avatar redgun sagt:

    Und wieder mal der Kuketz-Blog :) Kaum bei Heise von Hyperlocal gelesen, schon wird hier der PiHole-Teil ergänzt. Danke dafür. Habe zwar den Pi komplett neu aufgesetzt, aber das war die Sache wert. Kleine Anmerkung für Cisco- (und event. andere) Router: Die IP-Flood-Erkennung der Firewall MUSS ausgeschaltet sein, da sonst die Unbound-Aktivitäten als „LAN-side UDP Flood“ geblockt werden. Hat mich echt Zeit gekostet.

HilfeWenn du konkrete Fragen hast oder Hilfe benötigst, sind das offizielle Forum oder der Chat geeignete Anlaufstellen, um dein Anliegen zu diskutieren. Per E-Mail beantworte ich grundsätzlich keine (Support-)Anfragen – dazu fehlt mir einfach die Zeit. Kuketz-Forum

Abschließender Hinweis

Blog-Beiträge erheben nicht den Anspruch auf ständige Aktualität und Richtigkeit wie Lexikoneinträge (z.B. Wikipedia), sondern beziehen sich wie Zeitungsartikel auf den Informationsstand zum Zeitpunkt des Redaktionsschlusses.

Kritik, Anregungen oder Korrekturvorschläge zu den Beiträgen nehme ich gerne per E-Mail entgegen.