Erstens weiß ich, dass dies eine alte Frage ist, aber ...
Ich habe jahrzehntelang meinen eigenen autorisierenden, nicht rekursiven DNS-Server betrieben, war aber noch nie Opfer von DNS-basierten DDoS-Angriffen - bis jetzt, als ich zu einem neuen ISP wechselte. Tausende von gefälschten DNS-Abfragen überfluteten meine Protokolle und ich ärgerte mich sehr - nicht so sehr über die Auswirkungen auf meinen Server, sondern vielmehr über die Tatsache, dass meine Protokolle überfüllt sind und das unangenehme Gefühl, missbraucht zu werden. Es scheint, dass der Angreifer versucht, mein DNS in einem " Authoritative Name Server-Angriff " zu verwenden.
Obwohl ich rekursive Abfragen auf mein internes Netzwerk beschränke (alle anderen verweigere), verbringe ich meine CPU-Zyklen lieber damit, Zeichenfolgen in iptables abzugleichen, als negative Antworten auf die gefälschten IP-Adressen zurückzusenden (weniger Unordnung in meinen Protokollen, weniger) Netzwerkverkehr und eine höhere Zufriedenheit von mir).
Ich begann damit, wie es alle anderen zu tun scheinen , herauszufinden, welche Domainnamen abgefragt werden, und eine Zeichenfolgenübereinstimmung für diese Domain mit einem Ziel-DROP zu erstellen. Aber mir wurde schnell klar, dass ich am Ende eine Menge Regeln haben würde, die jeweils CPU-Zyklen beanspruchen. Also, was ist zu tun? Da ich keinen rekursiven Nameserver betreibe, habe ich mir vorgenommen, den Abgleich für die tatsächlichen Zonen vorzunehmen, für die ich zuständig bin, und alles andere zu löschen.
Meine Standardrichtlinie in iptables ist ACCEPT. Wenn Ihre Richtlinie DROP ist, müssen Sie möglicherweise einige Anpassungen vornehmen, wenn Sie die folgende Lösung verwenden möchten.
Ich behalte meine Zonenkonfiguration in einer separaten Datei (/etc/bind/named.conf.local), verwenden wir dies als Beispiel:
zone "1.168.192.in-addr.arpa" { // Private
type master;
allow-query { 192.168.1.0/24; 127.0.0.1; };
allow-transfer { 127.0.0.1; };
file "/etc/bind/db.192.168.1";
};
zone "home.example.net" { // Private
type master;
allow-query { 192.168.1.0/24; 127.0.0.1; };
allow-transfer { 127.0.0.1; };
file "/etc/bind/pri/db.home.example.net";
};
zone "example.net" {
type master;
file "/etc/bind/pri/db.example.net";
allow-transfer { 127.0.0.1; 8.8.8.8; };
};
zone "example.com" {
type slave;
masters { 8.8.8.8; };
file "sec.example.com";
allow-transfer { 127.0.0.1; };
notify no;
};
zone "subdomain.of.example.nu" {
type slave;
masters { 8.8.8.8; };
file "sec.subdomain.of.example.nu";
allow-transfer { 127.0.0.1; };
notify no;
};
Beachten Sie den Kommentar „// Privat“ zu meinen ersten beiden Zonen. Ich verwende diesen im folgenden Skript, um sie aus der Liste der gültigen Zonen auszuschließen.
#!/usr/bin/perl
# zone2iptables - Richard Lithvall, april 2014
#
# Since we want to match not only example.net, but also (for example)
# www.example.net we need to set a reasonable maximum value for a domain
# name in our zones - 100 character should be more that enough for most people
# and 255 is the absolute maximum allowed in rfc1034.
# Set it to 0 (zero) if you would like the script to fetch each zone (axfr)
# to get the actual max value.
$maxLengthOfQueryName=255;
$externalInterface="eth1";
print "# first time you run this, you will get error on the 3 first commands.\n";
print "# It's here to make it safe/possible to periodically run this script.\n";
print "/sbin/iptables -D INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n";
print "/sbin/iptables -F DNSvalidate\n";
print "/sbin/iptables -X DNSvalidate\n";
print "#\n";
print "# now, create the chain (again)\n";
print "/sbin/iptables -N DNSvalidate\n";
print "# and populate it with your zones\n";
while(<>){
if(/^zone\s+"(.+)"\s+\{$/){
$zone=$1;
if($maxLengthOfQueryName){
$max=$maxLengthOfQueryName;
} else {
open(DIG,"dig -t axfr +nocmd +nostats $zone |");
$max=0;
while(<DIG>){
if(/^(.+?)\.\s/){
$max=(length($1)>$max)?length($1):$max;
}
}
close(DIG);
}
printf("iptables -A DNSvalidate -m string --from 40 --to %d --hex-string \"",($max+42));
foreach $subdomain (split('\.',$zone)){
printf("|%02X|%s",length($subdomain),$subdomain);
}
print("|00|\" --algo bm -j RETURN -m comment --comment \"$zone\"\n");
}
}
print "# and end the new chain with a drop\n";
print "/sbin/iptables -A DNSvalidate -j DROP\n";
print "# And, at last, make the new chain active (on UDP/53)\n";
print "/sbin/iptables -A INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n";
Führen Sie das obige Skript mit der Zonenkonfigurationsdatei als Argument aus.
root:~/tmp/# ./zone2iptables.pl /etc/bind/named.conf.local
# first time you run this, you will get error on the 3 first commands.
# It's here to make it safe/possible to periodically run this script.
/sbin/iptables -D INPUT -i eth1 -p udp --dport 53 -j DNSvalidate
/sbin/iptables -F DNSvalidate
/sbin/iptables -X DNSvalidate
#
# now, create the chain (again)
/sbin/iptables -N DNSvalidate
# and populate it with your zones
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|net|00|" --algo bm -j RETURN -m comment --comment "example.net"
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|com|00|" --algo bm -j RETURN -m comment --comment "example.com"
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|09|subdomain|02|of|07|example|02|nu|00|" --algo bm -j RETURN -m comment --comment "subdomain.of.example.nu"
# and end the new chain with a drop
/sbin/iptables -A DNSvalidate -j DROP
# And, at last, make the new chain active (on UDP/53)
/sbin/iptables -A INPUT -i eth1 -p udp --dport 53 -j DNSvalidate
Speichern Sie die Ausgabe in einem Skript, leiten Sie sie an eine Shell weiter oder kopieren Sie sie und fügen Sie sie in Ihr Terminal ein, um die neue Kette zu erstellen und alle ungültigen DNS-Abfragen herauszufiltern.
Führen Sie / sbin / iptables -L DNSvalidate -nvx aus
, um die Paket- (und Byte-) Zähler für jede Regel in der neuen Kette anzuzeigen (möglicherweise möchten Sie die Zone mit den meisten Paketen an den Anfang der Liste verschieben, um sie effizienter zu gestalten).
In der Hoffnung, dass jemand dies nützlich finden könnte :)