16. September 2026

Pi-hole + dnscrypt-proxy: Sicheres DNS mit Docker

Pi-hole mit dnscrypt-proxy in Docker für Werbe- und Tracking-Blockierung sowie verschlüsselte DNS-Anfragen über Quad9.

Pi-hole ist eine der bekanntesten Lösungen, um Werbung, Tracking und unerwünschte Domains bereits auf DNS-Ebene aus dem eigenen Netzwerk herauszufiltern. In Kombination mit dnscrypt-proxy lässt sich das Ganze noch erweitern: DNS-Anfragen werden zunächst von Pi-hole gefiltert und anschließend über einen verschlüsselten DNS-Upstream weitergeleitet.

In diesem Beitrag zeige ich meinen Docker-Stack, der Pi-hole und dnscrypt-proxy kombiniert. Neben festen IPv4- und IPv6-Adressen bringt der Stack vorkonfigurierte Blocklisten, persistente Daten und eine optionale Integration in Traefik mit.

Das vollständige Projekt befindet sich auf GitHub:

https://github.com/happylippo/pihole-stack

Was macht der Stack?

Der grundlegende Aufbau ist relativ einfach:

Client
  │
  │ DNS :53
  ▼
Pi-hole
172.18.3.2
  │
  │ DNS :5053
  ▼
dnscrypt-proxy
172.18.3.3
  │
  │ verschlüsselte DNS-Anfrage
  ▼
Quad9
  │
  ▼
Internet

Pi-hole ist dabei der DNS-Server für die Geräte im lokalen Netzwerk.

Anfragen werden zunächst gegen die in Pi-hole hinterlegten Blocklisten geprüft. Erlaubte DNS-Anfragen gehen anschließend nicht direkt an einen gewöhnlichen DNS-Server, sondern an den ebenfalls im Stack laufenden dnscrypt-proxy.

Verwendete Docker-Images

Der Stack verwendet bewusst nur zwei zentrale Container:

pihole/pihole:latest
zydou/dnscrypt:latest

Pi-hole übernimmt DNS-Filterung und Verwaltung, während dnscrypt-proxy für die Kommunikation mit den externen DNS-Resolvern zuständig ist.

Die Konfiguration und persistenten Daten befinden sich außerhalb der Container. Dadurch können die Container aktualisiert oder neu erstellt werden, ohne die Pi-hole-Konfiguration zu verlieren.

Eigenes Dual-Stack-Netzwerk

Pi-hole und dnscrypt-proxy befinden sich in einem gemeinsamen Docker-Netzwerk namens dns.

Dabei werden sowohl IPv4 als auch IPv6 verwendet:

IPv4: 172.18.3.0/24
IPv6: fd00:dead:beef:30::/64

Die Container erhalten feste Adressen:

ServiceIPv4IPv6
Pi-hole172.18.3.2fd00:dead:beef:30::2
dnscrypt-proxy172.18.3.3fd00:dead:beef:30::3

Die festen Adressen sind hier durchaus sinnvoll. Pi-hole kann dadurch dnscrypt-proxy immer unter derselben Adresse erreichen.

Die Werte lassen sich bei Bedarf über die .env-Datei ändern.

DNS über dnscrypt-proxy

Pi-hole verwendet dnscrypt-proxy als Upstream-DNS-Server.

dnscrypt-proxy lauscht innerhalb des Docker-Netzwerks auf:

172.18.3.3:5053

Meine dnscrypt-proxy.toml verwendet Quad9 als Resolver:

ipv6_servers = true

listen_addresses = [
  '172.18.3.3:5053'
]

server_names = [
  'quad9-dnscrypt-ip6-filter-pri',
  'quad9-dnscrypt-ip4-filter-pri'
]

require_dnssec = true
require_nolog = true
require_nofilter = false

Zusätzlich werden DNSSEC-fähige Resolver vorausgesetzt.

Query- und NXDOMAIN-Logs können ebenfalls geschrieben werden:

[query_log]
file = '/var/log/dnscrypt-proxy/query.log'

[nx_log]

file = ‚/var/log/dnscrypt-proxy/nx.log‘

Diese Verzeichnisse werden vom Stack persistent auf dem Docker-Host gespeichert.

Vorgefertigte Blocklisten

Zusätzlich enthält das Repository eine Sammlung externer Pi-hole-Blocklisten.

Sie befindet sich unter:

config/pihole-blocklist.txt

Enthalten sind unter anderem Listen für:

  • Werbung
  • Tracking
  • Malware
  • Phishing
  • Microsoft-Telemetrie
  • Social-Media-Dienste
  • Streaming-Dienste
  • Adult-Inhalte
  • verschiedene deutschsprachige Filterlisten

Die Liste kann selbstverständlich vor der Installation angepasst werden.

Wer beispielsweise bestimmte Kategorien nicht blockieren möchte, entfernt die entsprechenden URLs einfach aus der Datei.

Blocklisten automatisch in Pi-hole importieren

Damit die Listen nicht alle manuell über die Pi-hole-Weboberfläche eingetragen werden müssen, enthält das Repository zusätzlich:

scripts/init-blocklists.sh

Das Skript liest die Blocklisten-Datei ein und trägt die URLs in die Adlist-Datenbank von Pi-hole ein.

Anschließend wird:

pihole -g

ausgeführt.

Pi-hole lädt dadurch die eingetragenen Listen herunter und baut seine Gravity-Datenbank auf.

Damit die Initialisierung nicht bei jedem Start erneut durchgeführt wird, legt das Skript anschließend eine Marker-Datei an:

/etc/pihole/.blocklists-initialized

So bleibt der normale Containerstart schlank.

Pi-hole als DNS-Server im LAN

Der Stack veröffentlicht Port 53 sowohl für TCP als auch UDP:

ports:
  - "0.0.0.0:53:53/tcp"
  - "0.0.0.0:53:53/udp"
  - "[::]:53:53/tcp"
  - "[::]:53:53/udp"

Im Router beziehungsweise DHCP-Server muss anschließend die IP-Adresse des Docker-Hosts als DNS-Server verteilt werden.

Die Clients senden ihre DNS-Anfragen damit an den Docker-Host, Docker leitet sie an Pi-hole weiter und Pi-hole verwendet anschließend dnscrypt-proxy als Upstream.

Problem: Port 53 ist bereits belegt

Gerade bei Ubuntu kann es passieren, dass der Stack zunächst nicht startet:

Bind for 0.0.0.0:53 failed: port is already allocated

Häufig ist systemd-resolved dafür verantwortlich.

Zunächst lässt sich prüfen, wer Port 53 verwendet:

sudo ss -lntup | grep ':53 '

Taucht dort beispielsweise 127.0.0.53:53 beziehungsweise systemd-resolved auf, kann der lokale DNS-Stub deaktiviert werden.

Dazu:

sudo nano /etc/systemd/resolved.conf

und folgende Einstellung setzen:

[Resolve]
DNSStubListener=no

Anschließend:

sudo systemctl restart systemd-resolved

Damit der Host selbst weiterhin DNS-Namen auflösen kann, sollte außerdem geprüft werden, wohin /etc/resolv.conf zeigt.

Eine mögliche Konfiguration ist:

sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Danach erneut:

sudo ss -lntup | grep ':53 '

Port 53 sollte nun für Pi-hole zur Verfügung stehen.

Es ist dabei normalerweise nicht notwendig, systemd-resolved vollständig zu deaktivieren.

Pi-hole hinter Traefik

Für die Weboberfläche befindet sich Pi-hole zusätzlich in meinem bereits vorhandenen externen Docker-Netzwerk:

proxy

Damit kann Traefik direkt mit dem Pi-hole-Webserver kommunizieren.

Der DNS-Dienst selbst läuft weiterhin über Port 53. Traefik wird ausschließlich für die HTTP-/HTTPS-Weboberfläche verwendet.

Der Stack enthält dafür entsprechende Traefik-Labels und unterstützt unter anderem meine dynamischen Middlewares:

default@file
authentik@file

Damit lässt sich beispielsweise Authentik vor die Pi-hole-Weboberfläche schalten.

Hinweis: Die konkrete Traefik-Konfiguration muss natürlich an die eigene Umgebung angepasst werden. Wer Traefik nicht verwendet, kann die entsprechenden Labels und das zusätzliche proxy-Netzwerk entfernen.

Installation

Zunächst das Repository klonen:

git clone https://github.com/happylippo/pihole-stack.git
cd pihole-stack

Danach die Beispielkonfiguration kopieren:

cp .env.example .env

Jetzt sollte insbesondere das Pi-hole-Passwort geändert werden.

Anschließend lässt sich die Compose-Konfiguration kontrollieren:

docker compose config

Wenn alles passt:

docker compose pull
docker compose up -d

Den Status der Container kann man anschließend mit:

docker compose ps

kontrollieren.

Die Logs stehen über:

docker compose logs -f

zur Verfügung.

Blocklisten initialisieren

Nach dem ersten erfolgreichen Start können die vorbereiteten Blocklisten importiert werden:

docker compose exec pihole bash /scripts/init-blocklists.sh

Je nach Anzahl und Größe der verwendeten Listen kann der anschließende Gravity-Aufbau etwas dauern.

Ob die Initialisierung bereits durchgeführt wurde, lässt sich anhand der Marker-Datei kontrollieren:

docker compose exec pihole \
  ls -l /etc/pihole/.blocklists-initialized

DNS testen

Nach der Installation sollte zunächst geprüft werden, ob Pi-hole DNS-Anfragen beantwortet.

Von einem anderen Rechner im Netzwerk beispielsweise:

nslookup example.com IP-DES-DOCKER-HOSTS

oder unter Linux:

dig @IP-DES-DOCKER-HOSTS example.com

Anschließend lohnt sich ein Blick in das Query Log von Pi-hole. Dort sollten die DNS-Anfragen des Clients erscheinen.

Auch dnscrypt-proxy kann kontrolliert werden:

docker compose logs dnscrypt

Damit lässt sich nachvollziehen, ob der verschlüsselte Upstream erfolgreich gestartet wurde.

Updates

Da Konfiguration und Pi-hole-Daten persistent gespeichert werden, ist das Aktualisieren des Stacks unkompliziert:

docker compose pull
docker compose up -d

Alte Images können anschließend optional entfernt werden:

docker image prune

Fazit

Die Kombination aus Pi-hole und dnscrypt-proxy ist für mich eine interessante Alternative zu einem einfachen Pi-hole-Setup.

Pi-hole übernimmt die zentrale DNS-Filterung für das Netzwerk, während dnscrypt-proxy die Kommunikation mit den externen Resolvern übernimmt. Durch Docker bleibt die Installation reproduzierbar und lässt sich sauber von anderen Diensten trennen.

Besonders praktisch finde ich bei diesem Stack:

  • Pi-hole und dnscrypt-proxy als getrennte Container
  • feste IPv4- und IPv6-Adressen
  • eigenes internes DNS-Netzwerk
  • persistente Konfiguration
  • vorbereitete Blocklisten
  • automatisierter Blocklisten-Import
  • Quad9 als vorkonfigurierter DNSCrypt-Upstream
  • optionale Traefik- und Authentik-Integration

Der komplette Stack inklusive compose.yml, .env.example, dnscrypt-Konfiguration und Blocklisten steht auf GitHub zur Verfügung:

https://github.com/happylippo/pihole-stack

Leave a Reply

Your email address will not be published. Required fields are marked *


Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.

WordPress Cookie Plugin von Real Cookie Banner