Zapytania DNS
Zapytania ruchu DNS standardowo wysyłane są protokołem DNS na port 53. Jeśli klient ma ustawiony adres serwera publicznego np. Cloudflare 1.1.1.1 to ruch ten „przechodzi” przez nasz routrer (ja wszelki inny do Internetu). Zatem mamy możliwość przechwycenia takiego ruchu i skierowania go do lokalnego resolvera DNS celem zaszyfrowania połączeń do publicznych serwerów DNS. Rozwiązań jest wiele, tutaj opiszemy sposób RouterOS. Inne rozwiązania to PiHole, AdGuard, Technitium. Są to aplikacje (serwery) buforujące i szyfrujące DNS oraz blokujące niebezpieczne treści, reklamy itp.
Poniżej widok konfiguracji klienta DNS systemu Linux. Zazwyczaj mamy wpis jednego lub częściej dwóch adresów serwerów DNS w pliku /etc/resolv.conf
Standardowo zapytanie (zapewne nieszyfrowane) wygląda tak:
W tym przypadku Linux wysyła zapytania bezpośrednio do Cloudflare a jeśli nie otrzyma odpowiedzi to jeszcze spróbuje zapytać Google. Bezpośrednio w sensie DNS ale oczywiście taki ruch przejdzie przez nasz router.
Jeśli popatrzymy na połączenia to zobaczymy, że host 192.168.0.2 (Linux) łączy się z hostem 1.1.1.1 po UDP na port 53 czyli typowy ruch zapytań DNS. Nie jest on szyfrowany. Router teraz pracuje tylko jako router i żądnych usług DNS nie świadczy więc na razie ma się nijak do kwestii DNS a tym bardzie bezpieczeństwa tego ruchu.
Szyfrowanie ruchu DNS z routera
Jeśli na routerze skonfigurujemy szyfrowany ruch DNS do publicznych serwerów, włączymy lokalny serwer DNS buforujący i skonfigurujemy na kliencie adres resolvera na adres naszego routera to zabezpieczymy taki ruch DNS klienta. Teraz wyglądać to może tak:
Już nieco lepiej pod względem bezpieczeństwa. Pozostaje jednak problem: co jeśli nie mam dostępu do klientów? Jeśli to są zmieniające się w naszej sieci LAN laptopy czy urządzenia mobilne sprawę możemy załatwić opcją 6 serwera DHCP. W tym wypadku host kiedy uzyska adres IP z naszego DHCP otrzyma także adres serwera DNS i może nim być nasz RouterOS. Co jednak z hostami, które nie korzystają z DHCP? Co z hostami, na których użytkownicy samodzielnie mogą wprowadzać dowolne zmiany? Rozwiązaniem będzie blokada ruchu DNS i przekierowanie jej do naszego resolvera na RouterOS.
Nowa konfiguracja na kliencie:
Konfiguracja na RouterOS
Czyli klient zadaje pytanie DNS lokalnemu serwerowi (tutaj nasz RouterOS) a on w imieniu klienta zadaje pytanie publicznemu serwerowi DNS. Nadal nie jest ruch szyfrowany!
Ponownie popatrzmy na połączenia sieciowe
Od klienta do RouterOS po sieci LAN:
Teraz klient już nie wysyła zapytań DNS do publicznego serwera DNS ale do lokalnego, którym jest nasz router.
Od RouterOS do publicznego DNS po Internecie:
Router wysyła zapytanie DNS do serwera Google (bo taki został mu wcześniej ustawiony) na port 53 ptotokołu UDP i to też nie jest szyfrowane. Włączymy teraz szybko szyfrowanie tego ruchu:
Dla pewności wyczyścimy bufor DNS (przycisk Cache)
Z klienta ponownie zadamy zapytanie DNS i patrzymy na połączenia od strony WAN:
Jak widać teraz router zadaje pytanie do Cloudflare (1.1.1.1) ale jest ono już w postaci zaszyfrowanej. Więcej tutaj.
Uwaga: samo włączenie tego szyfrowania nie powoduje, że wszystkie hosty będą z niego korzystać. Mogą ale nie muszą. Jeśli na naszym Linux ponownie zmienimy DNS na np. 1.1.1.1 to połączenia DNS będą realizowane w sposób nieszyfrowany. Zmieniamy zatem wpis w /etc/resolv.con na:
Sprawdź samodzielnie jak wyglądają teraz połączenia z RouterOS i z Linux. Co najważniejsze można zadawać pytania i uzyskiwać odpowiedź z publicznego DNS. Zaraz zrobimy tak, że to nie będzie możliwe.
Blokada i przekierowanie ruchu DNS
Załóżmy, że na Linux nie mamy oprogramowania szyfrującego ruch DNS ale chcemy takowe rozwiązanie wdrożyć. Mało tego: chcemy aby każdy host nie mógł bezpośrednio, bez szyfrowania zadawać pytań do publicznych serwerów DNS. Przygotujemy zatem szyfrowanie ruchu DNS na naszym routerze (RouterOS), zablokujemy ruch DNS z LAN do WAN i ustawimy przekierowanie zapytań DNS. Będzie ono działało tak, że kiedy klient wyśle zapytanie o adres IP nazwy domenowej do publicznego serwera nasz RouterOS przechwyci je, zablokuje i przekieruje do swojego wewnętrznego resolvera. A ten zada pytanie publicznemu DNS ale w sposób już szyfrowany.
Blokada połączeń DNS przechodzących przez router
Taką blokadę ustawimy na łańcuchu forward routera. Poniżej przykład z konsoli.
# /ip firewall filter add action=drop chain=forward dst-port=53 protocol=udp
To bardzo ogólna reguła i zabrania ruchu UDP docelowy port 53 w obie strony na routerze. Możemy ją doprecyzować zabraniając tylko ruchu z LAN do WAN czy inaczej.
Schemat działania teraz mamy taki:
Sprawdzimy teraz co z zapytaniami. Na Linux wydajemy polecenie ping www.wp.pl, na RouterOS obserwujemy połączenia:
z LAN brak połączeń:
Firewall reguła #1 złapała jakieś pakiety i zablokowała je ponieważ były to pakiety UDP cel port 53 przechodzące (forward) przez router:
Zatem teraz nikt z sieci LAN nie skorzysta z publicznego DNS po standardowym połączeniu (UDP/53). Adres IP serwera DNS nie jest istotny, wycięliśmy ruch na bazie protokołu i portu. Oczywiście jest teraz klient zapyta o nazwę DNS bezpośrednio nasz router to odpowiedź dostanie. Aby to zrobić trzeba na kliencie zmienić adres serwera DNS na 192.168.0.1 czyli interfejs LAN naszego routera. Ale na razie zostawmy naszą konfigurację, na Linux brak odpowiedzi na zapytanie DNS.
Przy okazji: w tej sytuacji koniecznie trzeba zabronić dostępu do DNS na RouterOS od strony WAN (tutaj ether1):
# /ip firewall filter add action=drop chain=input dst-port=53 in-interface=ether1 protocol=udp
Przekierowanie zapytań DNS
Teraz czas na wykonanie przekierowania: wszystko co z sieci LAN przechodzi (forward) przez nasz router i jest protokołem UDP na port docelowy 53 jest blokowane. Ten ruch „złapiemy” i przekierujemy do lokalnego resolvera działającego na RouterOS. Dzięki temu klient nawet jeśli będzie miał skonfigurowany adres publicznego DNS nie wspierającego szyfrowania dostanie odpowiedź z serwera lokalnego (nasz RouterOS). Ten z kolei zadaje pytanie zaszyfrowane do wybranego publicznego DNS.
Aby umożliwić automatyczne przekierowanie do lokalnego DNS uprzednio zablokowanego pytania dodamy nową regułę firewall do tablicy NAT
# /ip firewall nat add action=dst-nat chain=dstnat dst-port=53 in-interface=ether2 log=yes protocol=udp to-addresses=192.168.0.1 to-ports=53
Reguła ta przechwytuje ruch protokołu UDP na port 53 który wchodzi na interfejs ether2 i zamiast przekazać go do NAT celem wysłania do Internetu przekieruje na adres 192.168.0.1 port 53. Jest to oczywiście adres LAN naszego routera.
Schemat połączeń teraz wygląda tak:
Sprawdzamy z klienta czy działa:
W połączeniach widać:
Podsumowanie
Zablokowano ruch DNS przechodzący przez router, zablokowano zapytania DNS od strony WAN oraz przekierowano cały ruch DNS z sieci LAN do Internetu do lokalnego serwera DNS. Jak widać po regule firewall może to być dowolna maszyna w sieci LAN.