İlk olarak, bunun eski bir soru olduğunu biliyorum ama ...
Kendi yetkili, özyinelemeli olmayan DNS sunucumu onlarca yıldır çalıştırıyorum, ancak yeni bir ISS'ye geçtiğim zamana kadar hiçbir DNS tabanlı DDoS saldırısında kurban olmadım. Binlerce sahte DNS sorgusu günlüklerime su bastı ve gerçekten rahatsız oldum - sunucum üzerindeki etkisi hakkında çok fazla değil, daha çok günlüklerimi ve istismar edilen rahatsızlık hissini karıştırdı. Saldırganın DNS'imi “ Yetkili Ad Sunucusu saldırısı ” nda kullanmaya çalıştığı görülüyor .
Bu nedenle, iç ağımla özyinelemeli sorguları (diğerlerini reddederek) sınırlasam da, sahte döngülere (günlüklerimde daha az dağınıklık, daha az dağınıklık, daha az karışıklık) geri göndermek yerine iptables'daki iples eşleşmesine CPU döngülerimi harcadığımı düşündüm. ağ trafiği ve daha yüksek bir memnuniyet düzeyi).
Herkesin yaptığı gibi yaparak başladım , hangi etki alanı adlarının sorgulandığını bulun ve bu etki alanında hedef DROP ile bir dize eşleşmesi oluşturdum. Ama çok geçmeden fark ettim ki, her biri CPU döngüsü tüketen çok sayıda kuralla karşılaşacağım. Peki ne yapmalı? Özyinelemeli bir ad sunucusu çalıştırmadığım için, yetkili olduğum gerçek bölgelerdeki eşleştirmeyi yapabileceğimi ve diğer her şeyi bırakabileceğimi düşündüm.
Iptables'daki varsayılan politikam KABUL EDİYOR, politikanız DROP ise, aşağıdaki çözümü kullanmak istiyorsanız muhtemelen bazı ayarlamalar yapmanız gerekir.
Bölge yapılandırmamı ayrı bir dosyada (/etc/bind/named.conf.local) saklıyorum, bunu örnek olarak kullanalım:
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;
};
İlk iki bölgemdeki “// Private” yorumuna dikkat edin, bunları aşağıdaki kodlarda geçerli bölgeler listesinden çıkarmak için kullanıyorum.
#!/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";
Yukarıdaki komut dosyasını bölge yapılandırma dosyasıyla bağımsız değişken olarak çalıştırın.
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
Çıkışı bir komut dosyasına kaydedin, bir kabuğa ekleyin veya yeni zinciri oluşturmak ve tüm geçersiz DNS sorgularını filtrelemeye başlamak için terminalinize kopyalayıp yapıştırın.
yeni zincirdeki her kuralda paket (ve bayt) sayaçlarını görmek için / sbin / iptables -L DNSvalidate -nvx komutunu çalıştırın (daha verimli hale getirmek için çoğu paket içeren bölgeyi listenin en üstüne taşımak isteyebilirsiniz).
Umarım birisi bunu faydalı bulabilir :)