Nachdem seit einiger Zeit versucht wurde, meinen Server mittels gefälschter DNS-Queries als Teil eines DNS-Amplification-DDoS zu missbrauchen, gab es bereits vor einigen Wochen ein paar kleine Änderungen in meiner Firewall, um die Bandbreite, die mit solchen Angriffen erreicht werden kann, stark zu reduzieren. Und während wie man im DNS-Graphen sehen kann, auch bereits gut wirkte, so war dennoch dieses unnötige Grundrauschen da. Um auch dieses zu entfernen, gab es eine weitere Ergänzung in der Firewall.
Als Firewall kommt bei mir iptables zum Einsatz, was an sich keine große Sache darstellt. Es filtert halt die Sachen, die es soll und lässt den Rest in Ruhe. Nun bietet iptables aber eine ganze Menge mehr, als einfach nur stupide nach Source- oder Destination-IPs zu filtern. Während also die ersten Ansätze noch wirklich rein stupide
iptables -A INPUT -s "angebliche Quell-IP" -j DROP
waren, war der zweite Ansatz mittels Rate Limitting bereits etwas gezielter und dennoch wesentlich flexibler:
iptables -I INPUT -p udp --dport 53 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p udp --dport 53 -i eth0 -m state --state NEW -m recent --update --seconds 15 --hitcount 30 -j DROP
Während die erste Regel also Pakete zählt und den Timer resettet, sorgt die zweite Regel dafür, dass überschüssige Pakete gedroppt werden. So kommen die im Graphen sichtbaren Kanten bei etwa 3-5 Queries/Sekunde zustande.
Doch so richtig zufriedenstellend war das noch nicht. Also heute dann noch ein weiterer Schritt, der mittels String-Matching die problematischen Pakete vor dem DNS gezielt eliminiert:
iptables -t raw -I PREROUTING -p udp --destination-port 53 -m string --algo kmp --from 30 --hex-string "|010000010000000000000000020001|" -j DROP
iptables -t raw -I PREROUTING -p udp --destination-port 53 -m string --algo kmp --from 30 --hex-string "|0100000100000000000103697363036f72670000ff00010000291000000080000000|" -j DROP
Die erste der beiden Zeilen filtert hierbei Anfragen nach den Nameservern für . (Die Root-Domain), während die zweite Regel für Ruhe sorgt, was spezifische Quelldomains (in meinem Fall wurde ständig nach isc.org gefragt) angeht. Um den korrekten Matching-String zu finden, gibt es mit sowohl Wireshark als auch tcpdump zwei sehr leistingsfähige Programme. So kann man mit tcpdump recht einfach nach DNS-Paketen suchen, wenn man
tcpdump -nvvxxi eth0 port 53
eingibt und sich die einzelnen ankommenden Pakete anschaut. Interessant sind die Daten ab Offset 0x2C, was bei mir etwa wie folgt aussah:
15:01:52.966446 IP (tos 0x0, ttl 179, id 14613, offset 0, flags [none], proto UDP (17), length 64) 184.154.66.179.16996 > 176.9.26.150.53: [no cksum] 7490+ [1au] ANY? isc.org. ar: . OPT UDPsize=4096 OK (36) 0x0000: 6c62 6dbc bb87 28c0 da46 34a4 0800 4500 0x0010: 0040 3915 0000 b311 08ab b89a 42b3 b009 0x0020: 1a96 4264 0035 002c 0000 1d42 0100 0001 0x0030: 0000 0000 0001 0369 7363 036f 7267 0000 0x0040: ff00 0100 0029 1000 0000 8000 0000
Daraus die Leerzeichen entfernt, in zwei Pipes eingefasst und man hat den passenden Filter-String. Die eigentliche Domain findet sich ab Offset 0x36 und ist in diesem Fall isc.org.
Trotz der Regel sieht man zwar noch den einkommenden Traffic; aber zumindest gibt es keine Antworten mehr an die (gefälschten) Absenderadressen; man spart also durchaus einiges an Outbound-Traffic.
[…] Blog von Benny Baumann werden Tips vorgestellt, die sehr spezifisch bestimmte Anfragen mit einfachen iptables Regeln […]
Pingback by DNS-Query Limits mit iptables und Burstrate :: Debian, Hacks — 28.06.2012 @ 16:33:05
[…] Benny Baumann’s blog provides tips, which specifically drop certain requests with simple iptables rules. Sadly I can’t just drop requests for the root-servers (public name servers must answer such queries) and the problematic requests are not just for a single domain. The only thing coming into consideration was request limiting. In doing so the maximum count of requests per time time interval (such as per second) is limited. […]
Pingback by IPTables DNS query limiting with burst rate :: Debian, Hacks — 20.07.2012 @ 19:18:13
Guter Artikel !
Die Attacke von heute ist aber anders, das Paket sieht so aus:
0x0000: 001e 3353 0b52 00a0 c535 fdc7 0800 4500
0x0010: 003d c110 0000 ef11 0317 b2a2 931c c0a8
0x0020: 0121 ab92 0035 0029 0000 c554 0100 0001
0x0030: 0000 0000 0001 0000 ff00 0100 0029 2328
0x0040: 0000 0000 0000 0000 0000 00
Mit der Anleitung im Post und etwas knobeln kriegt man das
aber in den Griff 🙂
Kommentar by Tellenbach — 09.08.2012 @ 18:11:15