Response rate limiting pod drobnohledem

O RRL již krátce psal Ondřej Surý v článku Ochrana obětí před DNS amplification útoky, tak tedy jen v rychlosti oč se jedná. RRL je jedna z metod, jak se poprat s amplifikačními útoky na DNS, která shlukuje podobné odpovědi do tříd a následně omezuje rychlost toku odpovědí v pro danou třídu. Jedná se v podstatě o opak filtrování dotazů na firewallu a výhodou je právě třeba identifikace různých dotazů vedoucí na podobnou odpověď, typicky na neexistující jméno. RRL v současné chvíli implementuje BIND9/10, NSD od verze 3.2.15 a Knot DNS od verze 1.2.0-rc3.

Vzhledem k tomu, že v současné chvíli není tento mechanismus nijak standardizován, každá implementace se chová mírně odlišně. Podívejme se trochu blíže na tři nejzajímavější rozdíly a to, jaký vliv mají na chování serveru pod útokem.

Základní časovou jednotkou pro měření rychlosti toku je vteřina, pro kterou do každé třídy přibyde počet tokenů odpovídající povolené rychlosti. S každou odpovědí se pak token odebírá, a pokud už jsme vše vyčerpali, odpověď zahazujeme. BIND9 k tomu navíc zavádí ještě jedno „makro okno“, které průměruje rychlost toku pro několik následujících vteřin. Zásadním rozdílem je, že v rámci tohoto okna se může počet dostupných tokenů snížit do záporných hodnot, a tím vyčerpat kapacitu pro celý zbytek okna. Jestli je například okno dlouhé 5 vteřin, limit je 10 odpovědí za vteřinu a v první vteřině přijde 50 podobných dotazů, tak následující 4 vteřiny nebude podobné dotazy zodpovídat. Knot DNS ani NSD takový koncept nemají, dá se tedy říct že délka časového okna je 1s. Důvodem je větší férovost odezvy, každá vteřina začíná s čistým štítem, avšak za cenu menší agresivity potlačení nárazových toků.

Co ale dělat v případě, že přijde legitimní dotaz v době, kdy byl vyčerpán počet tokenů? Úplně jej zahodit? Takový dotaz jen velmi těžko rozlišíme od útoku, ale přesto bychom měli dát legitimnímu tazateli možnost získat odpověď a ne jej úplně odstřihnout. Místo toho, aby tedy server dotaz zcela ignoroval, tak odešle prázdnou odpověď s nastaveným TrunCated bitem v hlavičce. Tazatel je pak nucen opakovat dotaz po TCP, na který už dostane odpověď. Takovému mechanismu se říká SLIP (podporují ho všechny implementace). Knot DNS se odlišuje tím, že má počítadlo pro každé vlákno zvlášť, a pro menší rychlost toku není tak přesný. Během testování se ale nepřesnost nijak zvlášť neprojevila a největší vliv má konzervativní výchozí nastavení.

dknight_rrl_measurement
(Zdroj: Comparison of RRL behaviour in BIND9, Knot DNS, and NSD, Dave Knight, DNS-OARC Spring 2013)

Třetí zásadní odlišností je způsob klasifikace odpovědí. Technické memo a BIND9 klasifikují odpověď pomocí:

  • Zdrojové adresy (podsítě)
  • Dotazovaného jména (nebo zóny v případě chyb, nadřazeného jména pokud je odpověď pokrytá wildcardem)
  • Návratové hodnoty (RCODE)

NSD navíc rozlišuje několik podtříd dotazu, např. pokud je dotaz na typ ANY, Knot DNS dotazy navíc ještě klasifikuje podle velikosti. Všechny současné implementace jsou založené na hash tabulkách. Liší se ale výrazně v tom, jakým způsobem řeší kolize. Implementace v BIND9 je založená na přeplňování tabulek, přičemž kolidující klíče se řetězí za sebe (do omezeného počtu). A právě o kolizích probíhala na mailinglistu RRL dost živá diskuze. Abych to vysvětlil, řetězení dobře řeší kolize pokud je zdrojová podsíť různá, ale pořád zůstává možnost kolize hashe dotazovaného jména, které se neukládá celé. Nově ale zavádí potenciální problém, a to že útočníkovi do určité míry možnost kontrolovat množství alokované paměti pro tabulku a ztrácí výkon na procházení zřetězených hodnot.

NSD používá tabulku pevné velikosti, bez řetězení. Netrpí tedy na výše popsané problémy, ale s větší pravděpodobností umožňuje útočníkovi předem spočítat kolidující odpovědi (Birthday attack) v závislosti na velikosti tabulky. Protože není kolize kam řetězit, tak pro danou třídu resetuje počet tokenů, což sice na jednu stranu vylučuje riziko omezení kolidujících odpovědí, ale umožňuje při nalezení dvou kolidujících dotazů rate limiting zcela obejít.

Knot DNS využívá hopscotch hashing, který je velmi dobrým kompromisem s nízkou pravděpodobností kolize (1/32!) při zachování pevné velikosti. Zároveň do klíče přidává náhodně generované tajemství pro znesnadnění predikce kolizí a umožní jen jeden reset počítadla třídy za vteřinu.

rrl_effective

Ze zatím dostupných měření na reálných datech vyplývá, že chování všech implementací je i přes popsané rozdíly velmi podobné a liší se především citlivostí u pomalého toku dotazů. Hlavním omezením metody založené na rate limitingu je především nemožnost rozlišit právoplatný dotaz od útoku, což ale při rozumné spolehlivosti není ani prakticky možné. Příliš agresivní omezení by tak mohlo vést k přílišnému zahazování právoplatných dotazů, konzervativní zase k nižší účinnosti. BIND9 doporučuje agresivnější nastavení, Knot DNS je spolu s NSD spíše na konzervativní straně (RRL ve výchozím nastavení vypnuté, v dokumentaci 50 r/s).

Marek Vavruša

Quo vadis Knot DNS?

Uběhl téměř rok od doby, kdy z Laboratoří CZ.NIC vyšla první ostrá verze autoritativního DNS serveru Knot DNS. Kde všude běží a co na něj říkají uživatelé?

Začátky byly skromné, o to více nás proto potěšil zájem komunity, která se nám stará o balíčky a porty. Můžete nás najít například v linuxových distribucích Ubuntu, Fedora, Gentoo a openSUSE. Co se BSD balíčků a portů týče, tak FreeBSD a NetBSD. Zároveň nás velmi potěšilo zařazení do programu Coverity Scan, nástroje pro statickou analýzu kódu, která je pro open-source software zcela zdarma. Statická analýza nám pomohla odhalit několik zajímavých chyb a přispěla tak celkově ke zkvalitnění kódu.

Ale zpět k uživatelům. Prvním velkým nasazením byly domény CZ.NICu. První vlaštovkou byla doména knot-dns.cz, později se přidávaly další a nakonec i samotná doména .cz, kde Knot DNS můžete najít v anycastovém uzlu. Počáteční problémy nám byly neocenitelnou zpětnou vazbou a napomohly k odladění řady chyb. Přestože byl Knot DNS původně zaměřen pro větší TLD, našel si cestu i k hostingovým společnostem a jednotlivcům. Z českých mohu zmínit například společnosti HOSTING90 a igloonet.

Naším nejnovějším velkým přírůstkem v zahraničí je dánská .dk doména, kde se Knot DNS zatím zdárně rozbíhá :). V experimentálním provozu server kořenové zóny L-root a ruská .ru doména. U kořenové zóny se projevil problém s nedostatečnou kompresí jmen mimo zónu, do odpovědi se tak bez EDNS0 nevešla část záznamů v Additionals sekci. Tento problém byl již odstraněn, snad se tedy dostane do ostrého provozu. Nejčastěji si pak uživatelé chválí jednoduchost, rychlost a také možnost přidávat a odebírat zóny za běhu. Co naopak doposud chybělo, je DDNS, jednoduché statistiky a možnost vzdáleného ovládání.

A co máme v plánu do budoucna? K Vánocům vám nadělíme verzi 1.2, která přinese podporu pro DDNS a po novém roce dlouho chystanou verzi s optimalizovanou spotřebou paměti, novou ovládací utilitou a bleskurychlým načítáním zón.

Marek Vavruša

Test dnes: jak si vedl Knot DNS

Při příležitosti nedávné prezentace Knot DNS na Tech26 (CENTR Jamboree) jsme aktualizovali metodiku měření a chtěli bychom se podělit o nové výsledky.

Testování nyní proběhlo na syntetické zóně se zastoupením podporovaných RR typů na testovaných serverech (Knot DNS, BIND 9, NSD 3 a YADIFA[*]). Zóna obsahuje 1 324 899 záznamů, velikost zónového souboru je 76MB. Zároveň byly aktualizované testovací sady dotazů, které se nyní skládají z dotazů jak na existující, tak neexistující jména v poměru 1:1. Důvodem bylo prověřit výkon datových struktur serveru i při vyhledávání neexistujících jmen. Existující jména byla vybrána náhodným způsobem z tohoto zónového souboru. Konfigurace, zónový soubor, testovací sada pro program dnsperf (1 000 000 dotazů, 18MB) i syntetický provoz ve formátu pcap (50 000 dotazů, 4,2MB) jsou včetně dalších nástrojů volně ke stažení v Git repozitáři.

Prvním testem je škálovatelnost, kdy se měří závislost výkonu serveru na počtu spuštěných vláken/procesů. Výkon serveru je měřen programem dnsperf od společnosti Nominum. Tento test je specificky navržen pro měření výkonnosti autoritativních DNS serverů a mezi jeho přednosti patří regulace rychlosti dotazování, čímž poměrně věrně simuluje reálný síťový provoz. Jak je z grafu pro Linux patrné, podařilo se nám oproti verzi 1.0.3 vyřešit problém s plánováním vláken a nyní téměř dosahujeme naměřené propustnosti sítě. Ta byla změřena utilitou trafgen s malými UDP pakety (payload 60B) a zanesena do grafu. V případě tohoto testu nebylo možné určit u serveru Yadifa zadaný počet vláken, proto běží stále ve výchozím nastavení.


K testu škálovatelnosti nám přibyl nový test, který měří závislost podílu zodpovězených dotazů na rychlosti odesílaných odpovědí. Tento test byl dříve použit např. pro měření výkonnosti serveru NSD nebo nově Yadifa. V tomto testu figurují všechny tři stroje, kdy na prvním běží testovaný server, druhý pouze generuje provoz zadanou rychlostí a třetí zachytává odpovědi ze serveru. Pro testování byly využity standardní nástroje tcpreplaytcpdump. Ze získaných dat se vypočte procento zodpovězených dotazů pro danou rychlost. Každý test je třikrát opakován a jako výsledek se počítá průměrná hodnota. Z grafu je patrné, že Knot DNS 1.0.6rc1 i na Linuxu zodpověděl téměř všechny všechny dotazy zaslané maximální dosažitelnou rychlostí.

Samotné testování probíhalo na třech shodných strojích osazených procesorem Intel Xeon X3430 a 2GB RAM, propojených 1Gb ethernet linkou se síťovými kartami Broadcom BCM5723. První stroj slouží k běhu serveru, druhý ke generování dotazů a třetí k zachytávání odpovědí. Testy byly prováděny na 64bit OS Linux 3.0.0 a FreeBSD-8.2. V současné době je výkon omezen dosaženou propustností sítě, nicméně chystáme testování s rychlejší síťovou kartou a věříme, že je ještě prostor pro další zlepšení.

Marek Vavruša

* – Yadifa bohužel podporuje jen omezenou sadu RR typů, nicméně pro tento druh testování to nevadí