Saturday, May 8, 2010

Iptables - bezpieczna konfiguracja reguł dla DNS

Usługa DNS wymaga osobliwego spojrzenia jeżeli chodzi o jej bezpieczeństwo. Jest też specyficzna i wyjątkowa w swoim rodzaju. Niemal jak w łańcuchu pokarmowym zwierząt serwer DNS w usługach sieciowych stanowi pierwsze ogniwo dla większości usług.

Z punktu widzenia bezpieczeństwa protokół DNS oraz serwery tej usługi są dość wymagające. Po pierwsze używają protokołu transportowego UDP, który nie wymaga nawiązania sesji między klientem a serwerem. Po drugie są bardzo podatne na ataki ponieważ protokół DNS był projektowany w czasach gdy jeszcze nie było takiego zagrożenia jak teraz dla sieci. Obecnie trwają prace nad aktualizacja protokołu DNS na DNSSEC obsługujący szyfrowaną autoryzację [1]. Nawet systemy aktywnego przeciwdziałania, czyli systemy IPS nie działające w trybie inline są bezradne. Przedstawiony system IPS zaimplementowany i opisany wcześniej na łamach mojego bloga nie ma żadnych szans w obronie przed atakiem typu DoS na lokalny serwer DNS.
Aby zrozumieć specyfikę ataku i możliwości obrony podam przykład takiego ataku: http://bugs.debian.org/cgi-bin/bugre...g=5;bug=538975

Przykład ten wykorzystuje błąd serwera. Obrona przed nim jest trudna, ponieważ cały atak wymaga przesłania tylko jednego pakietu UDP, czyli gdyby system IPS outline nawet wykrył ten atak było by już za późno na jakąkolwiek interakcję.
Iptables mógłby wcielić się w rolę systemu IPS inline i przy użyciu np. modułu string zablokować opisane pakiety. Niemniej jednak atak musi być dobrze znany, a opisanie nie będzie zbyt problematyczne. Wydaje im się, że rozwiązaniem tego problemu będzie nieco inna strategia niż 'ściganie przestępcy'. Lepszym rozwiązaniem będzie zbudowanie takich reguł, które ograniczą w logiczny sposób możliwe największa ilość ataków przy jednoczesnym zachowaniu maksymalnej wydajności zapory.
Złą informacją jest dla nas to, że atak na serwer DNS ma postać typu "one shot", dobrą to, że zawsze znamy adresy IP serwerów DNS wyższego poziomu, z których powinniśmy korzystać. Należy to wykorzystać.
Jeżeli Twoja reguła dotycząca usługi DNS wygląda mniej więcej tak:

iptables -A INPUT -p udp --dport 53 -j ACCEPT

to znaczy, że powinieneś uważnie przeczytać ten artykuł.

Wariantów jest dużo, ja opisuję tu przykład gdy na serwerze - bramie sieci prywatnej - znajduje się serwer DNS buforujący.

Logicznie najlepszym rozwiązaniem byłoby pozwalać na łączenie się tylko ze znanymi nam adresami IP serwerów DNS. Nawet bez uwzględniania portu 53/UDP w taki sposób zabezpieczamy nasz serwer przed skryptami ogólnie dostępnymi w sieci do wykonania ataku DoS. Napastnik musiałby sfałszować adres IP naszego serwera DNS wyższego poziomu aby pakiet się przedostał przez zaporę co nie jest trudnym zadaniem. Jednak takie rozwiązanie na sam początek jest na pewno drogą w dobrym kierunku, ogranicza w znacznym stopniu napastników tylko do tych, którzy znają adresy IP naszych DNS-ów. Dobrą wiadomością jest też to, że nie z wszystkich sieci sfałszowany pakiet się wydostanie, pod warunkiem, że ISP poprawnie skonfigurował routery. Nasz router również powinien być skonfigurowany w taki sposób aby nie przepuszczał pakietów z poza innej sieci niż naszych wewnętrznych.
Gdy ktoś się podszywa pod honorowane przez nas adresy prawie na 90% zostawi po tym ślad w pakiecie protokołu DNS. Możesz wyłapać dużą próbkę pakietów od swojego serwera DNS i wyszukać w nich wspólną cechę, może to być wartość TTL - ale nie zawsze musi być taka sam. Modułu u32 pakietu iptables, którego zadaniem jest testowanie wybranych bajtów może okazać się tu bardzo przydatny.

Kolejną kwestią wykorzystania DNS jest chociażby atak na wspomniany przeze mnie IPS w Pythonie. Prezentowałem w jaki sposób zablokować adres IP, z którego miało miejsce zbyt nadmierne w krótkim czasie logowanie do usługi SSH. Sprytny napastnik mógłby wykorzystać to na swoją korzyść. Wystarczyłoby aby podawał się za serwer DNS z którego korzystamy aby zablokować całą wewnętrzną sieć. Nasz IPS, który miał nasz chronić teraz zablokował by nam usługę DNS! Na szczęście sesję TCP, bo z takiej korzysta SSH nie tak łatwo podrobić, ale gdy byśmy blokowali inne połączenia korzystające z protokołu UDP byłoby to proste i możliwe. Na szczęście serwerów DNS zawsze mamy więcej niż jeden. Dlatego przed regułami wstawianymi przez skrypt IPS należy umieścić regułę, która zadba o to aby kontakt z naszymi serwerami wyższego poziomu nie został zerwany.

W końcu z pomocą mechanizmu pamięci stanów ograniczymy możliwości komunikacji dla protokołu tylko do niezbędnego minimum. Nasz serwer DNS buforujący najczęściej wysyła pakiet z zapytaniem do serwera nadrzędnego, czyli łańcuch OUTPUT. Możemy również ograniczyć te zapytania do tylko znanych nam adresów. Serwer wyższego poziomu odpowiada na zapytanie naszego serwera. Jest to odpowiedź na nasze zapytanie więc jądro takiemu pakietowi przypisze stan ESTABLISHED i oddzielna reguła przepuszczająca pakiety z portu 53/UDP w łańcuchu INPUT staje jest zbędna. Datagramy UDP z protokołem DNS zawierającym odpowiedź przepuści reguła zezwalająca na połączenia już nawiązane.

Serwer DNS odbiera i odpowiada z portu 53/UDP, czasami również i 53/tcp ale bardzo rzadko - między serwerami gdy pakiety są bardzo duże podczas transferów stref oraz gdy odpowiedź serwera jest zbyt duża i wymaga buforowania. W standardowych przypadkach jednak nie ma to miejsca, chyba, że masz zapasowy (ang. secondary) serwer DNS.
Klient korzystający z usługi DNS używa portów dynamicznych UDP powyżej 1023.

Najlepszymi regułami powinny być więc takie:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -d [IP_SERWER_DNS_1] -p udp --dport 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -d [IP_SERWER_DNS_2] -p udp --dport 53 -m state --state NEW -j ACCEPT


Poza zwiększeniem bezpieczeństwa reguły te zwiększają wydajność zapory, ponieważ redukują ilość reguł zwłaszcza dla łańcucha INPUT. Łańcuch OUTPUT również możemy poddać optymalizacji usuwając warunek przeznaczenia (IP) dla pakietów wychodzących na port 53/UDP.
Jeżeli to konieczne powinieneś dodać jeszcze reguły dla portu 53/TCP w łańcuchu OUTPUT.

No comments:

Post a Comment