Verejný DNS doma

DNS (Domain Name System) je systém, ktorý má za úlohu prekladať doménové mená na IP adresy (alebo opačne a vtedy sa mu hovorí reverzný DNS) . To znamená, že ak do web prehliadača zadáme www.example.com, tak DNS server (resp. resolver) nám oznámi že názov tohto webu máme hľadať na stroji z IP adresou 93.184.216.34. Podstata systému je veľmi jednoduchá, ale inak je to dosť komplikovaný systém.

Obsah

Úvod do DNS

Už na začiatku sme si povedali čo je hlavnou úlohou DNS serverov. V DNS funguje akási hierarchia pri dopytovaní sa konkrétneho mena (webovej adresy napr. example.com). DNS servery môžeme rozdeliť do štyroch kategórii.

  • Rekurzívny resolver
  • Koreňový DNS server
  • Menný server TLD
  • Autoritatívny DNS server

Veľmi pekný článok o DNS serveroch je popísaný na cloudfare blogu. DNS servery, resp. rekurzívne resolvery su denne bombardované miliardami požiadaviek, ktoré musia byť veľmi rýchlo vybavené. V minulom blogu som písal o tom ako si postaviť vlastnú certifikačnú autoritu s nástrojom mkcert a ako spoločnosť freenom zrušila zákazníkom TLD. Ja som sa rozhodol, že zrušené domény si ponechám, ale len v lokálnej sieti.

Nedávno ma však napadla myšlienka ako by som dostal túto doménu na verejný internet. Ako funguje DNS som už spomínal dávnejšie v tomto blogovom článku. Teraz som našiel na webe geeksforgeeks veľmi peknú animáciu ako funguje rekurzívne dopytovanie DNS.

Tu je stručný popis. 1. Bežný užívateľ zadáva do webového prehliadača url geeksforgeeks.org. 2. Požiadavka sa preverí, či je k nejakej lokálnej IP adrese pridelené toto meno (napr. v /etc/hosts), prehľadá cache prehliadača, DNS cache routera. Ak sa odpoveď nájde, tak je koniec a požiadavka je vyriešená. 3. Ak sa požiadavka nevyrieši ani v lokálnom resolvery, tak ďalej smeruje do resolvera ISP, alebo iného verejného resolvera, ktorý sme si nastavili. 4. Ak sa požiadavka nenájde ani v DB verejného resolvera, tak resolver kontaktuje jeden z 13 koreňových DNS serverov, ktorý je v hierarchii najvyššie a je zodpovedný za com, org, net a pod. Koreňový server nevie, kde sa nachádza geeksforgeeks.org, ale pozná IP adresy serverov, ktoré spravujú TLD .org. 5. Preto poskytne resolveru IP adresy ďalších DNS serverov ktoré spravuje TLD .org. 6. Resolver posiela požiadavku na DNS server zodpovedný za TLD .org. Avšak ani ten nepozná, kde sa nachádza geeksforgeeks.org, ale vie, ktoré nameserverý to vedia. 7. Čiže znova odpovie resolveru, aby sa pýtal nameservera, ktorý je zodpovedný za geeksforgeeks.org. 8. Resolver sa opýta DNS servera, ktorý je autoritatívny pre geeksforgeeks.org a ten ma v tabuľke k tejto doméne pridelenú IPv4, resp. IPv6 adresu. 9. Nameserver odpovedá resolveru, že k doméne geeksforgeeks.org je pridelená IP adresa 34.218.62.116. 10. Resolver si údaj u seba uloží (časový interval uloženia závisí od nastaveného TTL) a konečne odpovie užívateľovi (resp. lokálnemu resolveru a následne webovému prehliadaču), že geeksforgeeks.org je na IP adrese 34.218.62.116. 11. a 12. Začne prebiehať medzi reálnym serverom a klientom komunikácia.

Toto bolo len veľmi stručné opísané ako by mohla prebiehať požiadavka DNS. V skutočnosti je to o niečo zložitejšie.

Na internete existuje 13 koreňových DNS serverov. V skutočnosti ich je samozrejme viac, ale fungujú len na 13 anycast IPv4 a IPv6 adresách. Ich rozloženie závisí od rôznych kritérií ako napr. geografické, sieťovej záťaže, redundancie a pod. Ďalej je tu mnoho rekurzívnych resolverov (napr. od googlu, opendns, clouflare atď.). Potom ma každý väčší ISP svoje rekurzívne resolvery (prevažne ich ma otvorené len vnútri svojho autonomného systému (AS)).To všetko je verejne známe.

Ale čo ja?

Som len obyčajný malý človek z jednou verejnou IPv4 adresou a ešte aj to dynamickou. Dokonca môžem byť rád, že môj ISP neblokuje smerom zo svojho AS port 53. Ako si teda ja môžem založiť autoritatívny DNS server pre nejaké domény, ktoré vo svete internetu vôbec neexistujú. Áno, je to možné ale má to nejaké obmedzenia.

Najprv napíšem, že to čo chcem vystrojiť nie je štandardné riešenie, takto sa to nemá robiť. Ak chce mať nejaká spoločnosť domény len vo vnútri firemnej sieti, tak nech sa páči. Ak má viac pobočiek po svete, tak jednoducho použijú VPN. Toto čo robím ja nie je správne, ale robím to len zo zvedavosti aby som skúsil ako funguje DNS vo veľkom internete. Nikdy to nebudem používať, lebo je to tiež nebezpečné z pohľadu útokov na DNS. Za ďalšie, ja nie som odborník na DNS. Začal som sa o to zaujímať len pred nedávnom a niečo málo som si o tom preštudoval. Neštudoval som to do hĺbky, ale len toľko aby som si vedel postaviť jednoduchý DNS, ktorý by splňoval moje požiadavky a to sa mi podarilo.

V tomto blogu nebudem riešiť žiadnu ochranu DNS servera (okrem toho, že vo firewalle povolím konkrétny subnet).

Cieľ projektu

O čo mi vlastne ide. V úvode som spomínal, že pred časom som používal bezplatné TLD. Tieto domény boli bez udania dôvodu zrušené. Ja som síce nebol vlastníkom domén, ale mal som právo ich zadarmo používať. Vzhľadom k tomu, že domény už na verejnom internete neexistujú, tak v lokálnej sieti ich stále používam. Napadla ma myšlienka, prečo by tieto domény nemohli byť viditeľné aj z internetu. Na nasledujúcom obrázku popíšem ako si to predstavujem

Majme na internete klienta s akýmkoľvek operačným systémom (ja som použil klienta s Windows 10). Ak sa klient pripája k internetu, tak je veľmi pravdepodobné, že nadradený router má aktívny DHCP server, ktorý klientovi prideľuje IP adresu. Okrem IP adresy zvykne DHCP server prideľovať klientovi aj IP adresy DNS serverov. Defaultne je DNS adresa nastavená na bránu routera (GW). Aj v tých najlacnejších routeroch (ktoré stoja 10€) je možné nastaviť akú IP adresu DNS servera dostanú klienti v LAN sieti. Ak by sa klient nevedel dostať do nastavení routera, tak DNS adresy si môže nastaviť priamo v OS vo vlastnostiach sieťového adaptéra (toto nastavenie vyžaduje administrátorke práva).

Poznámka: Je pravda, že nemám k dispozícii bežný SOHO router s oficiálnym FW a skúšal som to len na routery s OS OpenWRT. Nastaviť sa to musí takto

Network --> DHCP & DNS --> DNS forwardings
/example.com/11.22.33.44

Poznámka: táto konfigurácia hovorí, aby dnsmasq použil pre doménu example.com, DNS server s IP adresou 11.22.33.44. Ďalšia možnosť je nastaviť v OpenWRT aby bola klientovi pridelená IP adresa DNS servera 11.22.33.44 automaticky. Toto sa mi neosvedčilo pre OS windows (pre linux to fungovalo OK). Nastaviť to môžeme takto:

Network --> Interfaces --> lan-edit --> DHCP Server --> Advanced Settings --> DHCP-Options
6,11.22.33.44

Poznámka: pozor na číslo 6, pred IP adresou. To číslo je identifikátor pre DNS a musí tam byť.

Na druhej strane je DNS server. Postavený je na linuxovom kontajnery s Debianom a ako DNS beží známy daemon Bind9. DNS Bind9 je možné nakonfigurovať aj ako autoritatívny server. Ja som ho samozrejme nakonfiguroval pre autoritatívne záznamy, ale tiež ako forwardovací server (forwardovanie nie je nutné). To znamená, že bude odpovedať na konkrétne domény (v našom prípade jednu doménu) a ostatné požiadavky bude smerovať na rekurzívne resolvery (v našom prípade na google reslovery 8.8.8.8 a 8.8.4.4).

Jednou z najdôležitejších vecí je, aby klient používal náš DNS server. To znamená, že DNS IP adresa musí smerovať na náš DNS server, ale o tom sme si už napísali

Inštalácia a konfigurácia Bind9

Inštalácia je veľmi triviálna a zaberie minimum času. Taktiež stačí na testovanie min. HW požiadavky (úplne stačí jedno jadro a 512MB RAM).

sudo apt update
sudo apt install bind9
sudo named -v
sudo systemctl start named
sudo systemctl enable named
sudo systemctl status named
 named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: active (running) since Fri 2024-04-26 06:47:39 CEST; 4 days ago
       Docs: man:named(8)
    Process: 1638 ExecReload=/usr/sbin/rndc reload (code=exited, status=0/SUCCESS)
   Main PID: 136 (named)
     Status: "running"
      Tasks: 5 (limit: 38272)
     Memory: 9.0M
        CPU: 5.905s
     CGroup: /system.slice/named.service
             └─136 /usr/sbin/named -f -u bind

Teraz vytvorime zónu pre konkrétnu doménu

sudo nano /etc/bind/named.conf.local

Riadok 4 „allow-query“ hovorí, že ktoré IP adresy (v mojom prípade subnet) sú povolené pre túto zónu. Ak by sme chceli povoliť celý internet, tak ako parameter nastavíme „any“ (čo samozrejme neodporúčam).

zone "example.com" {
    type master;
    file "/etc/bind/zones/example.com.zone";
    allow-query { 98.76.54.0/24; };
}

Konfigurácia súboru zóny pre doménu example.com.

sudo mkdir /etc/bind/zones/
sudo nano /etc/bind/zones/example.com.zone
$TTL 86400
@   IN  SOA     example.com. admin.example.com. (
            2024041701 ; Serial
            3600       ; Refresh
            1800       ; Retry
            604800     ; Expire
            86400      ; Minimum TTL
            )
; Define name servers
@   IN  NS      ns1.example.com.
 
; Define IP address of the server (public IP)
ns1 IN  A       11.22.33.44
 
; Define other records like MX, CNAME, etc.
@   IN  A       11.22.33.44
www IN  A       11.22.33.44

Ja som ešte nastavoval pre klientov aj DNS forwarding aby ostatné dotazy boli preposielané na rekurzívne resolvery googlu. Čiže upravovať budeme

sudo nano /etc/bind/named.conf.options
options {

    forwarders {
        8.8.8.8;  // Google Public DNS
        8.8.4.4;  // Google Public DNS
    };

    forward only;
    allow-query { 98.76.54.0/24; };
 
};

Teraz nám stačí preveriť či je v poriadku syntax a Bind9 reloadujeme

named-checkconf
sudo systemctl reload bind9

Je potrebné dávať pozor pri konfigurácii, pretože keď named-checkconf, hodí na výstup nejakú chybu, tak budeme musieť chybu nájsť. Vo výstupe síce je uvedené, kde sa nachádza chyba, avšak niektoré konfiguračné súbory sú „includované“ do hlavného súboru a chyba ukazuje práve na hlavný súbor. To môže administrátora zmiasť.

Nastavujeme NAT

Teraz potrebujeme na firewalle otvoriť port 53, na ktorom počúva DNS Bind9. V závislosti od toho aký používame firewall, tak nastavíme NAT na IP adresu, kde máme DNS server (u mňa 192.168.1.106) s portom 53. Na pfSense by to mohlo vyzerať napr. takto.

Na strane servera je teraz všetko nastavené. Môj DNS server môžu dopytovať len klienti, ktorý pochádzajú zo subnetu 98.76.54.0/24. U klientov je potrebné nastaviť aby používali DNS adresu 11.22.33.44. Ak klient zadá do webového prehliadača example.com, tak by sa mu mal zobraziť obsah z nášho webového servera (tento blog nerieši webový server).

Diagnostika

Ak to nefunguje, tak niekde je nejaký problém. Ako sa s problémom popasovať ? Najprv by som preveril, či je port 53 do internetu určite otvorený. Pozor!!! pri checkovaní portu musíme v Source nastaviť dočasne Any (akákoľvek IP), inak to bude stále hlásiť, že port je closed. Ak sa presvedčíme, že port je skutočne otvorený, tak ďalej môžeme sledovať u klienta pomocou príkazu nslookup (v linuxe je lepšie použiť dig) čo sa deje s DNS. Vo Windowse otvoríme príkazový riadok (Win+R – cmd) a použijeme príkaz

nslookup example.com

Mohli by sme vidieť niečo také

nslookup example.com
Server:  bband-dyn11.22.33.44.isp.com
Address:  11.22.33.44
 
DNS request timed out.
    timeout was 2 seconds.
Name:     example.com
Address:  11.22.33.44

Alebo sa môžeme opýtať DNS servera aby nám poskytol informácie ohľadom akýchkoľvek záznamov pre danú doménu

nslookup -q=any example.com 11.22.33.44
Server:	Unknown
Address: 11.22.33.44
 
example.com
	primary name server = example.com
	responsible mail addr = admin.example.com
	serial  = 2024041701
	refresh = 3600 (1 hour)
	retry   = 1800 (30 mins)
	expire  = 604800 (7 days)
	default TTL = 86400 (1 day)
example.com	      nameserver = ns1.example.com
example.com	      internet address = 11.22.33.44
ns1.example.com	  internet address = 11.22.33.44

Monitorovať vieme aj na DNS servery pomocou utilitky tcpdump. Ak nemáme tcpdump nainštalovaný, tak to môžeme urobiť

sudo apt update
sudo apt-get install tcpdump

Budeme preverovať len port 53. V mojom prípade je sieťová karta (-i interface) označená eth0. Preveriť sa to dá caz príkaz ip a

sudo tcpdump -i eth0 -n port 53

Ak sa klient dopytuje DNS servera a server správne odpovedá, tak by to mohlo vyzerať aj takto

15:55:39.897571 IP 98.76.54.32.62210 > 192.168.1.106.53: 32805+ A? example.com. (30)
15:55:39.897808 IP 192.168.1.106.53 > 98.76.54.32.62210: 32805* 1/0/0 A 11.22.33.44 (46)
15:55:39.947619 IP 98.76.54.32.50379 > 192.168.1.106.53: 37276+ AAAA? example.com. (30)
15:55:39.947898 IP 192.168.1.106.53 > 98.76.54.32.50379: 37276* 0/1/0 (72)
15:55:40.452523 IP 98.76.54.32.53904 > 192.168.1.106.53: 7208+ A? www.example.com. (34)
15:55:40.452778 IP 192.168.1.106.53 > 98.76.54.32.53904: 7208* 1/0/0 A 11.22.33.44 (50)
15:55:40.504415 IP 98.76.54.32.53204 > 192.168.1.106.53: 6781+ A? www.example.com. (34)
15:55:40.504696 IP 192.168.1.106.53 > 98.76.54.32.53204: 6781* 1/0/0 A 11.22.33.44 (50)
15:55:41.764317 IP 98.76.54.32.51964 > 192.168.1.106.53: 34564+ AAAA? www.example.com. (34)
15:55:41.764582 IP 192.168.1.106.53 > 98.76.54.32.51964: 34564* 0/1/0 (76)

Záver

Ako som už v článku naznačil, takéto experimenty nie sú ideálne pre otváranie portu 53 smerom do internetu. Nebodaj by sme použili allow-query { any; } a na firewalle by sme po testovaní portu zabudli nastaviť source, tak do niekoľkých minút (možno hodín) by našu IP adresu určite nejaký scanner našiel a to by sme určite nechceli. Ak chceme dopytovať stroje v lokálnej sieti, tak použijeme DNS lokálne (napr. aj Bind9). V rámci internetu určite použijeme VPN. Ja som to chcel len vyskúšať a som spokojný, že to fungovalo celkom dobre. Ešte malý doplnok: aby sa klientom zobrazovali weby korektne, tak na lokálnom webovom (príp. reverznom proxy) servery, musíme mať vygenerované pre domény certifikáty. Na to použijeme CA o ktorej som písal minule. Tento koreňový certifikát je potrebné nahrať klientom do systému.

Použitá literatúra

Leave a Reply

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *