2017 schrieb ich über die Einrichtung von DNSCrypt in Debian, mittlerweile nutze ich aber DNS-over-TLS (DoT) mit einem eigenen server. Sowohl auf Server-, als auch auf Client-Seite nutze ich knot-resolver.
Einrichtung
Server
Zuerst muss das Paket knot-resolver installiert werden:
apt install knot-resolver
Danach muss /etc/knot-resolver/kresd.conf
editiert werden:
net.listen('127.0.0.1', 53)
net.listen('IP4', 853, { kind = 'tls' })
net.listen('IP6', 853, { kind = 'tls' })
user('knot-resolver','knot-resolver')
cache.size = 2*GB
modules = {
'view',
'hints > iterate',
'serve_stale < cache',
'workarounds < iterate'
}
Statt IP4
und IP6
muss natürlich die IP-Adresse eingegeben werden, auf der der server
über DoT erreichbar sein soll. Ggf. muss man natürlich auch noch den Port 853 in der firewall
für Zugriffe von Außen freigeben.
Anschließend aktiviert man den server folgendermaßen:
systemctl enable --now kresd@{1..4}.service
Zugriff auf TLS-Zertifkate
Ohne weitere Konfiguration benutzt kresd selbstsignierte Zertifikate für DoT. Ich habe auf meinem server bereits Zertifikate von Let’s Encrypt und möchte diese auch für DoT nutzen. Um die Zertifikate für kresd erreichbar zu machen habe ich ein kleines Skript geschrieben:
cp /etc/letsencrypt/live/mdosch.de/privkey.pem /var/lib/knot-resolver
cp /etc/letsencrypt/live/mdosch.de/fullchain.pem /var/lib/knot-resolver
chown -R knot-resolver:knot-resolver /var/lib/knot-resolver
chmod 700 /var/lib/knot-resolver
systemctl restart kresd@{1..4}.service
Die Pfade der Zertifikate sind natürlich anzupassen und das Skript muss nach dem Speichern ausführbar gemacht werden:
chmod +x /pfad/zum/script.sh
Damit das Skript auch ausgeführt wird wenn certbot die Zertifikate erneuert, lasse ich
es mittels --renew-hook
aufrufen.
Nun muss die Konfiguration abgeändert werden (Zeile 1) damit kresd die Zertifikate auch nutzt:
net.tls("/var/lib/knot-resolver/fullchain.pem", "/var/lib/knot-resolver/privkey.pem")
net.listen('127.0.0.1', 53)
net.listen('IP4', 853, { kind = 'tls' })
net.listen('IP6', 853, { kind = 'tls' })
user('knot-resolver','knot-resolver')
cache.size = 2*GB
modules = {
'view',
'hints > iterate',
'serve_stale < cache',
'workarounds < iterate'
}
Danach muss kresd neu gestart werden:
systemctl restart kresd@{1..4}.service
Werbung und Tracking filtern
Ich möchte Werbung und Tracking direkt auf DNS-Ebene blocken und nutze dafür die Blocklisten
von hBlock. Wenn man das hBlock-repo klont und dort make hosts
ausführt erhält man
u.a. eine Datei hosts_rpz.txt
im Ordner dist
. Diese Datei kann kresd einlesen und die
dort gelisteten hosts bei DNS-Abfragen blockieren. Die Konfiguration muss folgendermaßen
angepasst werden (Zeilen 13 und 16):
net.tls("/var/lib/knot-resolver/fullchain.pem", "/var/lib/knot-resolver/privkey.pem")
net.listen('127.0.0.1', 53)
net.listen('IP4', 853, { kind = 'tls' })
net.listen('IP6', 853, { kind = 'tls' })
user('knot-resolver','knot-resolver')
cache.size = 2*GB
modules = {
'view',
'hints > iterate',
'serve_stale < cache',
'workarounds < iterate',
'policy'
}
policy.add(policy.rpz(policy.DENY, '/pfad/zu/hosts_rpz.txt'))
Danach muss kresd wieder neu gestart werden:
systemctl restart kresd@{1..4}.service
Rekursives Blocken
Einige Trackingfirmen nutzen für ihre Kunden subdomains um die üblichen Schutzmaßnahmen
zu umgehen, z.B. zn0lxkzethotizctx-bahn.siteintercept.qualtrics.com
. Um den Schutz
vor Tracking zu verbessern kann man auch rekursiv alle subdomains der domains in der Blockliste
sperren.
Mit Hilfe von hBlock kann man eine Blockliste erstellen, die über wildcards auch die Subdomains umfasst:
hblock --output ./hosts_rpz.txt --header none --footer none --redirection '.' --template '%D CNAME %R\n*.%D CNAME %R' --comment ';' --filter-subdomains
Durch rekursives Blocken wird aber auch eine zufällig generierte subdomain in der Form
<random>-dnsotls-ds.metric.gstatic.com
geblockt, die bei Benutzung von DoT in
Android genutzt wird. Um die resultierende Fehlermeldung in Android zu vermeiden
wird diese subdomain gezielt erlaubt und folgendes in /etc/knot-resolver/kresd.conf
eingetragen:
policy.add(policy.pattern(
policy.PASS,
'%w+%-dnsotls%-ds\006metric\007gstatic\003com\000$'
))
Client
Linux
Auf dem client muss ebenfalls das Paket knot-resolver installiert werden:
apt install knot-resolver
Die Konfiguration /etc/knot-resolver/kresd.conf
gestaltet sich auf dem client recht
simpel:
net.listen('127.0.0.1', 53, { kind = 'dns' })
modules = {
'policy',
}
policy.add(policy.all(policy.TLS_FORWARD({
{'5.181.50.75', hostname='mdosch.de'},
{'2a03:4000:3f:1c8:8839:33ff:feba:fe4a', hostname='mdosch.de'},
})))
Die IPs und der hostname müssen natürlich gegen eure IPs und domain ausgetauscht werden.
Auch hier muss kresd aktiviert werden:
systemctl enable --now kresd@{1..4}.service
Anschließend muss man dem System mitteilen, den DNS-forwarder unter 127.0.0.1:53 zu nutzen.
Das tut man indem man die Datei /etc/resolv.conf
folgendermaßen editiert:
nameserver 127.0.0.1
Ggf. muss man noch den NetworkManager zähmen, damit dieser nicht die Datei
/etc/resolv.conf
überschreibt.
Android
Unter Android kann der DoT server folgendermaßen konfiguriert werden:
Einstellungen → Netzwerk & Internet → Erweitert → Privates DNS
Dort ist dann die domain, in meinem Fall z.B. mdosch.de
, einzutragen.
Test
Zum testen kann man den Befehl dig
aus dem Paket bind9-dnsutils nutzen.
Mit z.B. dig debian.org
bekommt man folgende Ausgabe:
dig debian.org
; <<>> DiG 9.17.19-1-Debian <<>> debian.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13249
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;debian.org. IN A
;; ANSWER SECTION:
debian.org. 280 IN A 128.31.0.62
debian.org. 280 IN A 130.89.148.77
debian.org. 280 IN A 149.20.4.15
;; Query time: 240 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Oct 31 11:00:57 CET 2021
;; MSG SIZE rcvd: 87
Hier wurde die domain debian.org erfolgreich aufgelöst und die Zeile
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
zeigt, dass der lokale DNS-forwarder benutzt
wurde.
Man kann natürlich auch Webseiten, wie z.B. dnsleaktest.com, benutzen um zu sehen welche DNS-server benutzt werden.
Mit dig google-analytics.com
kann getestet werden ob das Blocken von Werbung und Tracking
auch funktioniert:
dig google-analytics.com
; <<>> DiG 9.17.19-1-Debian <<>> @127.0.0.1 google-analytics.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 19517
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;google-analytics.com. IN A
;; Query time: 220 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Oct 31 11:03:38 CET 2021
;; MSG SIZE rcvd: 49
Hier wurde google-analytics nicht aufgelöst (status: SERVFAIL
),
die Blockliste wird also genutzt.
Updates
- 2022-03-06: Abschnitt Rekursives Blocken hinzugefügt.