bind: blackhole dla nieprawidłowych zapytań rekurencyjnych?

13

Mam serwer nazw, który jest publicznie dostępny, ponieważ jest to autorytatywny serwer nazw dla kilku domen .

Obecnie serwer jest zalewany fałszywymi typami ANYżądań dla isc.org, mature.net i podobnych (jest to znany rozproszony atak DoS ).

Serwer uruchamia BIND i allow-recursionustawił na moją sieć LAN, więc te żądania są odrzucane. W takich przypadkach serwer odpowiada tylko sekcjami authorityi additionalsekcjami odnoszącymi się do serwerów głównych.

Czy mogę skonfigurować BIND, aby całkowicie ignorował te żądania, bez wysyłania odpowiedzi?

Udo G.
źródło

Odpowiedzi:

5

W obliczu tego samego problemu postanowiłem zignorować wszystkie rekurencyjne żądania. Wszystkie resolwery wysyłają nierekurencyjne zapytanie, gdy chcą użyć mojego serwera jako serwera autorytatywnego. Tylko źle skonfigurowani klienci i osoby atakujące, w moim przypadku, używają zapytań rekurencyjnych.

Niestety nie znalazłem sposobu, aby pozwolić BIND to zrobić, ale w przypadku, gdy iptables jest dla ciebie wystarczająco dobry, użyłem

iptables -t raw -I PREROUTING -i eth0 -p udp --destination-port 53 \
    -m string --algo kmp --from 30 \
    --hex-string "|01000001000000000000|" -j DROP
pino42
źródło
Nie, ta reguła blokuje również żądania typu autorytatywnego (przynajmniej na moim komputerze). Najwyraźniej blokuje wszystkie rodzaje żądań DNS.
Udo G
Sprawdziłem dwukrotnie i używam dokładnie tej reguły. Oto wycinanie i wklejanie z serwera na żywo. Polecenie: iptables -t raw -S PREROUTING. Dane wyjściowe:, -P PREROUTING ACCEPTa następnie -A PREROUTING -i eth0 -p udp -m udp --dport 53 -m string --hex-string "|01000001000000000000|" --algo kmp --from 30 --to 65535 -j DROP. Testowałem, czy działa poprawnie host -ar exampledomain.com dns-server.example.net. Oczywiście nie działało to poprawnie, dopóki nie dodałem -ropcji.
pino42,
OK, -ropcja robi różnicę. Osobiście nie podoba mi się to, że proste hostzapytania już nie działają i może to być bardzo mylące. Jest to prawdopodobnie prawidłowa (jak dotąd najlepsza) odpowiedź i dam ci nagrodę, ponieważ wkrótce wygaśnie, nawet jeśli nadal będę stosować własne podejście, filtrując WYJŚCIE.
Udo G
Dzięki! Jeśli wpadnę na lepsze rozwiązanie, postaram się je opublikować. Zgadzam się z tobą: ten jest hack. Działający, ale wciąż hack.
pino42,
2

Spróbowałbym:

zone "." {
  type redirect;
  allow-query "none";
}

Odpowiedzi kierujące klientów do serwerów głównych są kontrolowane przez strefę „przekierowania”. To powinno powiedzieć mu, żeby nie odpowiadał na nie.

Jest to wskazane w dokumentach Bind9: http://ftp.isc.org/isc/bind9/cur/9.9/doc/arm/Bv9ARM.ch06.html#id2592674

Możesz zastąpić "none"swoją lokalną podsiecią.

Jeśli masz już zone "."deklarację, po prostu dodaj allow-query "none";ją.

freiheit
źródło
Mam zone "." { type hint; file "/etc/bind/db.root"; };deklarację z db.root zawierającą listę serwerów głównych. Usunięcie tej deklaracji zatrzymuje odpowiedzi na obce domeny, ale serwer mimo to reaguje „awarią serwera” i dlatego może być nadal używany do DoS.
Udo G
@UdoG: Czy próbowałeś dodać allow-query "none";do zone "."konfiguracji?
freiheit
Wygląda na to, że oszczędza to tylko przepustowość w górę, co powinno być obfite. Po poprawce atakujący wykorzystał już przepustowość i moc obliczeniową serwerów
TheLQ,
@TheLQ: Pytanie dotyczy tego ataku DDoS. Typowym atakiem DDoS opartym na systemie DNS jest wysyłanie zapytań DNS z fałszywym adresem IP celu. Ponieważ pakiet odpowiedzi DNS jest większy niż zapytanie, zapewnia on mnożnik. Jeśli twój serwer nie odpowiada znacznie większym pakietem, wyeliminowałeś powód, dla którego używa on twojego serwera w ataku.
freiheit,
@UdoG: Pakiet awarii serwera ma tylko 31 do 32, podczas gdy skierowanie do serwerów głównych miało prawdopodobnie kilkaset bajtów. Jeśli odpowiedź twojego serwera jest tego samego rozmiaru co zapytanie lub tylko odrobinę większa, twój serwer jest bezużyteczny w ataku DNS DDoS, ponieważ osoby atakujące zużyją tyle pasma, ile dostaną, aby wysłać je do celu. Testowałem na wielu prawdopodobnie dobrze skonfigurowanych autorytatywnych serwerach nazw (takich jak Google), a oni odpowiedzieli „żądaniem rekurencji, ale niedostępnym”.
freiheit,
1

Ogólnie sugerowałbym:

Włącz dzienniki powiązań i zapisz IP, który zostanie odrzucony. Zainstaluj program fail2ban, dodaj akcję blackhole: http://pastebin.com/k4BxrAeG (umieść regułę w pliku w /etc/fail2ban/actions.d)

Utwórz plik filtra powiązań w /etc/fail2ban/filter.d z czymś takim (wymaga debugowania!)

[Definition]
failregex = ^.* security: info: client #<HOST>: query \(cache\) .* denied

Edytuj fail2ban.conf, dodaj sekcję:

[bindban]

enabled  = true
filter   = bind
# "bantime" is the number of seconds that a host is banned.
bantime  = 6000
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 60
# "maxretry" is the number of failures before a host get banned.
maxretry = 150
action   = blackhole
logpath  = /var/log/named.log

Mam nadzieję, że to pomoże!

Andriej Michałow
źródło
DO ZROBIENIA: przykład pliku dziennika powiązania.
Andrei Mikhaltsov,
1

Podstawowy pomysł pozwala powiązać klasyfikację odpowiedzi DNS jako odrzuconą, a następnie użyć iptables do konwersji odrzuconej na dyskretnie ignorowaną.

Odmowa jest łatwą częścią sekcji opcji named.conf:

allow-recursion { none;};

Lub oczywiście twoje ulubione listy ACL dla lokalnych wyjątków ...

Następnie zwariuj iptables, dostosuj lub usuń „-o eth0” w razie potrzeby. To polecenie zakłada standardowy 20-bajtowy nagłówek warstwy IPv4 przed UDP.

iptables -A OUTPUT -o eth0 -p udp --sport 53 -m string --from 30 --to 32 --hex-string "|8105|" --algo bm -j DROP

Ten klucz w polu flagi odpowiedzi DNS z ustawionymi następującymi bitami

  • Odpowiedź DNS
  • Zapytanie rekurencyjne
  • Odrzucono kod odpowiedzi

Zauważyłem komunikat dziennika z uruchomionym wiązaniem podczas debugowania „błąd podczas wysyłania odpowiedzi: host nieosiągalny”, gdy reguła pasuje, aby uzyskać informacje zwrotne do testowania.

Trzeba przyznać, że jest to trochę bezcelowe ćwiczenie. Jeśli nie ma wzmocnienia, atakujący może równie łatwo odzwierciedlić TCP SYN. Ostatecznie DNS jest zepsuty, po prostu nie ma realnego rozwiązania innego niż użycie TCP lub wdrożenie plików cookie DNS firmy Eastlake.

zjadacz dysku
źródło
0

Czy próbowałeś zablokować ciąg isc.org lub zablokować ciąg szesnastkowy?

To działało dla mnie:

iptables -A WEJŚCIE -p udp -m ciąg - hex-ciąg "| 03697363036f726700 |" --algo bm -j DROP

Klątwa
źródło
Czy nie byłoby lepiej zidentyfikować ciągi szesnastkowe dla wszystkich domen, na które serwer powinien odpowiadać, zrobić powyższe, aby na nie zezwolić, i porzucić cały inny ruch udp / 53?
freiheit,
Obecnie już blokuję odpowiedzi UDP odnoszące się do serwerów głównych: iptables -A OUTPUT -p udp -m string -hex-string "|726f6f742d73657276657273|" –algo bm –to 65535 -j DROPale naprawdę wolałbym rozwiązanie oparte tylko na konfiguracji BIND, jeśli to w ogóle możliwe.
Udo G
to jest słabe. możesz wygenerować dowolne żądło jako domenę. mamy teraz do czynienia z tym problemem i nie jest to sposób, aby go zablokować za pomocą nazwy statycznej'bnrexex.www.sf97.net/A/IN' 'whzpkacpxpiuycm.www.tpa.net.cn/A/IN'
godz. 4 godz.
0

Ten atak nazywa się Amplified Denial of Service. Powinieneś poprawnie skonfigurować powiązanie, ale ten ruch nie powinien dostać się do twojego powiązania. Zablokuj na pierwszym urządzeniu sieciowym, które może to zrobić w twojej sieci. Miałem ten sam problem i poradziłem sobie z nim z głuchą regułą prychnięcia:

alert udp $ EXTERNAL_NET dowolny -> $ HOME_NET 53 (msg: „PROTOCOL-DNS nadmierne zapytania typu DOWOLNY - potencjalny DoS”; test bajtowy: 1,! & 0xF8,2; treść: "| 00 00 FF 00 01 |"; detection_filter: track by_src, count 30, seconds 30; metadane: service dns; reference: url, foxpa.ws / 2010/07/21 / thwarting-the-isc-org-dns-ddos /; classtype: próba-dos; sid : 21817; rev: 4;)

3h4x
źródło
0

Po pierwsze wiem, że to stare pytanie, ale ...

Od dziesięcioleci prowadzę własny autorytatywny, nierekurencyjny serwer DNS, ale nigdy nie padłem ofiarą ataków DDoS opartych na DNS - do tej pory, kiedy przestawiłem się na nowego dostawcę usług internetowych. Tysiące sfałszowanych zapytań DNS zalało moje logi i bardzo mnie to zirytowało - nie tyle na temat wpływu na mój serwer, co raczej zaśmiecenie moich logów i niewygodne uczucie bycia wykorzystywanym. Wygląda na to, że atakujący próbuje użyć mojego DNS w „ autorytatywnym ataku na serwer nazw ”.

Pomyślałem więc, że chociaż ograniczam zapytania rekurencyjne do mojej sieci wewnętrznej (zaprzeczając wszystkim innym), wolę spędzać cykle procesora na dopasowywaniu ciągów znaków w iptables niż wysyłaniu negatywnych odpowiedzi na sfałszowane adresy IP (mniej bałaganu w moich logach, mniej ruch w sieci i mój własny wyższy poziom satysfakcji).

Zacząłem od zrobienia tego, co wszyscy inni robią , aby dowiedzieć się, które nazwy domen są wyszukiwane, i utworzyłem ciąg znaków w tej domenie z docelowym DROP. Ale wkrótce zdałem sobie sprawę, że skończy się z ogromną ilością reguł, z których każda pochłania cykle procesora. Co więc robić? Ponieważ nie prowadzę rekurencyjnego serwera nazw, pomyślałem, że mogę dopasować rzeczywiste strefy, dla których jestem autorytatywny, i porzucić wszystko inne.

Moją domyślną polityką w iptables jest AKCEPTUJ, jeśli twoją polisą jest DROP, prawdopodobnie musisz wprowadzić pewne zmiany, jeśli chcesz skorzystać z następującego rozwiązania.

Trzymam konfigurację strefy w osobnym pliku (/etc/bind/named.conf.local), wykorzystajmy to jako przykład:

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;
};

Zwróć uwagę na komentarz „// Private” do moich pierwszych dwóch stref. Korzystam z tego w poniższym skrypcie, aby wykluczyć je z listy prawidłowych stref.

#!/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";

Uruchom powyższy skrypt z plikiem konfiguracji strefy jako argumentem.

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

Zapisz dane wyjściowe w skrypcie, potokuj je do powłoki lub skopiuj i wklej w terminalu, aby utworzyć nowy łańcuch i rozpocząć filtrowanie wszystkich nieprawidłowych zapytań DNS.

uruchom / sbin / iptables -L DNSvalidate -nvx, aby zobaczyć liczniki pakietów (i bajtów) dla każdej reguły w nowym łańcuchu (możesz chcieć przenieść strefę z większością pakietów na górę listy, aby była bardziej wydajna).

Mam nadzieję, że ktoś może uznać to za przydatne :)

bogaty
źródło