Ich beschreibe euch wie ihr einen eigenen DNS Resolver inklusive DoT und DoH für die Namensauflösung im Internet aufsetzen könnt.
So wurde auch der adminForge Service: dnsforge.de konfiguriert.
Aufbau des Setups:
- dnsdist – DNS Loadbalancer: DNS Port 53, DoT Port 853, DoH Port 443
- Pi-hole – Werbeblocker: 127.0.0.1:53
- PowerDNS Recursor – auflösender Nameserver: 127.0.0.1:5300
Punkt 1: PowerDNS Repositories hinzufügen
Zuerst fügen wir die beiden Repositories von dnsdist und PowerDNS Recursor hinzu: https://repo.powerdns.com/
Beispiel Debian 11:
1 2 3 |
apt-get update apt-get install gnupg curl https://repo.powerdns.com/FD380FBB-pub.asc | apt-key add - |
1 2 3 4 |
cat <<EOF > /etc/apt/sources.list.d/powerdns.list deb [arch=amd64] http://repo.powerdns.com/debian bullseye-dnsdist-17 main deb [arch=amd64] http://repo.powerdns.com/debian bullseye-rec-47 main EOF |
Punkt 2: Pakete installieren
Wir installieren die beiden Pakete.
1 2 |
apt-get update apt-get install dnsdist pdns-recursor |
Punkt 3: Pi-hole installieren
Wir starten mit der Installation des Werbeblockers Pi-hole.
1 |
curl -sSL https://install.pi-hole.net | bash |
Wenn ihr die eine vollständige Pi-hole Installation haben möchtet, mit Webserver und Webinterface, dann drückt die Installation mit ENTER durch.
Das Pi-hole Admin Interface ist dann unter http://YOUR-IP/admin/ zu erreichen. Ich empfehle eine zusätzliche Absicherung des Webinterfaces!
Punkt 4: dnsdist konfigurieren
Kopiert diesen Text in die Konsole um eine dnsdist Konfiguration zu erstellen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
cat <<EOF > /etc/dnsdist/dnsdist.conf setLocal('YOUR-IPv4:53') addLocal('[YOUR-IPv6]:53') setACL({'0.0.0.0/0', '::/0'}) --addDOHLocal('YOUR-IPv4', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') --addDOHLocal('YOUR-IPv6', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') --addTLSLocal('YOUR-IPv4', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') --addTLSLocal('YOUR-IPv6', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') newServer({address='127.0.0.1:53', pool='recursor', checkInterval='300', checkTimeout='5', maxCheckFailures='3'}) -- Block hosts that exceeded 100 queries in 10 seconds for 30 minutes function maintenance() addDynBlocks(exceedQRate(100, 10), "Exceeded query rate", 1800) end addAction(AllRule(), PoolAction('recursor')) EOF |
Ersetzt dann eure IPv4 und IPv6 Adressen in den markieten Zeilen.
Für einen öffentlichen Resolver könnt ihr diese Befehle verwenden:
1 2 |
IPV4=$(curl -s 4.ipwho.de/ip); sed -i 's/YOUR-IPv4/'$IPV4'/g' /etc/dnsdist/dnsdist.conf IPV6=$(curl -s 6.ipwho.de/ip); sed -i 's/YOUR-IPv6/'$IPV6'/g' /etc/dnsdist/dnsdist.conf |
Punkt 5: Let’s Encrypt
Für Let’s Encrypt verwende ich gerne acme.sh, ihr könnt aber auch gerne eigene Zertifikate oder andere Let’s Encrypt Scripte verwenden.
1 2 |
apt-get install socat curl https://get.acme.sh | sh |
Einen Ordner für die Zertifikate legen wir in folgender Datei fest, ich empfehle den bereits vorhandenen Ordner /etc/ssl/private
.
1 |
CERT_HOME="/etc/ssl/private" |
Nun holen wir uns ein Zertifikat.
WICHTIG: Eure Domain sollte bereits jetzt einen A-Record mit der IP-Adresse eures Servers haben und auflösen!
Variante 1 (Pi-hole mit Webserver):
1 |
/root/.acme.sh/acme.sh --issue -k ec-384 -w /var/www/html -d domain.de --reloadcmd "systemctl restart dnsdist.service" |
Variante 2 (Pi-hole ohne Webserver):
1 |
/root/.acme.sh/acme.sh --issue -k ec-384 --standalone -d domain.de --reloadcmd "systemctl restart dnsdist.service" |
Punkt 6: dnsdist DoT und DoH aktivieren
In der /etc/dnsdist/dnsdist.conf
entfernen wir die --
und ersetzen domain.de mit unserer Domain YOUR-DOMAIN.de
aus dem Schritt zuvor.
1 2 |
sed -i 's/--add/add/g' /etc/dnsdist/dnsdist.conf sed -i 's/domain.de/YOUR-DOMAIN.de/g' /etc/dnsdist/dnsdist.conf |
Änderungen sollten in etwa so ausschauen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
setLocal('YOUR-IPv4:53') addLocal('[YOUR-IPv6]:53') setACL({'0.0.0.0/0', '::/0'}) addDOHLocal('YOUR-IPv4', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') addDOHLocal('YOUR-IPv6', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') addTLSLocal('YOUR-IPv4', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') addTLSLocal('YOUR-IPv6', '/etc/ssl/private/domain.de_ecc/fullchain.cer', '/etc/ssl/private/domain.de_ecc/domain.de.key') newServer({address='127.0.0.1:53', pool='recursor', checkInterval='300', checkTimeout='5', maxCheckFailures='3'}) -- Block hosts that exceeded 100 queries in 10 seconds for 30 minutes function maintenance() addDynBlocks(exceedQRate(100, 10), "Exceeded query rate", 1800) end addAction(AllRule(), PoolAction('recursor')) |
Punkt 7: Pi-hole anpassen
Wir erweitern die Adlist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
cat <<EOF > /etc/pihole/adlists.list https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt https://justdomains.github.io/blocklists/lists/easylist-justdomains.txt https://justdomains.github.io/blocklists/lists/easyprivacy-justdomains.txt https://justdomains.github.io/blocklists/lists/adguarddns-justdomains.txt https://justdomains.github.io/blocklists/lists/nocoin-justdomains.txt https://adaway.org/hosts.txt https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt https://dbl.oisd.nl/basic/ https://blocklistproject.github.io/Lists/malware.txt https://blocklistproject.github.io/Lists/phishing.txt https://blocklistproject.github.io/Lists/ransomware.txt https://blocklistproject.github.io/Lists/tracking.txt EOF |
Passen /etc/pihole/setupVars.conf
unseren Wünschen an: Lokale IP-Adresse, Loopback Interface, deaktivieren Querry logging, stellen Pihole DNS auf unseren PowerDNS Recursor.
1 2 3 4 5 6 |
sed -i 's/IPV4_ADDRESS=.*/IPV4_ADDRESS=127.0.0.1/' /etc/pihole/setupVars.conf sed -i 's/IPV6_ADDRESS=.*/IPV6_ADDRESS=::1/' /etc/pihole/setupVars.conf sed -i 's/QUERY_LOGGING=.*/QUERY_LOGGING=false/' /etc/pihole/setupVars.conf sed -i '$ a\DNSSEC=true' /etc/pihole/setupVars.conf sed -i 's/PIHOLE_DNS_1=.*/PIHOLE_DNS_1=127.0.0.1#5300/' /etc/pihole/setupVars.conf sed -i '/PIHOLE_DNS_2=.*/d' /etc/pihole/setupVars.conf |
Um sicher zu gehen, dass Pi-hole bei einem Update diese Variable nicht löscht, erstellen wir eine neue Datei um das Interface lo
zu binden.
1 2 3 4 |
cat <<EOF > /etc/dnsmasq.d/02-bind.conf interface=lo bind-interfaces EOF |
Punkt 8: PowerDNS Recursor konfigurieren
Jetzt gehen wir das letzte Element der Kette an – dem Recursor von PowerDNS. Das kleine Programm schickt sämtliche DNS-Anfragen direkt an die DNS-Rootserver und behilft sich der vorinstallierten DNS-Rootserver Datei /usr/share/dns/root.hints
.
1 2 3 4 |
sed -i 's/# dnssec=.*/dnssec=validate/' /etc/powerdns/recursor.conf sed -i 's/local-address=.*/local-address=127.0.0.1/' /etc/powerdns/recursor.conf sed -i 's/# local-port=.*/local-port=5300/' /etc/powerdns/recursor.conf sed -i 's/# query-local-address6=.*/query-local-address6=::/' /etc/powerdns/recursor.conf |
Punkt 9: Dienste starten
Nun ist es an der Zeit die Pi-hole Konfiguration zu übernehmen
1 |
pihole -r |
und die Dienste neu zu starten.
1 |
systemctl restart pihole-FTL.service pdns-recursor.service dnsdist.service |
WICHTIG: dnsdist zuletzt starten da wir ein checkInterval
von 5 Minuten eingestellt haben! Ansonsten ist der downstream Server 127.0.0.1:53 nicht direkt up
.
Punkt 10: DNS Auflösung testen
Zu guter Letzt überprüfen wir ob alle Dienste auf den korrekten Ports lauschen.
1 |
netstat -ntupl | egrep "dnsdist|pdns|pihole" |
Soll:
dnsdist/tcp: 53, 443, 853
dnsdist/udp: 53
pihole/tcp+udp: 127.0.0.1:53, ::1:53
pdns_recursor/tcp+udp: 127.0.0.1:5300
Wenn alles stimmt können wir die ersten Namensauflösungen testen.
DNS:
Das Tool dig
ist unter Debian vorinstalliert. Tragt hinter dem @
die öffentliche IP-Adresse des Servers ein.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
dig adminforge.de @xxx.xxx.xx.xx ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> adminforge.de @xxx.xxx.xx.xx ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17240 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;adminforge.de. IN A ;; ANSWER SECTION: adminforge.de. 277 IN A 5.9.68.168 ;; Query time: 0 msec ;; SERVER: xxx.xxx.xx.xx#53(xxx.xxx.xx.xx) ;; WHEN: Mon Jan 27 15:32:16 CET 2020 ;; MSG SIZE rcvd: 58 |
DNS over TLS:
Da PHP dank Pi-hole bereits installiert ist, nutzen wir am einfachsten dnstls zum testen. Anstelle domain.de
nehmt bitte eure Domain.
1 2 3 4 |
wget https://raw.githubusercontent.com/dcid/dns-over-tls-php-client/master/dnstls.php php dnstls.php adminforge.de domain.de adminforge.de has address 5.9.68.168 |
DNS over HTTPS:
Über einen kleinen curl
Aufruf kann man prüfen ob DoH funktioniert. Angefragt wird hier example.com (verschlüsselt dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE).
1 2 3 4 5 6 |
curl -I "https://domain.de/dns-query?ct&dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE" HTTP/2 200 server: h2o/dnsdist date: Mon, 27 Jan 2020 15:12:00 GMT content-type: application/dns-message content-length: 45 |
Unterstütze unsere Arbeit mit einer Spende. |