Software

oDroid XU4 / Raspberry Pi: PiHole mit DNS-over-TLS in Docker

PiHole Logo

Seitdem Docker den Support für den Raspberry Pi und somit sämtliche ARM-Prozessoren aufgenommen hat, ist es ein leichtes Software auf unseren geliebten günstigen Single-Board-Computern zu deployen. So kam es, dass ich vor kurzem auf das DNS-over-TLS (DoT) Docker Image von qdm12 auf GitHub gestoßen bin. Ein DNS-„Proxy“, der DNS Anfragen annimmt und sie verschlüsselt bei Google (8.8.8.8), CloudFlare (1.1.1.1) oder anderen DoT-Servern abfragt. Dies ließ sich auch ratzfratz auf meinem oDroid XU4 und Raspberry Pi 3 einrichten (zwei Geräte, dass falls mal ein Gerät ausfällt, das Internet zuhause problemlos funktioniert). Kurz noch die DNS-Server der Fritzbox auf die beiden IPs der Geräte eingestellt und schon waren die DNS-Abfragen meines Heimnetzes verschlüsselt und gingen nicht mehr im Klartext durch meine Leitung. Während ich mich mit dem Thema DNS beschäftigte, bin ich dann auch noch auf PiHole (Docker Image) gestoßen. Ein DNS-Server, der DNS-Anfragen beantwortet, außer sie gehen an Werbe-Server. Somit kann man praktisch auf unterster Ebene Ad- und Tracking-Blocking bewerkstelligen, z.B. auch für Geräte wo sich keine AdBlocker installieren lassen. Beides kombiniert, PiHole mit DNS-over-TLS, ergibt, durch das Deployment auf zwei Geräten, ein ausfallsicheres, verschlüsseltes, werbefreies und trackingfreies DNS-Setup für die ganze Familie. In diesem Beitrag möchte ich einmal kurz erklären wie man sich dieses aufbaut. Dieses Tutorial richtet sowohl an mein Stammpublikum, Fans vom oDroid XU4, als auch Raspberry Pi Benutzer, da das Setup identisch ist.

 

Docker installieren

Die Installation von Docker und Docker-Compose ist kinderleicht. Öffnet eine SSH-Verbindung und gebt folgende Befehle ein:

sudo su # Als root anmelden

cd ~ # Home-Dir öffnen

curl -fsSL https://get.docker.com -o get-docker.sh # Docker Paketquellen-Import von Docker, Inc.
sh get-docker.sh # Paketquellen importieren

apt install docker-ce python3-pip # Docker und pip3 installieren

systemctl enable docker-ce # Docker beim Systemstart starten
systemctl start docker-ce # Docker jetzt starten

pip3 install docker-compose # Docker-Compose installieren

Docker-Compose ist für die Orchestrierung von mehreren Docker-Containern zuständig und vereinfacht diese stark.

 

PiHole und DoT-Proxy installieren

Haben wir Docker und Docker-Compose installiert, können wir uns auch schon an’s Eingemachte begeben. Wir werden einen PiHole und zwei DNS-over-TLS Server starten. Ich habe die DoT-Server auf verschiedene DNS-Upstream Server gerichtet, sodass einer bei Cloudflare die Anfragen stellt und der andere beim Google Public DNS. Beide haben eine Verfügbarkeit zwischen 99% und 99,99%. Solange kein DNS-Resolver eine Uptime von 100% gewährleisten kann, würde ich also jedem empfehlen immer zwei Anbieter zu nutzen. Das Docker-Image von qdm12 bietet neben beiden erwähnten auch noch quad9, quadrant und cleanbrowsing an. Ansonsten kann man sich gerne durch die entrypoint.sh wühlen und dort eigene Provider eintragen.

Wir klonen also erstmal das Git-Repository vom DoT-Server und richten diesen ein. Wenn das läuft werden wir PiHole mit in die docker-compose.yml integrieren.

apt install git

cd ~ && git clone https://github.com/qdm12/cloudflare-dns-server.git ./dns-server

cd dns-server

In der docker-compose.yml könnt ihr nun die Einstellungen anpassen. Unter anderem würde ich dazu raten BLOCK_MALICIOUS auf off zu stellen, da der mir nach meinem Geschmack zu viel wegblockt. VERBOSITY habe ich auf 0 gesetzt. Und bei provider habt ihr wie gesagt die Möglichkeit zwischen google, cloudflare, quad9, cleanbrowsing und quadrant zu wählen. Einen genaueren Einblick zu den Einstellmöglichkeiten findet man auf der README Seite des Git Repos. Anschließend kann man mit docker-compose up –build #optional -d um den Prozess in den Hintergrund zu schieben den Compose-Stack builden und starten. Wenn Änderungen an den Konfig-Files vorgenommen worden sind, würde ich immer den Stack mit –build starten. Ansonsten reicht docker-compose up -d zum hochfahren und docker-compose down  zum herunterfahren. Wie testen wir jetzt, ob der DNS-Server funktioniert? Dazu gibt es das kleine Tool dig:

apt install dig

dig blaumedia.com @127.0.0.1

der Befehl sollte dann sowas zurückgeben:

; <<>> DiG 9.11.3-1ubuntu1.3-Ubuntu <<>> blaumedia.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42751
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;blaumedia.com.			IN	A

;; ANSWER SECTION:
blaumedia.com.		86400	IN	A	159.69.38.130

;; Query time: 100 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 13 18:14:59 CET 2019
;; MSG SIZE  rcvd: 58

Ihr habt es soweit geschafft? Sehr gut! Dann machen wir aus einem DoT-Server nun zwei und fügen noch PiHole hinzu. Der Einfachheit halber zeige ich euch erstmal mein docker-compose.yml File und werde anschließend erklären, was ich da genau mache. Mein docker-compose.yml File:

version: '2'
services:
  cloudflare-dns-tls:
    build: .
    restart: always
    image: qmcgaw/cloudflare-dns-server
    container_name: cloudflare-dns-tls
    environment:
      - VERBOSITY=0
      - VERBOSITY_DETAILS=0
      - BLOCK_MALICIOUS=off
      - LISTENINGPORT=53
      - PROVIDER=cloudflare
    networks:
      dnsbridge:
        ipv4_address: 10.5.0.2
  google-dns-tls:
    build: .
    restart: always
    image: qmcgaw/cloudflare-dns-server
    container_name: google-dns-tls
    environment:
      - VERBOSITY=0
      - VERBOSITY_DETAILS=0
      - BLOCK_MALICIOUS=off
      - LISTENINGPORT=53
      - PROVIDER=google
    networks:
      dnsbridge:
        ipv4_address: 10.5.0.3
  pihole:
    image: pihole/pihole:4.2.1
    dns:
      - 127.0.0.1
      - 192.168.1.1
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
      - "443:443/tcp"
    cap_add:
      - NET_ADMIN
    networks:
      dnsbridge:
        ipv4_address: 10.5.0.4
    environment:
      ServerIP: DEVICE_IP (192.168.1.100 z.B.)
      TZ: Europe/Berlin
      DNS1: 10.5.0.2
      DNS2: 10.5.0.3
      WEBPASSWORD: PIHOLE_PASSWORD
    volumes:
      - '/etc/pihole/:/etc/pihole/'
      - '/etc/dnsmasq.d/:/etc/dnsmasq.d/'
    restart: always
networks:
  dnsbridge:
    driver: bridge
    ipam:
     config:
       - subnet: 10.5.0.0/16
         gateway: 10.5.0.1

Es sind viele Änderungen, deshalb empfehle ich euch euer docker-compose.yml einfach mit meiner zu überschreiben. Zu aller erst solltet ihr in Zeile 47 die IP eures Gerätes angeben, unter dem PiHole erreicht werden kann. Mit ip route get 1.1.1.1 | awk ‚{print $NF; exit}‘ könnt ihr schnell herausfinden, welche dies ist (Quelle: AskUbuntu.com). Anschließend unter Zeile 51 das Passwort für das Web Interface von PiHole festlegen.

Was machen wir da nun genau? Um die beiden DoT-Server für PiHole erreichbar zu machen, erstellen wir ganz unten eine Network-Bridge. Diese sorgt dafür, dass wir den einzelnen Containern feste IP Adressen zuweisen können. Docker handhabt das normalerweise so, dass die Container sich immer untereinander mit den Container-Namen erreichen können. DNS Server wie dnsmasq von PiHole kennen aber Upstream-Server mit Domain-Namen nicht, sondern möchte selbstverständlich IP Adressen. Wie sollte er diese denn die Domains auch auflösen? Also den Container fixe IPs geben, easy. Diese legen wir in Zeile 49 und 50 als Upstream-Server für PiHole fest. In Zeile 34 und 35 legen wir die DNS-Server des Containers selber fest, die z.B. beim hochfahren der Prozesse genutzt werden. An erster Stelle muss immer 127.0.0.1 stehen, an zweiter kann ein beliebiger stehen. Ich habe dort die IP meiner Fritzbox.

In Zeile 53 und 54 mounten wir noch die Konfig-Ordner von PiHole auf unserem Hostsystem, damit diese nicht bei jedem Buildvorgang gelöscht werden und persistent bleiben. Das wäre es auch schon soweit, den Rest solltet ihr kennen oder ist selbstverständlich. Mit docker-compose up –build -d können wir nun alles builden und starten.

 

PiHole Ad-Lists einfügen

Das Web Interface von PiHole erreichen wir nun mit unserem Browser, indem wir einfach die IP des Raspberry Pi/oDroids aufrufen.

PiHole Web Frontend

PiHole Web Frontend

Mit dem Link kommt ihr nun zum Interface. Links in der Navigation „Login“ auswählen und das Passwort eingeben, welches ihr soeben in der Konfig festgelegt habt. Voilà! Testet am besten nun nochmal mit dig, ob DNS Abfragen funktionieren. Läuft alles tadellos, können wir nun Listen bei PiHole einpflegen, die zum Blockieren der Werbung zuständig sind. Ich beziehe meine Ad-Lists in der Regel ausschließlich von firebog.net. Einpflegen in PiHole könnt ihr diese dann unter Settings -> Blocklists.

PiHole Blocklists hinzufügen

PiHole Blocklists hinzufügen

Da in meinem Haushalt mehr Personen als ich das Internet nutzen, sperre ich lieber weniger als zu viele DNS-Adressen. Wenn nämlich irgendwo irgendwas aufgrund des DNS-Blackholes nicht geht, ist’s nervig für alle. Das ist am Ende aber natürlich jedem selbst überlassen. Am Ende auf Save and Update klicken und schon werden die DNS Abfragen, die in den Listen enthalten sind, blockiert. Die Listen werden nachts um 00:00 Uhr automatisch aktualisiert.

 

Schluss

Ihr habt nun einen PiHole Server, der seine DNS-Anfragen verschlüsselt erhält. Wenn ihr sicher seid, dass alles funktioniert, könnt ihr nun euren PiHole-Server als DNS-Server in eurem Router angeben. Wir haben hier eine Fritzbox und die Konfiguration darin sieht so aus:

FritzBox DNS-Server festlegen

FritzBox DNS-Server festlegen

Tragt dort die interne IP Adresse eures PiHole-Geräts ein und speichert die Einstellungen. Wie ihr seht, habe ich dort zwei IPs eingetragen. An erster Stelle kommt der oDroid XU4, an zweiter mein Backup-Pi3.

Tada! Absofort laufen die DNS-Abfragen des gesamten Netzwerkes gefiltert über PiHole -> DNS-over-TLS -> Cloudflare/Google/Quad9/…

Seid ihr auf Fragen oder Probleme gestoßen? Meldet euch gerne in den Kommentaren!

Ähnliche Beiträge:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.