Verschlüsseltes DNS selber machen

23.02.2022 | Jens Meißner in howto

Die Anleitung setzt Debian 11 “Bullseye” als verwendetes Betriebssystem voraus. Für andere Betriebssysteme können die Befehle geringfügig abweichen. Es wird mindestens Version 1.4 der Software dnsdist benötigt.

dnsdist als DoT-/DoH-Server

Als DoT- und DoH-Server soll dnsdist verwendet werden. Bei dnsdist handelt es sich eigentlich um einen DNS-Loadbalancer zur Verteilung von DNS-Anfragen auf mehrere DNS-Server, welcher seit Version 1.4 auch DoT und DoH für eingehende Anfragen unterstützt. Die Loadbalancer-Funktion wird für den Betrieb eines verschlüsselnden Resolvers nicht zwingend benötigt, stört aber auch nicht weiter, da dnsdist auch mit einem einzelnen Backend funktioniert. Als Loadbalancer kann dnsdist selbst keine rekursiven DNS-Anfragen auflösen, dafür soll unbound als Backend verwendet werden. Grundsätzlich unterstützt auch unbound die verschlüsselten DNS-Protokolle, allerdings unterstützt die in Debian mitgelieferte Version von unbound kein DoH, sodass hier auf dnsdist zurückgegriffen werden soll.

Los geht es mit der Installation von unbound:

apt-get install unbound

In der Standard-Konfiguration akzeptiert unbound nur lokale Anfragen. Da es ausschließlich als Backend für den auf demselben Host laufenden dnsdist dienen soll, reicht dies aus. Die Konfiguration kann somit unverändert bleiben. Als nächstes wird dnsdist installiert:

apt-get install dnsdist

Der Start von dnsdist wird zunächst fehlschlagen, da es sich an den Port 127.0.0.1:53 binden möchte, welcher bereits durch unbound belegt ist. Auf diesem Port möchte dnsdist auf unverschlüsselte DNS-Anfragen hören. Da ein Server für verschlüsseltes DNS entstehen soll, wird diese Funktion nicht benötigt. Abschalten lässt sich der Port für unverschlüsseltes DNS nicht, aber er kann an eine andere Adresse gebunden werden. Konfiguriert wird dnsdist über die Datei /etc/dnsdist/dnsdist.conf in der Programmiersprache Lua. Mit der Direktive setLocal("127.0.0.2") kann der Socket auf eine andere Adresse des Loopback-Interfaces geändert werden. Anschließend sollte sich dnsdist starten lassen.

Über die Direktive newServer({address='127.0.0.1', checkInterval=60}) wird der zuvor installierte unbound als Backend für dnsdist konfiguriert. Das Check-Interval gibt an, wie oft geprüft wird, ob das Backend verfügbar ist. Da nur ein Backend existiert, bringt dieser Health-Check keine Vorteile und kann entsprechend selten erfolgen.

Für die Verschlüsselung der DNS-Abfragen mit TLS wird ein Zertifikat benötigt. Dafür kann entweder ein bereits vorhandenes Zertifikat verwendet oder über Let’s Encrypt ein neues erstellt werden. Im Folgenden wird davon ausgegangen, dass das Zertifikat in der Datei /etc/ssl/server.crt und der zugehörige private Schlüssel in der Datei /etc/ssl/private/server.key gespeichert ist. Sowohl das Zertifikat als auch der private Schlüssel müssen für den Benutzer _dnsdist lesbar sein.

Jetzt können die Direktiven für verschlüsseltes DNS zur Konfiguration hinzugefügt werden. Für DoT ist dies die Direktive addTLSLocal('0.0.0.0', '/etc/ssl/server.crt', '/etc/ssl/private/server.key'), wobei der erste Parameter die zu verwendende IP-Adresse des Servers angibt oder 0.0.0.0 gesetzt wird, damit alle konfigurierten IP-Adressen verwendet werden können. Es kann auch zusätzlich ein Port angegeben werden, standardmäßig wird 853 verwendet.

Bei der Direktive für DoH gibt es einen zusätzlichen vierten Parameter für den HTTP-Endpunkt, welcher später im Client ebenfalls konfiguriert werden muss: addDOHLocal('0.0.0.0', '/etc/ssl/server.crt', '/etc/ssl/private/server.key', '/dns-query'). Der Standard-Port für DoH ist der HTTPS-Port 443, der Standardwert für den HTTP-Endpunkt ist /dns-query.

Die letzte benötigte Direktive betrifft die Zugriffssteuerung, wozu eine ACL gesetzt werden muss. Da unbekannt ist, von welchen IP-Adressen später die Clients zugreifen sollen, wird der Zugriff von überall erlaubt: setACL('0.0.0.0/0')

Die komplette Konfigurationsdatei, ergänzt um zwei Parameter zur TLS-Konfiguration, könnte wie folgt aussehen:

setACL('0.0.0.0/0')
setLocal('127.0.0.2')
addTLSLocal('0.0.0.0', '/etc/ssl/server.crt', '/etc/ssl/private/server.key', {ciphers='HIGH:!SSLv3:!TLSv1:!aNULL:!eNULL:!kRSA:!DSS:!SHA256:!SHA384',minTLSVersioni='tls1.2'})
addDOHLocal('0.0.0.0', '/etc/ssl/server.crt', '/etc/ssl/private/server.key', '/dns-query', {ciphers='HIGH:!SSLv3:!TLSv1:!aNULL:!eNULL:!kRSA:!DSS:!SHA256:!SHA384',minTLSVersioni='tls1.2'})
newServer({address='127.0.0.1', checkInterval=60})

Damit ist die Konfiguration des Resolvers abgeschlossen, mit einem Neustart von dnsdist wird sie neu eingelesen: systemctl restart dnsdist.service

Vorhandenen Webserver nutzen

Wenn auf dem System bereits ein Webserver läuft, dann ist der für DoH verwendete HTTPS-Port bereits durch den Webserver in Verwendung. Es ist aber möglich, den Webserver so zu konfigurieren, dass DoH-Anfragen an den Resolver weitergeleitet werden. Zunächst wird dnsdist so konfiguriert, dass es einen anderen Port verwendet und nur lokal erreichbar ist: addDOHLocal('127.0.0.1:8080', nil, nil, '/dns-query'). Da der Webserver die TLS-Terminierung übernimmt, müssen in diesem Fall keine Zertifikate konfiguriert werden.

Die Konfiguration des Webservers soll beispielhaft für den Apache gezeigt werden, sollte sich aber auch auf andere Webserver übertragen lassen.

Es wird das Apache-Modul proxy_http benötigt, welches mit a2enmod proxy_http aktiviert wird. Anschließend wird die vHost-Konfiguration um folgende zwei Zeilen erweitert:

ProxyPass /dns-query http://localhost:8080/dns-query
ProxyPassReverse /dns-query http://localhost:8080/dns-query

Es muss sich dabei um einen vHost handeln, welcher per HTTPS erreichbar ist. Zum Schluss muss die neue Webserver-Konfiguration noch geladen werden: systemctl reload apache2.service

Client-Konfiguration

Wenn der Resolver läuft, können die Clients konfiguriert werden. In Android ist DNS over TLS eingebaut, der Webbrowser Firefox unterstützt DNS over HTTPS.

Android

Unter Android ab Version 9 kann DoT in den Einstellungen konfiguriert werden. Im Menü Netzwerk & Internet findet sich unter Erweitert der Punkt Privates DNS. Nach der Auswahl des Punktes Hostname des privaten DNS-Anbieters kann der Hostname des Resolvers eingetragen werden. Je nach Hersteller und Betriebssystem-Version kann das Menü anders aufgebaut sein.

Firefox

Der Webbrowser Firefox unterstützt DoH seit Version 60. In den Einstellungen können unter Allgemein ganz unten die Verbindungs-Einstellungen aufgerufen werden. Sobald dort DNS über HTTPS aktiviert wurde, kann ein Anbieter ausgewählt werden. Wird dort Benutzerdefiniert ausgewählt, kann die URL zum Endpunkt des DoH-Resolvers in der Form https://server.domain/dns-query eingetragen werden.

Fazit

Mit DoT und DoH können DNS-Abfragen verschlüsselt zwischen Client und Resolver übertragen werden. Der Betrieb eines eigenen Resolvers ermöglicht es, verschlüsseltes DNS zu benutzen, ohne auf die Resolver großer Cloud-Betreiber angewiesen zu sein. Es sollte jedoch bedacht werden, dass ein Zugriffsschutz bei DoT und DoH nicht vorgesehen ist. Der eingerichtete Server steht somit allen Personen zur Verfügung, welche den Namen des Endpunkts kennen. Dennoch sorgt ein eigener Resolver dafür, dass die eigenen DNS-Anfragen privat bleiben.

Jens Meißner
Jens Meißner
Jens Meißner arbeitet seit 2018 als Linux-Consultant bei B1 Systems und beschäftigt sich mit den Themen Netzwerk, Virtualisierung, Automatisierung und Monitoring. Am liebsten benutzt er Debian, interessiert sich neben Linux aber auch für FreeBSD und OpenBSD.

 


Haben Sie Anmerkungen oder Nachfragen? Melden Sie sich unter blog%b1-systems.de
Col 2