Vor einiger Zeit habe ich bei mir Zuhause ein Pi-hole auf einem Raspberry installiert, um unerwünschte Werbung zu filtern. Dieser funktioniert nach einigen Startschwierigkeiten (selbstgemachte Firewall Probleme) sehr gut. Damit wird nun sämtlicher Netzwerkverkehr in meinem Netzwerk gefiltert, was auch z.B. Fernseher oder Smartphones, Tablets usw. betrifft.
Gerade Geräte wie Smartphones, bei denen häufig In-App Werbung eingeblendet wird, profitieren von der Filterung der DNS-Anfragen direkt beim DNS-Server. Es wird nicht nur Werbung gefiltert, sonder z.B. auch Tracker von Samsung TV, Google Analytics oder Sonos (was nicht deaktiviert werden kann).

Mehr über das Pi-hole und eine Anleitung zur Installation findest du hier:

Neulich wurde ein neuer DNS-Dienst Quad9 in Betrieb genommen. Quad9 unterscheidet sich von ähnlichen Diensten wie Google Public DNS durch die Fokussierung auf Benutzerfreundlichkeit, Skalierbarkeit, Sicherheit und Datenschutz. Ein interessantes und scheinbar undokumentiertes Feature ist, dass der Dienst DNS-over-TLS anbietet. Dadurch wird die Kommunikation zwischen dem Client und dem DNS-Server mit TLS verschlüsselt und die Privatsphäre (bis und mit DNS-Server) geschützt. Bisher verspricht Quad9 keine personenbezogene Daten zu sammeln.

Ich möchte nun das Pi-Hole so einrichten, damit DNS Queries an Quad9 gehen und mit TLS verschlüsselt übertragen werden.

Stubby

Dafür benötigen wir einen DNS-Client der DNS-over-TLS fähig ist. Der wohl fortschrittlichste (experimentelle) Client ist momentan Stubby von getdns.

Update: Es gibt stubby nun in den Paketquellen von Debian Buster. Mein Raspberry Pi läuft momentan mit Debian Stretch, daher kompiliere ich den Client von der Source.

Build

Auf dem Raspberry Pi:

# Dependencies installieren für Build und Run
sudo apt-get install build-essential libssl-dev libtool m4 autoconf automake libyaml-dev libev4 libuv1

Nun das Git-Repo auschecken und die Git-Submodules aktualisieren

git clone https://github.com/getdnsapi/getdns.git
cd getdns
sed -i 's#git://#https://#g' .gitmodules # fix for git checkout
git submodule update --init
libtoolize -ci
autoreconf -fi
mkdir -v build && cd build
../configure --prefix=/usr/local --without-libidn --without-libidn2 --enable-stub-only --with-stubby

Zeit für ein Kaffee:

make && sudo make install
Konfiguration

Soweit ist Stubby kompiliert und installiert. Nun erstellen wir noch die Stubby Konfiguration und integrieren diesen in Systemd, damit er zuverlässig verwaltet werden kann:

cd ../stubby
sudo useradd stubby
sudo /usr/bin/install -Dm644 stubby.yml.example /etc/stubby.yml

Achtung! Per default ist der Strict-Mode aktiv, daher kein Fallback auf tcp oder udp dns.

Die Transportoptionen im Strict-Mode beschränkt die Kommunikation auf TLS und zusätzlich wird eine Authentifizierung des Upstream DNS gefordert.

dns_transport_list:
  - GETDNS_TRANSPORT_TLS
#  - GETDNS_TRANSPORT_TCP   # disabled, cleartext queries
#  - GETDNS_TRANSPORT_UDP   # disabled, cleartext queries

# For Strict use        GETDNS_AUTHENTICATION_REQUIRED
# For Opportunistic use GETDNS_AUTHENTICATION_NONE
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED

Wir editieren die Stubby Konfiguration und tragen unter listen_addresses auf welche Adresse und Port der Client hören soll. Da der Client vom Pi-hole genutzt wird, muss Stubby nur lokal erreichbar sein. Zusätzlich benötigen wir einen anderen Port, da das Pi-hole ja selbst einen DNS-Dienst auf dem Standardport 53 betreibt.
Ich habe 127.0.2.2 als lokale IP verwendet um im Log und der Graphen von Pi-Hole unterscheiden zu können, wohin die Abfragen eventuell weitergeleitet werden. Somit ist klar, dass diese an Stubby gestellt werden.

# sudo vi /etc/stubby.yml
listen_addresses:
  - 127.0.2.2@5353
  - 0::2@5353

Als Upstream Servers (an welche die DNS-Abfragen weitergeleitet werden), habe ich nun ein bisschen weiter unten Quad9 eingetragen. Das kann natürlich ein beliebiger DNS-Dienst sein, der TLS unterstützt. Zusätzlich verifiziere ich die Authenizität des Servers über den tls_auth_name damit sich nicht jemand anderes als dns.quad9.netausgeben kann.

upstream_recursive_servers:
  - address_data: 9.9.9.9
    tls_auth_name: "dns.quad9.net"
  - address_data: 2620:fe::fe
    tls_auth_name: "dns.quad9.net"

Alternativ könnte die Authentifizierung mit Public-Key-Pinning (SPKI) für TLS verwendet werden (RFC7858) (tls_pubkey_pinset), was aber eine manuelle anpassung der Konfiguration bedingt, wenn das Zertifikat erneuert wird. Die pubkey digest value kann selbst abgefragt werden (funktioniert für jeden TLS-DNS-Server):

echo | openssl s_client -connect '9.9.9.9:853' 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Und da haben wir die Antwort für Quad9: MujBQ+U0p2eZLTnQ2KGEqs+fPLYV/1DnpZDjBDPwUqQ=

Das Quad9 Zertifikat ist von Let's Encrypt, daher ist zu vermuten, dass nach dem erneuern des Zertifikats sich der Digest ändert und die Authentifizierung nicht mehr funktioniert. Es empfiehlt sich daher nur tls_auth_name zu verwenden.

Hier ist mein finales Stubby-Konfigfile /etc/stubby.yml:

resolution_type: GETDNS_RESOLUTION_STUB
dns_transport_list:
  - GETDNS_TRANSPORT_TLS
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 256
edns_client_subnet_private: 1
idle_timeout: 10000
round_robin_upstreams: 0

listen_addresses:
  - 127.0.2.2@5353
  - 0::2@5353
upstream_recursive_servers:
  - address_data: 9.9.9.9
    tls_auth_name: "dns.quad9.net"

Installation des Systemd-Services

sudo vi /lib/systemd/system/stubby.service 

[Unit]
Description=stubby DNS resolver
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/bin/stubby -C /etc/stubby.yml
Restart=on-abort
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
User=stubby

[Install]
WantedBy=multi-user.target

Als letzter Schritt für den TLS-DNS-Client Teil starten und testen wir nun Stubby:

sudo systemctl daemon-reload
sudo systemctl enable stubby
sudo systemctl start stubby
pi@raspberrypi:~/ $ dig @127.0.2.2 -p 5353 quad9.net

; <<>> DiG 9.10.3-P4-Raspbian <<>> @127.0.2.2 -p 5353 quad9.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12094
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; CLIENT-SUBNET: 9.9.0.0/20/0
;; QUESTION SECTION:
;quad9.net.         IN  A

;; ANSWER SECTION:
quad9.net.      120 IN  A   216.21.3.77

;; Query time: 142 msec
;; SERVER: 127.0.2.2#5353(127.0.2.2)
;; WHEN: Sun Jan 14 11:49:22 UTC 2018
;; MSG SIZE  rcvd: 74

Hooray!

Pi-hole mit Stubby

Damit Pi-hole nun unseren lokalen DNS-Resolver Stubby verwendet, konfigurieren wir die Forwarding DNS Server vom Pi-hole um.

Das Pi-hole Webgui lässt keine DNS-Server mit Port konfigurieren, daher muss dies manuell angepasst werden

Dazu erstelle ich eine neues Konfigfile /etc/dnsmasq.d/02-stubby.conf und trage die Stubby-Adressen als Upstream ein:

server=127.0.2.2#5353

Die Anpassung am Pi-hole, damit die Server nicht doppelt oder falsch konfiguriert sind:

  • server= aus dem /etc/dnsmasq.d/01-pihole.conf löschen.
  • PIHOLE_DNS_1 aus /etc/pihole/setupVars.conf löschen.

Und als letztes den Pi-hole DNS-Dienst neu starten:

sudo systemctl restart dnsmasq

Test

Im Pi-hole log /var/log/pihole.log oder im Webgui sollte nun ersichtlich sein, dass die Anfragen an Stubby forwarded werden:

forwarded maps.googleapis.com to 127.0.2.2
forwarded fedoraproject.org to 127.0.2.2

Mit tcpdump habe ich auf dem Router die gesendeten und empfangenen Pakete mitgeschnitten und in Wireshark ausgewertet.
Wie zu erwarten ist der DNS Verkehr jetzt verschlüsselt:

Wireshark Segment

Next Post Previous Post

Kommentar hinzufügen

Kommentare

Bei mir hängt es bei der dig-Abfrage - da kommt bei mir folgendes: pi@raspberrypi:~ $ dig @127.0.2.2 -p 5353 quad9.net ; DiG 9.10.3-P4-Raspbian @127.0.2.2 -p 5353 quad9.net ; (1 server found) ;; global options: cmd ;; connection timed out; no servers could be reached pi@raspberrypi:~ $ Die config-Files habe ich, wie auch den Rest, gecopypasted - und dann noch dreimal auf Fehler geprüft. Daran kanns also eigentlich nicht liegen :/ Der Stubby selbst scheint aber auch zu spinnen: service stubby status ● stubby.service - stubby DNS resolver Loaded: loaded (/lib/systemd/system/stubby.service; enabled; vendor preset: Active: failed (Result: exit-code) since Wed 2018-07-11 11:54:12 UTC; 6h ago Process: 20362 ExecStart=/usr/local/bin/stubby -C /etc/stubby.yml (code=exite Main PID: 20362 (code=exited, status=127) Jul 11 11:54:11 raspberrypi systemd[1]: Started stubby DNS resolver. Jul 11 11:54:12 raspberrypi systemd[1]: stubby.service: Main process exited, co Jul 11 11:54:12 raspberrypi systemd[1]: stubby.service: Unit entered failed sta Jul 11 11:54:12 raspberrypi systemd[1]: stubby.service: Failed with result 'exi lines 1-10/10 (END) Eine Idee?
geschrieben am Wed, 11 Jul 2018 20:04:20 von Andreas
I'm stuck at this point -> dig @127.0.2.2 -p 5353 quad9.net. The response I get isn't successful. dig @127.0.2.2 -p 5353 quad9.net ; DiG 9.10.3-P4-Raspbian @127.0.2.2 -p 5353 quad9.net ; (1 server found) ;; global options: cmd ;; connection timed out; no servers could be reached I have no idea how to fix this - I've followed the instructions exactly but I have no idea how to fix this error. Any help would be appreciated.
geschrieben am Mon, 02 Jul 2018 15:11:11 von Josh
Please be aware that if you use android phone it will leak your DNS even if your networks DHCP settings tell it not to. Only solution I have found so far is to manually set the DNS to Pi-hole using DNS Changer app from playstore (which acts as vpn) forcing android to use that DNS. If anyone finds a better solution than doesn't require manual intervention please post here:).
geschrieben am Mon, 18 Jun 2018 15:03:55 von Roland
Hi James again, I was able to get this running within a container via Linux Deploy on Android. MODIFIED STEPS - Stubby configuration for pihole setup You will need to make the following changes to the procedure above. - After creating the systemd script. (Step - Installation of the Systemd-Services) Power off then power on the container. This will run the newly created systemd script on startup. - Change to su then run systemctl enable stubby. This should show the following: Created symlink /etc/systemd/system/multi-user.target.wants/stubby.service -> /lib/systemd/system/stubby.service. - Power off the container then power it on again. This will re-run the systemd script and ensure that stubby is enabled. - Run stubby -i, this will show you what configuration file stubby is looking at. For some reason, the stubby configuration file that appears to be referenced is: /usr/local/etc/stubby/stubby.yml rather than the tutorial specified /etc/stubby.yml. Edit the stubby file in the /usr directory - Then run sudo stubby to start stubby. stubby starts as a daemon by sudo stubby. WAIT. IT WILL TAKE SOME TIME TO START THIS SERVICE! It will appear to hang. If there are no errors during launch, begin the testing. For testing, you could alternatively run stubby -l as this will show a rolling log in the console. Thank you for this great tutorial. Regards, James
geschrieben am Mon, 04 Jun 2018 13:26:09 von James
Thank you for this great tutorial. I'm running Debian Stretch within a container on Android using Linux Deploy (https://play.google.com/store/apps/details?id=ru.meefik.linuxdeploy&hl=en) There were no errors or issues in following these instructions until I got to this point: sudo systemctl daemon-reload sudo systemctl enable stubby sudo systemctl start stubby When I try to run these commands, I get the following error message: Running in chroot, ignoring request. Could I please request your assistance with this issue? Regards, James
geschrieben am Sun, 03 Jun 2018 11:54:45 von James
Awesome! works great.
geschrieben am Thu, 12 Apr 2018 05:40:27 von jm