dnsdist DNS loadbalancer

Какво е dnsdist

dnsdist е loadbalancer на DNS трафик който:

1. Оценява най бързо отговарящите DNS сървъри.
2. Следи за състоянието им, UP и DOWN.
3. Конфигурира натоварването между тях.
4. Филтрира или забавя DoS атаки.
5. Блокира домейни или определен трафик.
6. Кешира DNS записи за още по висока скорост.
7. и други, които не ми се изброяват сега 🙂

Защо dnsdist

Общо взето аз посегнах към dnsdist поради три причини:

Първата е скороста, скоростите на Интернет постоянно се вдигат, операторите непрекъснато го рекламират но никой от тях и дума не обелва за качество. Качеството на Интернет не е само скороста, защото какъв е смисъла ако имаш 1G Интернет когато имаш от време на време загуба на пакети, не можеш да направиш повече от 200-300 connection или пък не можеш да изпозлваш по големи пакети от 1360 MTU. Да предположим, че всички тези неща са наред но по някаква причина имаме DNS сървър който ни отговаря бавно (далече в Интернет е, претоварен е или е жертва на DoS атака). В подкрепа на всичко това е факта, че една част от потребителите сами си променят DNS сървърите (например на 8.8.8.8) като твърдят, че Интернета им е по бърз. Очевидно е, че трябва да има нещо безотказно, бързо, близо и кеширащо за да реши този проблем.

Втората причина е, че ми трябва интелигентен филтър както за запитванията за домейни, така и за отговорите им към потребителите. Голяма част от потребителите незнаят, че са “досери“, и че питат за някой несъществуващ поддмейн на Facebook 200 пъти в минута което си е една мини DoS атака. Плюс всичко това, по някой път се налага една група клиенти да получават различен отговор в DNS заявките (например вътрешен сървър в локалната мрежа).

Третата и не на последно място причина е статистиката, информацията която вади dnsdist с лекота е впечатляваща. Лесно може да се види кой е по по най в запитванията към pornhub например :), но по важното е, че тази статистика дава детайлна информация какво е състоянието на DNS услугата в един доставчик, услуга която повярваите ми често е меко казано занемарена.

Как работи dnsdist

В основата на терминологията на dnsdist са bаckеnd сървърите към които той проксира заявки за DNS записи. bаckеnd сървърите могат да бъдат както авторитарни така и рекурсори, тоест всички (Open DNS, Google DNS или локален сървър). dnsdist освен, че проксира, той може и да филтрира с команди които му задаваме ние, а така също и да кешира за да доставя по бързи отговори до клиентите на DNS услугата.

dnsdist автоматично следи състоянието и здравето на backend сървърите като ако някой отпадне веднага го маркира като DOWN и докато не стане пак UP го изключва от таблицата със заявките.

Черешката на тортата разбира се е loadbalancer-a. “Лоуд баланса” може да се извършва по предварително дефинирани политики а ако не конфигурираме такава той си създава по подарзбиране (default).
firstAvailble – изпраща заявки в секунда до достигане на QPS лимита.
wradnom – изпраща заявки на случаен принцип.
roundrobin – изпраща заявки конферентно (по равно).
LeastOutstanding – по подразбиране (заявки до най бързите backend сървъри).

dnsdist има собствена runtime конзола която ни позволява да изпълняваме директно команди с автоматично дописване в стил bash без да рестартираме демона и с това по някакъв начин да нарушаваме работата му.

Една от най трудните услуги за мониторинг е DNS, защото сървърите обслужват десетки хиляди заявки в секунда и ако трябва да се пишат детаилни логове за работата си които след това да се анализират ще отиде огромен ресурс, който вероятно ще консумира повече процесорно време за статистика отколкото за същественната си работа. dnsdist обаче е малката програмка която върши “голямата” работа в DNS – балансиране, кеширане и статистика в реално време.

dnsdist притежава и вгаден web сървър който показва моментни статистики в реално време и графика на заявките и натоварването.

Инсталация

В хранилището на Ubuntu 16.04 LTS, dnsdist е версия 1.0 alpha2, което силно не препоръчвам да се инсталира защото текущата версия в момента е 1.2 stable и за да я инсталираме от “репо-то” на powerdns ще изпълним следните команди.

Създаваме файл с sudo nano /etc/apt/sources.list.d/pdns.list и в него копираме.

deb [arch=amd64] http://repo.powerdns.com/ubuntu xenial-dnsdist-12 main

Същото правим и с sudo nano /etc/apt/preferences.d/dnsdist като в него копираме следното.

Package: dnsdist*
Pin: origin repo.powerdns.com
Pin-Priority: 600

След което изпълняваме:

curl https://repo.powerdns.com/FD380FBB-pub.asc | sudo apt-key add
sudo apt-get update
sudo apt-get install dnsdist

Конфигурация и стартиране на dnsdist

Копираме директивите в конфигурационния файл на dnsdist.
sudo nano /etc/dnsdist/dnsdist.conf

addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("[::]:53",{ doTCP=true, reusePort=true })
addACL("85.118.94.0/23")
addACL("88.203.248.0/22")
addACL("93.155.130.0/23")
addACL("93.155.162.0/24")
addACL("93.155.169.0/24")
addACL("2001:470:20f1::/48")
newServer({address="8.8.4.4", name="google", qps=10})
newServer({address="8.8.8.8", name="google", qps=10})
newServer({address="208.67.220.220", name="opendns", qps=10})
newServer({address="208.67.222.222", name="opendns", qps=10})
newServer({address="2001:470:20::2", name="he", qps=5})
newServer({address="2001:4860:4860::8888", name="google", qps=1})
setServerPolicy(firstAvailable)
pc = newPacketCache(1000000, 86400, 0, 60, 60)
getPool(""):setCache(pc)
webserver("0.0.0.0:8083", "qwerty")
controlSocket('127.0.0.1:5199')
setKey("qwerty")

Рестартираме demona за да влязат директивите в сила.

sudo systemctl restart dnsdist.service

Проверяваме дали се е стартирал демона.

sudo systemctl status dnsdist.service

Също може и с htop:

Работа в конзола с dnsdist

Вълшебната команда за работа в конзола е dnsdist -c изпълнена в bash терминала.

Най често използваната команда в конзола в dnsdist е showServers() която следи състоянието, заявките и балансирането на backend сървърите.

Ето още няколко команди които показват състоянието на DNS услугата в dnsdist.

Конфигурациони директиви в dnsdist

Броя на тредовете според ядрата на процесора, цялата конфигурация може да запали и само с един такъв ред, но ще изпозлва само един процесор. Тъй като машината има 4 ядра аз съм задал 4 реда. Първите три реда са 0.0.0.0:53 което значи, че демона ще слуша от всички IPv4 адреси на машината на 53 порт и ще използва 3 процесорни ядра. Четвъртия ред [::]:53 значи, че демона ще слуша от всички IPv6 адреси, на 53 порт, само на едно процесорно ядро.

addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("0.0.0.0:53",{ doTCP=true, reusePort=true })
addLocal("[::]:53",{ doTCP=true, reusePort=true })

ACL е директивата за access листа в dnsdist. По подразбиране приема всички от RFC1918 без да се описват (тоест 192.168.0.0/16, 172.16.0.0/12 и 10.0.0.0/8), останалите – обикновено публични ип адреси трябва да се добавят в аксес листата.

addACL("85.118.94.0/23")
addACL("88.203.248.0/22")
addACL("93.155.130.0/23")
addACL("93.155.162.0/24")
addACL("93.155.169.0/24")
addACL("2001:470:20f1::/48")

Backend сървърите без които не може да се изпълни конфигурацията. Може би вече някой се е запитал: -Каво е QPS “qps е queries per second” (заявки в секунда)

newServer({address="8.8.4.4", name="google", qps=10})
newServer({address="8.8.8.8", name="google", qps=10})
newServer({address="208.67.220.220", name="opendns", qps=10})
newServer({address="208.67.222.222", name="opendns", qps=10})
newServer({address="2001:470:20::2", name="he", qps=5})
newServer({address="2001:4860:4860::8888", name="google", qps=1})

Политика на балансиране.

setServerPolicy(firstAvailable)

Параметри за кеширане.

pc = newPacketCache(1000000, 86400, 0, 60, 60)
getPool(""):setCache(pc)

Web сървъра слуша на всички адреси на Линукс машината с който и да е потребител с парола “qwerty” на порт 8083.

webserver("0.0.0.0:8083", "qwerty")

Достъп до конзолата е възможна само от локалната машина 127.0.0.x.

controlSocket('127.0.0.1:5199')
setKey("qwerty")

Leave a Reply

Your email address will not be published. Required fields are marked *