bind: blackhole для недійсних рекурсивних запитів?


13

У мене є сервер імен, який є загальнодоступним, оскільки це авторитетний сервер імен для пари доменів .

Наразі сервер ANYзаповнений фальшивими запитами типу isc.org, ripe.net тощо (це відома розподілена DoS-атака ).

Сервер працює BIND і allow-recursionвстановив мою локальну мережу, щоб ці запити були відхилені. У таких випадках сервер відповідає тільки з authorityі additionalсекції з посиланням на кореневі сервери.

Чи можу я налаштувати BIND так, щоб він повністю ігнорував ці запити, не надсилаючи відповіді взагалі?

Відповіді:


5

Зіткнувшись з тією ж проблемою, я вирішив ігнорувати всі рекурсивні запити. Усі вирішальні пристрої надсилають нерекурсивний запит, коли хочуть використовувати мій сервер як авторитетний сервер. Лише неправильно налаштовані клієнти та зловмисники, в моєму випадку, використовують рекурсивні запити.

На жаль, я не знайшов способу дозволити BIND це зробити, але у випадку, коли iptables для вас достатньо хороший, я використовував

iptables -t raw -I PREROUTING -i eth0 -p udp --destination-port 53 \
    -m string --algo kmp --from 30 \
    --hex-string "|01000001000000000000|" -j DROP

Ні, це правило блокує також запити авторитетного типу (принаймні на моїй машині). Мабуть, він блокує всі види запитів DNS.
Udo G

Я двічі перевірив і використовую саме це правило. Ось вирізання та вставка з прямого сервера. Команда: iptables -t raw -S PREROUTING. Вихід: з -P PREROUTING ACCEPTнаступним -A PREROUTING -i eth0 -p udp -m udp --dport 53 -m string --hex-string "|01000001000000000000|" --algo kmp --from 30 --to 65535 -j DROP. Я перевірив, що він працює правильно host -ar exampledomain.com dns-server.example.net. Звичайно, це не спрацювало правильно, поки я не додав -rваріант.
pino42

Гаразд, -rваріант має значення. Мені особисто не подобається, що прості hostзапити більше не працюють, і це може бути дуже заплутано. Це, мабуть, дійсна (найкраща поки що) відповідь, і я дам вам нагороду, оскільки це закінчиться, навіть якщо я продовжую використовувати власний підхід, фільтруючи вихід.
Udo G

Спасибі! Якщо я натрапляю на краще рішення, я обов’язково опублікую його. Я з вами згоден: цей хак. Працюючий, але все-таки хак.
pino42

2

Я б спробував:

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

Відповіді, що спрямовують клієнтів на кореневі сервери, контролюються зоною "переадресація". Це повинно сказати йому не відповідати на них.

На це натякають документи Bind9: http://ftp.isc.org/isc/bind9/cur/9.9/doc/arm/Bv9ARM.ch06.html#id2592674

Ви можете замінити "none"свою локальну підмережу.

Якщо у вас вже є zone "."декларація, просто додайте allow-query "none";її.


У мене є zone "." { type hint; file "/etc/bind/db.root"; };декларація з db.root із зазначенням кореневих серверів. Видалення цієї декларації зупиняє анвер для іноземних доменів, але сервер все-таки реагує на "помилку сервера" і, таким чином, все ще може використовуватися для DoS.
Udo G

@UdoG: Ви спробували додати allow-query "none";до zone "."конфігурації?
freiheit

Схоже, це лише економія пропускної здатності вгору за течією, хоча цього має бути багато.
Здійснюючи

@TheLQ: Питання стосується того, що це DDoS-атака. Поширена DDoS-атака на основі DNS - це надсилання DNS-запитів із підробленим IP-адресою цілі. Оскільки пакет відповідей DNS більший за запит, він забезпечує множник. Якщо ваш сервер не відповідає значно більшим пакетом, ви усунули причину, коли вони використовують ваш сервер в атаці.
freiheit

@UdoG: Пакет відмов сервера становить лише 31 до 32, тоді як направлення до кореневих серверів, ймовірно, було кілька сотень байт. Якщо відповідь вашого сервера має той самий розмір, що і запит, або лише на трохи менший розмір, ваш сервер виявляється марним при атаці DNS DDoS, оскільки зловмисники будуть споживати стільки пропускної здатності, скільки вони змусять вас відправити їх до своєї цілі. Я протестував на ряді ймовірних добре налаштованих авторитетних серверів імен (таких як google), і вони відповіли "рекурсія запитується, але недоступна".
freiheit

1

Як правило, я б запропонував:

Увімкніть журнали прив’язки та запишіть ips, на який буде відхилена відповідь. Встановіть програму fail2ban, додайте дію blackhole: http://pastebin.com/k4BxrAeG (покласти правило у файл у /etc/fail2ban/action.d)

Створіть файл фільтрів у /etc/fail2ban/filter.d з чимось подібним (потрібна налагодження!)

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

Редагувати fail2ban.conf, додати розділ:

[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

Сподіваюся, це допоможе!


TODO: прив'яжіть приклад файлу журналу.
Андрій Михальцов

1

Основна ідея дозволить прив’язати класифікувати відповідь DNS як відмовлену, а потім використовувати iptables для перетворення Refused в мовчазне ігнорування.

У розділі з параметрами named.conf відмовлено - це проста частина:

allow-recursion { none;};

Або звичайно ваші улюблені ACL для місцевих винятків ...

Далі божевільні iptables зачаровують, коригують або видаляють "-o eth0" за потребою. Ця команда передбачає стандартний 20-байтний заголовок IPv4 шару перед UDP.

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

Це клавіші у полі прапорців DNS-відповіді із наступними бітами

  • Відповідь DNS
  • Рекурсивний запит
  • Код відповіді відхилено

Помічене повідомлення журналу запущене, прив'язуйте до налагодження "помилка надсилання відповіді: хост недоступний", коли правило відповідає деяким відгукам для тестування.

Потрібно визнати, що це все дещо безглуздо. Якщо немає посилення, зловмисник може так само легко відображати TCP SYN. Зрештою, DNS просто не може бути прийнятним, крім використання TCP або розгортання файлів cookie DNS Eastlake.


0

Ви намагалися заблокувати рядок isc.org або заблокувати шістнадцяткову рядок для нього?

Це працювало для мене:

iptables -A INPUT -p string udp -m --hex-string "| 03697363036f726700 |" --algo bm -j ДРОП


Хіба не було б краще визначити шістнадцяткові рядки для всіх доменів, на які повинен відповідати сервер, зробіть вище, щоб дозволити їх, і відкиньте всі інші udp / 53 trafic?
freiheit

Наразі я вже блокую відповіді UDP, які посилаються на кореневі сервери: iptables -A OUTPUT -p udp -m string -hex-string "|726f6f742d73657276657273|" –algo bm –to 65535 -j DROPале я дійсно вважаю за краще рішення, яке базується лише на конфігурації BIND, якщо це можливо взагалі.
Udo G

це слабко. ви можете генерувати будь-яке жало, яке ви хочете, як домен. ми стикаємося з цією проблемою прямо зараз, і це не спосіб блокувати її за допомогою статичної назви'bnrexex.www.sf97.net/A/IN' 'whzpkacpxpiuycm.www.tpa.net.cn/A/IN'
3h4x

0

Ця атака називається посиленою відмовою у службі. Ви повинні налаштувати прив’язку належним чином, але цей трафік не повинен дотягуватись до вашого прив'язки. Заблокуйте його на першому мережевому пристрої, який здатний робити це у вашій мережі. У мене була така ж проблема, і я вирішував її з глухим правилом:

сигнал udp $ EXTERNAL_NET any -> $ HOME_NET 53 (msg: "PROTOCOL-DNS надмірні запити типу ANY - потенційний DoS"; byte_test: 1,! &, 0xF8,2; content: "| 00 00 FF 00 01 |"; dete_filter: трек by_src, кількість 30, секунди 30; метадані: service dns; довідка: URL, foxpa.ws / 2010/07/21 / thwarting-the-isc-org-dns-ddos /; classtype: спроба-dos; sid : 21817; rev: 4;)


0

По-перше, я знаю, що це старе питання, але ...

Я працював на власному авторитетному, не рекурсивному сервері DNS протягом десятиліть, але ніколи не став жертвою жодної DDoS-атаки на основі DNS - дотепер, коли я перейшов на новий провайдер. Тисячі підроблених запитів DNS заполонили мої журнали, і я справді роздратувався - не стільки щодо впливу на мій сервер, скоріше того, що воно захарастило мої журнали та незручне відчуття зловживання. Здається, що зловмисник намагається використовувати мій DNS в атаці " Авторитетний сервер імен ".

Тому я зрозумів, що, хоча я обмежую рекурсивні запити у своїй внутрішній мережі (заперечуючи всі інші), я швидше витрачаю свої цикли процесора на відповідність рядків у iptables, ніж на надсилання негативних відповідей на підроблені IP-адреси (менше захаращування в моїх журналах, менше мережевий трафік та більш високий рівень власної задоволеності).

Я почав, роблячи так, як це роблять всі інші , з'ясовуючи, які доменні імена запитуються, і створив відповідність рядка для цього домену з цільовим DROP. Але незабаром я зрозумів, що закінчу величезну кількість правил, кожен з яких вимагає циклу процесора. Отже, що робити? Оскільки я не запускаю рекурсивний сервер імен, я зрозумів, що я можу виконати відповідність у фактичних зонах, для яких я авторитетний, і відкинути все інше.

Моя політика за замовчуванням в iptables - це ACCEPT, якщо ваша політика DROP, вам, ймовірно, потрібно внести деякі коригування, якщо ви хочете використовувати наступне рішення.

Я зберігаю свою конфігурацію зони в окремому файлі (/etc/bind/named.conf.local), давайте скористаємося цим як приклад:

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

Зверніть увагу на "// Приватний" коментар до моїх перших двох зон, я використовую це в наступному сценарії, щоб виключити їх зі списку дійсних зон.

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

Запустіть вищезазначений скрипт з файлом конфігурації зони як аргументом.

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

Збережіть вихідний скрипт, передайте його в оболонку або скопіюйте та вставте його у свій термінал, щоб створити нову ланцюжок і почати фільтрувати всі недійсні запити DNS.

запустіть / sbin / iptables -L DNSvalidate -nvx, щоб побачити лічильники пакетів (і байтів) кожного правила в новому ланцюжку (ви можете перенести зону з більшістю пакетів у верхню частину списку, щоб зробити її більш ефективною).

У надії, що хтось може виявити це корисним :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.