So erkennst du DNS-Tunneling auf einem Linux-Server
Zuletzt aktualisiert:
Beim DNS-Tunneling werden Daten in DNS-Anfragen versteckt. Ein Programm auf dem Server fragt nach Namen wie mzxw6ytboi4dgnzt.tunnel.example, wobei die Subdomain die Daten sind, und der Nameserver des Angreifers für tunnel.example antwortet mit weiteren Daten in TXT- oder anderen Einträgen. Das klappt, weil fast jeder Server DNS-Anfragen senden darf, auch einer, dessen ausgehender Verkehr sonst per Firewall gesperrt ist. Malware nutzt es, um Befehle zu empfangen und gestohlene Daten hinauszuschicken; Tools wie iodine und dnscat2 bauen ganze Netzwerkverbindungen darüber auf.
Der Verkehr hinterlässt Spuren, die normales DNS nicht hat: sehr lange zufällige Subdomains, viele eindeutige Namen unter einer Domain, ein hoher Anteil an TXT-Anfragen, eine gleichmäßige Rate von Anfragen an eine einzige Domain. Hier erfährst du, wie du den DNS-Verkehr des Servers mitschneidest und liest, die Resolver-Logs prüfst, das Programm findest und den Tunnel sperrst. Die Befehle gelten für Debian und Ubuntu sowie für die RHEL-Familie.
Erkennen, wie ein DNS-Tunnel aussieht
| Anzeichen | Normaler Verkehr | Ein Tunnel |
|---|---|---|
| Länge der Subdomain | Kurze Wörter: www, mail, api | 30 bis 63 zufällige Zeichen pro Label, oft mehrere Labels |
| Eindeutige Namen pro Domain | Wenige, immer wieder abgefragt | Hunderte oder Tausende, jeder nur einmal abgefragt |
| Anfragetypen | Überwiegend A und AAAA | Viele TXT-, NULL-, CNAME- oder MX-Anfragen |
| Rhythmus | Schübe, wenn jemand einen Dienst nutzt | Eine gleichmäßige Rate, Tag und Nacht, an dieselbe Domain |
| Resolver | Die aus /etc/resolv.conf | Manchmal ein DNS-Server, für den das System nicht konfiguriert ist |
Hinweis: Mancher legitime Verkehr sieht ähnlich aus: Abfragen von Virenscannern und Reputationsdiensten (sie kodieren Datei-Hashes in Namen), die Blocklist-Prüfungen eines Mailservers und manche CDN- und Cloud-Namen. Prüf die Domain, bevor du sie einen Tunnel nennst.
Den DNS-Verkehr des Servers mit tcpdump mitschneiden
Installier tcpdump und für die Auswertung weiter unten tshark. Unter Debian und Ubuntu fragt der tshark-Installer, ob Benutzer ohne Root-Rechte mitschneiden dürfen: Antworte mit Nein.
sudo apt install tcpdump tsharksudo dnf install tcpdump wireshark-cliZeichne fünf Minuten DNS-Verkehr auf, UDP und TCP, auf allen Schnittstellen. Mit systemd-resolved fragen Programme den lokalen Stub auf 127.0.0.53, und der Stub fragt weiter nach außen: -i any sieht beides.
sudo timeout 300 tcpdump -i any -nn -Z root -w /root/dns.pcap 'port 53'Dann wertest du aus. Zuerst den Anteil jedes Anfragetyps: Viele TXT? oder NULL? fallen auf.
sudo tcpdump -nn -r /root/dns.pcap 'dst port 53' 2>/dev/null \
| grep -oE '[A-Z0-9]+\? [^ ]+' | awk '{print $1}' | sort | uniq -c | sort -rnDann die Domains mit den meisten eindeutigen Namen darunter. Ein Tunnel bringt eine Domain mit Hunderten Namen an die Spitze; normaler Verkehr verteilt sich auf viele Domains mit jeweils wenigen Namen. (Die Zählung gruppiert nach den letzten beiden Labels, example.co.uk erscheint also als co.uk.)
sudo tcpdump -nn -r /root/dns.pcap 'dst port 53' 2>/dev/null \
| grep -oE '[A-Z0-9]+\? [^ ]+' | awk '{print tolower($2)}' | sort -u \
| awk -F. '{n = NF - 1; if (n >= 2) print $(n-1) "." $n}' | sort | uniq -c | sort -rn | head -20Und die Namen mit einem Label von 30 oder mehr Zeichen:
sudo tcpdump -nn -r /root/dns.pcap 'dst port 53' 2>/dev/null \
| grep -oE '[A-Z0-9]+\? [^ ]+' | awk '{print $2}' \
| awk -F. '{for (i = 1; i < NF; i++) if (length($i) >= 30) {print; break}}' | sort -u | head -20Dasselbe mit tshark
tshark liefert Statistiken nach Anfragetyp und Quelle und Ziel jeder Anfrage und findet ungewöhnlich große Antworten, mit denen Tunnel Daten zurückschicken:
sudo tshark -r /root/dns.pcap -q -z dns,tree
sudo tshark -r /root/dns.pcap -Y 'dns.flags.response == 0' -T fields \
-e ip.src -e ip.dst -e dns.qry.type -e dns.qry.name | head -50
sudo tshark -r /root/dns.pcap -Y 'dns.flags.response == 1 && udp.length > 512' -T fields \
-e dns.qry.name | sort | uniq -c | sort -rn | headHinweis: Das sieht nur DNS auf Port 53. Ein Tunnel über DNS over HTTPS läuft als gewöhnliches HTTPS auf Port 443 und ist hier unsichtbar; DNS over TLS nutzt Port 853, den Schritt 5 sperrt.
Die Resolver-Logs prüfen
Sieh dir zuerst an, welche Resolver der Server nutzen soll. Anfragen an jede andere Adresse sind schon für sich einen Blick wert.
cat /etc/resolv.conf
resolvectl status 2>/dev/null | grep -E 'DNS Servers|Current DNS'systemd-resolved führt kein Anfrage-Log, zeigt aber ab systemd 252 (Debian 12, Ubuntu 24.04, RHEL 9 und neuer) jede Abfrage live an. Lass es ein paar Minuten laufen und achte auf lange zufällige Namen:
sudo resolvectl monitorBetreibt der Server einen eigenen Resolver, schalte dessen Anfrage-Log ein. Bei unbound danach sudo systemctl restart unbound:
# /etc/unbound/unbound.conf (RHEL) or a file in /etc/unbound/unbound.conf.d/ (Debian, Ubuntu)
server:
log-queries: yes
log-replies: yessudo rndc querylog onBeide schreiben ins Journal. Das listet die Namen mit einem Label von 30 oder mehr Zeichen aus der letzten Stunde:
sudo journalctl --since "1 hour ago" -u unbound -u named -u bind9 \
| grep -ioE '([a-z0-9-]{30,}\.)+[a-z0-9.-]+' | sort | uniq -c | sort -rn | head -20Achtung: Anfrage-Logs wachsen auf einem ausgelasteten Resolver schnell. Schalte sie wieder ab, wenn du fertig bist (log-queries: no, sudo rndc querylog off).
Das Programm hinter den Anfragen finden
DNS-Sockets leben nur Sekundenbruchteile, also nimm Stichproben: Das schaut eine Minute lang jede Sekunde nach und zählt die Programme, die einen DNS-Socket offen hatten. Programme, die den Stub von systemd-resolved fragen, erscheinen mit ihrem eigenen Namen, denn auch der Stub lauscht auf Port 53.
for i in $(seq 1 60); do sudo ss -unpH '( dport = :53 )'; sleep 1; done \
| grep -o 'users:(("[^"]*",pid=[0-9]*' | sort | uniq -c | sort -rnSteht systemd-resolve, unbound oder named oben, kommen die Anfragen über den Resolver von einem anderen Programm: Schneide noch einmal nur auf der Loopback-Schnittstelle mit (-i lo) und vergleiche die Zeiten. Bei einem Programm, das du nicht kennst, sieh dir die Binärdatei, den Ordner und die Unit an, die es gestartet hat:
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PIDEin Tunnel-Client ist ein Zeichen einer Kompromittierung, nicht die Kompromittierung selbst. Such nach dem Rest wie in Krypto-Miner auf dem Server finden und entfernen: Persistenz in cron, systemd und SSH-Schlüsseln, veränderte Systembinärdateien und der Weg, auf dem der Angreifer hereinkam.
Den Tunnel sperren
Stopp zuerst das Programm. Sorg dann dafür, dass DNS den Server nur über die Resolver verlassen kann, die du gewählt hast: Diese nftables-Tabelle verwirft DNS an jede andere Adresse und DNS over TLS überall. Ersetze 192.0.2.53 durch deine Resolver aus Schritt 3 (mehrere durch Kommas getrennt).
sudo nft add table inet dnsguard
sudo nft 'add chain inet dnsguard out { type filter hook output priority 0; policy accept; }'
sudo nft add rule inet dnsguard out ip daddr != { 127.0.0.0/8, 192.0.2.53 } meta l4proto { tcp, udp } th dport 53 drop
sudo nft add rule inet dnsguard out tcp dport 853 dropAchtung: Mit einer falschen Resolver-Adresse kann der Server keine Namen mehr auflösen: Updates, Mail und die meisten Anwendungen stehen still. Halte eine zweite Sitzung offen, teste mit getent hosts debian.org und entferne die Tabelle bei einem Fehler mit sudo nft delete table inet dnsguard. Die Regeln decken IPv4 ab; ergänze ip6 daddr-Regeln, wenn der Server IPv6-Resolver nutzt. Die Tabelle ist nach einem Neustart weg.
Ein Tunnel über deinen eigenen Resolver funktioniert weiter, weil der Resolver die Anfragen weiterleitet. Wenn du unbound betreibst, beantworte die Tunnel-Domain mit „existiert nicht“:
# In the server: section of unbound.conf
local-zone: "tunnel.example." always_nxdomainsudo unbound-checkconf && sudo systemctl restart unboundMit systemd-resolved allein gibt es keine Sperre pro Domain: Richte den Server auf einen Resolver aus, der das kann, oder verlass dich darauf, das Programm zu entfernen. /etc/hosts hilft nicht, weil es nicht jede Subdomain abdecken kann.
Wie InfraFence DNS-Tunneling erkennt
Mit **DNS-Verkehr prüfen**, standardmäßig an, liest der Agent die eigenen DNS-Anfragen und -Antworten des Servers auf Paketebene: UDP-Port 53, nur lesend, mit einem Filter, der im Kernel läuft. Jedes Ereignis nennt das Programm, das gefragt hat, auch wenn die Anfrage über systemd-resolved lief.
dns_tunneling: 60 oder mehr verschiedene Subdomains einer Domain innerhalb von 5 Minuten, im Schnitt lange (24 Zeichen oder mehr), gezählt werden Subdomains ab 16 Zeichen sowie TXT- und NULL-Anfragen. Das Ereignis nennt die Domain, die Zahl der Subdomains und ihre durchschnittliche Länge.dns_dga: 20 oder mehr zufällig aussehende Domains, die es nicht gibt, innerhalb von 5 Minuten, das Kennzeichen von Malware, die ihren Server sucht.dns_threat_resolver(kritisch), wenn eine Anfrage an einen DNS-Server auf einer Bedrohungsliste geht,dns_threat_answer, wenn ein Name auf eine gelistete Adresse auflöst, unddns_unlisted_resolver, wenn ein Programm einen anderen als die konfigurierten DNS-Server nutzt.- Abfragen von Virenscannern und Reputationsdiensten, Blocklist-Prüfungen für Mail sowie große CDNs und Clouds werden ausgelassen, und der eigene DNS-Dienst des Servers zählt nicht als verdächtiges Programm.
Siehe Ausgehende und DNS-Bedrohungen. Was es nicht tut: Es meldet einen Tunnel und sperrt ihn nicht; ausgehende Sperren gelten nur für Adressen auf Bedrohungslisten (Ports und ausgehende Sperren), die Sperre oben bleibt also deine Aufgabe. Es sieht kein DNS über TCP, TLS oder HTTPS, und ein Tunnel, der langsamer als die Schwellen ist, wird nicht gemeldet.
Fragen
- Meine Firewall sperrt ausgehenden Verkehr. Kann DNS-Tunneling trotzdem funktionieren?
- Ja, wenn der Server einen Resolver fragen darf, und das darf fast jeder Server. Der Resolver leitet die Anfragen für dich an den Nameserver des Angreifers weiter. Deshalb muss auch der Resolver die Domain sperren, oder das Programm muss weg.
- Stoppen DNSSEC oder DNS over HTTPS das?
- Nein. DNSSEC belegt, dass Antworten echt sind, und die Antworten des Angreifers sind für seine eigene Domain echt. DNS over HTTPS verbirgt die Anfragen vor dem Netzwerk, was einen Tunnel schwerer erkennbar macht, aber nicht unmöglich.
- Welcher legitime Verkehr sieht wie ein Tunnel aus?
- Abfragen von Virenscannern und Reputationsdiensten, die Datei-Hashes in Namen kodieren, die Blocklist-Prüfungen eines Mailservers sowie manche CDN-, Cloud- und Telemetrie-Namen. Schlag die Domain nach, bevor du handelst.
Kostenlos auf 1 Server testen
Starter ist für einen Server kostenlos, mit vollem Schutz und automatischen Sperren. Ohne Kreditkarte.
Installiere den Agenten als root, mit deinem Token anstelle von <TOKEN>:
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>Das Token erstellst du im Dashboard unter Server › Server hinzufügen.
