Position: Home > Computer Know-How / Gewusst Wie > DNS-Server als Werbe- und Trackingfilter mit Raspberry Pi und Pi-Hole® und Unbound

DNS-Server als Werbe- und Trackingfilter mit Raspberry Pi und Pi-Hole® und Unbound

Obwohl es diesen Mini-Computer schon seit geraumer Zeit gibt, bin ich erst vor kurzem auf ihn aufmerksam geworden und bin über die Einsatzmöglichkeiten erstaunt.

Ich habe aktuell zwei "Projekte", einen "MP3-Server" für die Stereoanlage sowie einen eigenen lokalen DNS-Server. Hier geht es um den DNS-Server, primär als Filter gegen Werbung und Tracking im internen Netzwerk. Grundlage ist das Projekt "Pi-Hole®". Es gibt auch eine Dokumentation dazu.

Mein Heimnetzwerk läuft unter 192.168.178.x. Der Router, eine FritzBox 7560 als Standard-Gateway, auch als Zeitserver und als (weiterer) DNS-Server ist die 192.168.178.1.

Ich verwende hier einen Raspberry Pi 3B+ in dem originalen weiß/himbeerfarbenen Gehäuse und eine Micro-SD-Karte Sandisk Ultra 32GB (SDHC, UHS-1, Class 10) sowie das originale Raspberry-Pi-Netzteil in Weiß. Das ist eine ungefähre Investition von 65 Euro (Stand 01/2019).

 

Raspberry Pi im schicken, originalen himbeer-weißen Gehäuse, 89 x 71 x 26 mm

 

Vorbereitungen

  • Raspbian Stretch Lite Image downloaden
  • die heruntergeladene .zip-Datei entpacken und daraus eine .img-Datei erhalten
  • Die Micro-SD-Karte ggf. mit einem Adapter in PC bzw. das Lesegerät stecken
  • Das entpackte Image muss anschließend auf die SD-Karte geschrieben werden, damit daraus ein bootfähiger Datenträger wird. Dafür kann man unter Windows z.B. die Software balenaEtcher verwenden (Empfehlungen von Raspberry Pi für Windows).
  • Die SD-Karte in den Pi stecken und den Pi an die Stromversorgung anschließen
  • einmalig TV/Monitor (via HDMI) und Tastatur (via USB) an den Pi anschließen aufgrund des im Originalzustands in Raspbian Stretch (aus Sicherheitsgründen) deaktivierten SSH-Zugangs
  • Den Pi als zukünftigen DNS-Server und damit ganz wichtigen Heimnetzwerk-Bestandteil mit einem Netzwerkkabel an den Router anschließen, nicht via WLAN!
  • Einloggen mit user:pi / password:raspberry (Achtung: engl. Tastatur, d.h. y und z sind vertauscht...)
  • In der Shell aufrufen: sudo raspi-config
  • Dort im Menü unter "Interfacing Options" nun die SSH aktivieren
  • Neu starten mit sudo shutdown -r now
  • nun von einem Client aus per SSH auf den Pi zugreifen (unter Windows mit dem separaten kostenfreien Programm Putty oder unter Windows 10 in der Windows Power Shell) und wieder einloggen (Login siehe oben).
  • in der Shell erneut aufrufen: sudo raspi-config
  • Unter "Advanced Options" das Filesystem expandieren, d.h. von der Datenmenge des geschriebenen Image (siehe oben) auf die maximal verfügbare Größe der SD-Karte.
  • Neu starten
  • System aktualisieren
    • sudo apt-get update
    • sudo apt-get upgrade
    • sudo apt-get dist-upgrade

  • Die Datei /boot/config.txt ändern mit sudo nano /boot/config.txt
  • in /boot/config.txt einfügen zum Deaktivieren von WLAN und Bluetooth, außerdem Untertakten zum Strom sparen und Wärme reduzieren:

    dtoverlay=pi3-disable-wifi
    dtoverlay=pi3-disable-bt
    arm_freq_min=500
    sdram_freq_min=200
    gpu_freq_min=100
    temp_limit=75
    never_over_voltage=1

  • Zeitserver definieren mit folgenden Einträgen in: sudo nano /etc/systemd/timesyncd.conf

    NTP=192.168.178.1
    FallbackNTP=0.de.pool.ntp.org 1.de.pool.ntp.org

  • Danach die folgenden Befehle ausführen, damit der NTP-Service aktiviert und aktualisiert wird:
    • sudo systemctl restart systemd-timesyncd.service
    • sudo systemctl status systemd-timesyncd.service
    • sudo systemctl enable systemd-timesyncd
    • sudo systemctl start systemd-timesyncd
    • sudo timedatectl set-ntp 1
    • timedatectl

  • Weitere Aktualisierungen und Einstellungen des Systems durchführen:
    • sudo apt-get install ca-certificates
    • sudo apt-get install rpi-update
    • sudo rpi-update
    • sudo shutdown -r now
    • sudo apt-get autoremove
    • sudo apt-get autoclean

 

Installation und Einrichtung

  • Nun die Installation des Pi-Hole starten, dabei wird ein umfangreiches Installationsmenu durchlaufen (auch in der SSH):

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

  • Dort einstellen (man kann dieses Installationsmenü per SSH später neu aufrufen mit pihole -r):
    • Upstream DNS Provider Google (kann man später auch noch im Webinterface ändern)
    • Protokolle: IPV4, kein IPV6
    • Statische IP-Adresse: Vorschlag 192.168.178.2/24 und Gateway 192.168.178.1 annehmen
    • Admin-Interface installieren: Ja
    • Webserver lighttpd installieren (für das Admin-Interface): Ja
    • Log: Ja
    • Privacy Mode: Alles anzeigen

  • Um das Schreiben der Logs auf die SD-Karte und damit deren Belastung etwas zu reduzieren, verlängert man die Frequenz des Log-Schreibens von 1 (Standard) auf 60 Minuten mit
    sudo nano /etc/pihole/pihole-FTL.conf
    • dort ergänzen: DBINTERVAL=60

  • Das Admin-Interface im Browser auf einem der Clients aufrufen mit: http://pi.hole/admin oder mit http://192.168.178.2/admin mit dem Passwort wie vom Pi-Hole generiert.
  • Ergänzende Listen für Domains, die man unter Settings / Blocklists eintragen kann: firebog.net.
  • Unter Settings / DNS kann man die DNS-Server im Internet festlegen, an die DNS-Anfragen, die nicht geblockt werden, weitergeleitet werden sollen. Dabei kann man unter vorkonfigurierten Services auswählen oder auch (zwei) andere Server eintragen. Im Hinblick auf Datenschutz, Zensur und andere Faktoren habe ich ausgewählt:
  • Etwas weiter unten auf dieser Einstellungseite sollte man auch auf jeden Fall DNSSEC aktivieren.
  • Pi-Hole lässt sich auf neuere Versionen aktualisieren mit dem Shell-Kommando pihole -up (Neustart des Servers nötig!).

 

Mit der bis hierhin beschriebenen Konfiguration hat man einen hervorragend funktionierenden Werbefilter, der zwischen 10% und 50% Traffic schon vor den Clients im Heimnetz filtert. Wenn man noch einen Schritt weitergehen möchte, kann man (ebenfalls auf demselben Raspberry Pi) einen eigenen DNS-Server aufsetzen, den Pi-Hole zuerst anfragt und der erst wenn er keine Antwort kennt, externe DNS-Server abfragt. Dies erhöht die Sicherheit noch einmal einen Schritt, obwohl dadurch (vor allem anfangs) die Netzwerkabfragen etwas verlangsamt. Dieser weitere Schritt wird auch in einer speziellen Pi-Hole-Dokumentation auf Basis des DNS-Servers Unbound separat erklärt.

Hier ebenfalls Schritt für Schritt:

 

Installation und Einrichtung von Unbound (der einfache Weg..., Unbound 1.6.0)

  • Installation von Unbound starten mit sudo apt install unbound
  • Aktuelle Datei "root.hints" (Liste der DNS Root Server, die die Domain "." bereitstellen. Die Liste wird ca. alle 6 Monate aktualisiert und die Datei ändert sich dabei in unregelmäßigen Abständen.) downloaden und installieren mit:
    • wget -O root.hints https://www.internic.net/domain/named.root
    • sudo mv root.hints /var/lib/unbound/

  • Die Datei /etc/unbound/unbound.conf.d/pi-hole.conf neu anlegen mit sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf und dort reinkopieren:

    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: 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

    # 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

    access-control: 192.168.0.0/16 allow

    forward-zone:
    name: "."
    forward-addr: 1.1.1.1@53#one.one.one.one
    forward-addr: 1.0.0.1@53#one.one.one.one
    forward-addr: 84.200.69.80@53#resolver1.dns.watch
    forward-addr: 84.200.70.40@53#resolver2.dns.watch
    forward-addr: 46.182.19.48@53#dns2.digitalcourage.de
    forward-addr: 9.9.9.9@53#dns.quad9.net
    forward-addr: 8.8.8.8@53#dns.google


  • Danach die Datei abspeichern
  • Nun Unbound starten und "aktivieren", sodass er auch bei einem Neustart des Raspberry Pi automatisch mit startet (den Service neu starten kann man mit
    sudo systemctl restart unbound.service):
    • Starten mit: sudo systemctl start unbound.service
    • "Aktivieren" mit: sudo systemctl enable unbound.service

  • Unbound-Status abfragen mit sudo systemctl status unbound.service
  • Nun Unbound einmal testen mit z.B. dig pi-hole.net @127.0.0.1 -p 5353
  • Als letztes muss man Unbound noch in Pi-Hole als (einzigen) DNS-Server eintragen unter "Custom 1 (IPV4)" als "127.0.0.1#5353"

Nun müsste alles laufen wie zuvor, nur dass (seit Aktivierung des Unbound) das erste Mal aufgerufene Seiten etwas länger benötigen, bis sie geladen werden. Dies ist ein gutes Zeichen dafür, dass Unbound arbeitet!

 

Installation und Einrichtung von Unbound (der schwierige Weg..., Unbound 1.9.0)

Auf dem "einfachen Weg" haben wir die Standardversion von Unbound installiert, für die es ein vorgefertigtes Installationspaket gibt. Leider wird damit nur Version 1.6.0 installiert, die keine Verbindung mittels DNS over TLS zu externen DNS-Servern über Port 853 herstellen kann.

Links für den schwierigen Weg:

 

Ich habe sehr lange suchen und probieren müssen, um es zu schaffen, auf dem Raspberry Pi "from scratch" die allerneueste Unbound-Version 1.9.0 (vom 5.2.2019) installieren und aktivieren zu können:

  • evtl. die zuvor installierte Version von Unbound deinstallieren mit
    sudo apt-get remove unbound unbound-anchor libunbound2 libprotobuf-c1 libfstrm0

  • Installation benötigter zusätzlicher Pakete mit
    sudo apt-get install make gcc libssl libssl-dev libevent-dev libexpat1-dev libldns-dev

  • einen User und eine Gruppe "unbound" anlegen (ich bin nicht zu 100% sicher, ob das wirklich nötig ist...) mit
    sudo groupadd -g 88 unbound
    sudo useradd -c "Unbound DNS resolver" -d /var/lib/unbound -u 88 -g unbound -s /bin/false unbound


  • Download der Quellen, Entpacken mit:
    sudo wget https://nlnetlabs.nl/downloads/unbound/unbound-1.9.0.tar.gz
    sudo tar xvfz unbound-1.9.0.tar.gz
    cd unbound-1.9.0

  • Compilierung und Installation mit:
    sudo ./configure --prefix=/usr --sysconfdir=/etc --disable-static --with-pidfile=/run/unbound.pid --with-conf-file=/etc/unbound/unbound.conf --with-libevent
    sudo make
    sudo make install
    sudo mv -v /usr/sbin/unbound-host /usr/bin/

  • Die evtl. fehlende und für den Betrieb von Unbound wichtige Datei /etc/unbound/root.key erzeugen mit:
    sudo unbound-anchor

  • Bootscript downloaden, compilieren und installieren, damit Unbound auch nach einem Neustart automatisch startet, mit:
    sudo wget http://anduin.linuxfromscratch.org/BLFS/blfs-bootscripts/blfs-bootscripts-20180105.tar.xz
    sudo tar xf blfs-bootscripts-20180105.tar.xz
    cd blfs-bootscripts-20180105
    make install-unbound


  • Aktuelle Datei "root.hints" (Liste der DNS Root Server, die die Domain "." bereitstellen. Die Liste wird ca. alle 6 Monate aktualisiert und die Datei ändert sich dabei in unregelmäßigen Abständen.) downloaden und installieren mit:
    • wget -O root.hints https://www.internic.net/domain/named.root
    • sudo mv root.hints /var/lib/unbound/

  • Die Datei /etc/unbound/unbound.conf.d/pi-hole.conf neu anlegen mit sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf und dort reinkopieren:

    server:
    # If no logfile is specified, syslog is used
    # logfile: "/var/log/unbound/unbound.log"
    verbosity: 0

    username: ""
    chroot: ""

    # 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: no

    # Use this only when you downloaded the list of primary root servers!
    root-hints: "/var/lib/unbound/root.hints"
    tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"

    # 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

    access-control: 192.168.0.0/16 allow

    forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#one.one.one.one
    forward-addr: 1.0.0.1@853#one.one.one.one
    forward-addr: 84.200.69.80#resolver1.dns.watch
    forward-addr: 84.200.70.40#resolver2.dns.watch
    forward-addr: 46.182.19.48@853#dns2.digitalcourage.de
    forward-addr: 9.9.9.9@853#dns.quad9.net
    forward-addr: 8.8.8.8@853#dns.google


  • Danach die Datei abspeichern
  • Nun Unbound starten und "aktivieren", sodass er auch bei einem Neustart des Raspberry Pi automatisch mit startet (den Service neu starten kann man mit
    sudo systemctl restart unbound.service):
    • Starten mit: sudo unbound oder auch mit sudo systemctl start unbound.service
    • "Aktivieren" mit: sudo systemctl enable unbound.service

  • Nun Unbound einmal testen mit z.B. dig pi-hole.net @127.0.0.1 -p 5353
  • Unbound-Status abfragen mit sudo systemctl status unbound.service
  • Als letztes muss man Unbound noch in Pi-Hole als (einzigen) DNS-Server eintragen unter "Custom 1 (IPV4)" als "127.0.0.1#5353"

 

Nun müsste alles laufen wie zuvor, nur dass (seit Aktivierung des Unbound) das erste Mal aufgerufene Seiten etwas länger benötigen, bis sie geladen werden. Dies ist ein gutes Zeichen dafür, dass Unbound arbeitet!

 

Im Router (hier FritzBox 7560, FritzOS 7.0.2) einstellen

Unter Heimnetz / Netzwerkeinstellungen / IPV4-Adressen (etwas weiter unten) in den DHCP-Adressen die Adresse des Pi-Hole (hier 192.168.178.2) als lokaler DNS-Server eintragen. Damit verteilt das DHCP den lokalen DNS-Server automatisch mit im Netz und man muss nichts an den Clients einstellen!