Dichttimmeren van DNS met DNSsec

Het domain name system DNS is een bekende sluitpost in de veiligheid van de opbouw van een netwerkverbinding. Met DNS spoofing is het mogelijk om elke gewenste verbinding om te leiden naar elk gewenst IP-nummer. Een goede oplossing is DNSsec, kort voor secure DNS.

Dit artikel verscheen eerder in het Windows & .NET Magazine van oktober 2002.

De populaire bind nameserver, die beschikbaar is onder NT en 2000 en voor Unix platformen, ondersteunt DNSsec vanaf versie 9. We bespreken hier het beveiligen van een domein met behulp van DNSsec. Bind wordt onder Windows bespeeld vanaf een DOS prompt en wordt geconfigureerd via een tekstfile named.conf.

Wie het eerst komt...

DNS spoofing is het overnemen van een name service, en daarvoor volstaat het om sneller te zijn met antwoorden op DNS vragen dan de legitieme name server. Vraagt iemand om het IP-nummer voor de domeinnaam www.postbank.nl, dan kan een spoofer daarop antwoorden met een IP-nummer naar wens, en achter dat IP-nummer kan een website draaien die er netzo uitziet als die van de Postbank. Een inlogpagina (die niet via https:// werkt) kan de spoofer aan een flinke stapel interessante passwords helpen.

De vraag om het IP-nummer bij een domeinnaam is een DNS vraag die aan een bepaalde name server wordt gezonden, bijvoorbeeld die van de ISP of die op het LAN. Die name server reageert met de query plus het antwoord. Om de queries te onderscheiden wordt een 16-bit random getal in de query opgenomen, en het antwoord vermeldt datzelfde getal. Aangezien vraag en antwoord normaliter via UDP plaatsvinden, is er voor de spoofer dus niets meer nodig dan het reproduceren van dit random getal, en natuurlijk het geven van een geschikt antwoord op de DNS vraag.

Het opvangen van DNS vragen is met name mogelijk voor computers die op een gedeeld netwerk zitten, zoals BNC-gebaseerd ethernet, UTP met een hub, wireless LAN of een kabelnetwerk. Verder zijn er natuurlijk strategisch geplaatste systemen zoals routers en name servers die kunnen spoofen, maar dat is doorgaans een minder prangend probleem. Tenslotte neemt de kans dat DNS spoofing werkt toe naarmate het beantwoorden van queries door de legitieme name servers langer duurt.

Digitale handtekeningen

De oplossing die DNSsec biedt voor dit probleem is een digitale handtekening onder de antwoorden op DNS vragen, gezet door de name server. Zo'n handtekening maakt het mogelijk om te controleren dat het antwoord afkomstig is van een vertrouwde bron, en dat het antwoord na verzending door die bron niet is gewijzigd.

Er zijn in principe twee manieren om een handtekening te plaatsen. De eerste is met een symmetrische sleutel ofwel met een gedeeld geheim, de andere met een asymmetrische sleutel ofwel met een paar van een geheime en publieke sleutel. Van deze twee is de symmetrische sleutel efficiënter, terwijl een public key systeem breder inzetbaar is; ze worden dan ook beide gebruikt, afhankelijk van ontwerpoverwegingen.

De werkwijze met een symmetrische sleutel is slechts geschikt tussen systemen die elkaar wederzijds vertrouwen. Vanwege dat vertrouwen is het aantal systemen beperkt tot een vast aantal, met twee als ideaal. De concrete plek in DNS waar dit nuttig werkt is tussen de master en een slave name server die beide optreden als oorprong voor een domein; de master ondertekent alle DNS informatie die aan een bepaalde slave wordt doorgegeven met een symmetrische sleutel die bij de combinatie van master met die slave hoort. De slave kan de ontvangen DNS informatie hierdoor authenticeren, want buiten de slave kan alleen de master een handtekening zetten met het gedeelde geheim.

De oorspronkelijke name servers voor een domein verspreiden de DNS informatie naar losse computers waarvan de lokale resolver om de informatie vraagt, en ook naar andere name servers die DNS vragen stellen uit naam van lokale resolvers; dit zijn de zogenaamde caching name servers, ook wel bekend als recursive name servers. Aangezien het hier gaat om ongebreidelde verspreiding moet wel gebruik worden gemaakt van de duurdere handtekeningentechniek die met een public key controleerbaar is. Immers, alleen een publieke sleutel kan vrijelijk worden verspreid.

Secure kanaal van master naar slaves

Het is raadzaam om oorspronkelijke name servers zo verspreid mogelijk over de aardbol op te zetten; in het verleden is het hele domein microsoft.com al eens een paar dagen uit de lucht geweest doordat de 4 servers voor dat domein samen op een gang stonden; het dichttrekken van de gedeelde uplink naar Internet met een DoS aanval volstond om alle name servers onbereikbaar te maken, zodat alles onder het domein onvindbaar werd. Graafwerkzaamheden en aardbevingen kunnen hetzelfde gevolg hebben, dus geografische verspreiding van name servers is van belang.

Dat introduceert wel meteen allerlei kansen om het verkeer tussen master en slave servers te spoofen; hoewel dat verkeer vaak via TCP geschiedt is het toch niet onmogelijk dat een kwade macht er tussen gaat zitten. Hier passen we dus de genoemde symmetrische sleutels toe.

In principe kan elk willekeurig getal van 128 tot en met 512 bits dienen als gedeelde sleutel, en 128 bits is al flink veilig. Langere sleutels worden via een secure hash `ingedikt' tot 128 bits. Sleutels worden in base64-codering opgeslagen en uitgewisseld. Desgewenst is het ook mogelijk om de sleutel te genereren met een commando onder bind 9:

dnssec-keygen -a hmac-md5 -b 128 -n HOST deedee-dexter.
het mechanisme voor authenticatie is hier HMAC-MD5, ofwel een MD5 secure hash over data plus geheime sleutel; het aantal sleutelbits in 128; de menselijke sleutelnaam is deedee-dexter ("voor de verbinding tussen Deedee en Dexter"). De gegenereerde sleutel wordt opgeslagen in een file met een naam als Kdeedee-dexter.+157+12345.key.

In de genoemde file staat de sleutel na een prefix Key: genoemd, bijvoorbeeld de base64-string B0ekenka5t/3eBoek/Pulg==. Die moeten we in de configuratiefile named.conf opnemen met de menselijke naam voor later gebruik; dit gebeurt met een declaratie als

key deedee-dexter. {
	algorithm hmac-md5;
	secret "B0ekenka5t/3eBoek/Pulg==";
};

Deze declaratie wordt gemaakt op zowel master als slave, dus op Deedee en Dexter. Daar kan een reeds vertrouwd mechanisme voor worden gebruikt, bijvoorbeeld een encrypted kanaal via SSH of PGP, of gewoon een telefoontje of fietstochtje van Deedee naar Dexter's lab.

Nu wordt het leuk. Als Deedee de master name server is, dus degene waarop de originele zone file wordt ingevoerd, dan moet ze de sleutel gaan gebruiken om verzoeken van Dexter te ondertekenen met de gedeelde sleutel. Als het IP-nummer van Deedee 1.2.3.4 is, dan kan dat met de volgende declaratie in named.conf:

server 1.2.3.4 {
	keys { deedee-dexter. ; };
};
Evenzo stelt Deedee in dat Dexter, met IP-nummer 5.6.7.8, deze gedeelde sleutel gebruikt:
server 5.6.7.8 {
	keys { deedee-dexter. ; };
};
Hierdoor weten beide dat ze een TSIG record, met een transaction signature, moeten toevoegen aan alle DNS vragen en antwoorden die tussen hen worden uitgewisseld, en dat alles wat van de andere kant komt gecontroleerd moet worden. De communicatie tussen Deedee en Dexter is hiermee potdicht, ook over barre tochten langs onbetrouwbare sujetten; Dexter weigert gewoon wat hij van Deedee haalt als daar geen TSIG aan toegevoegd is (en vermeldt dat dan ook in de log files).

Deze procedure wordt afzonderlijk uitgevoerd, met afzonderlijke sleutels, voor elke slave van een master; het is niet raadzaam dezelfde sleutel te gebruiken voor meerdere slaves, omdat een eventuele kraak van een sleutel hiermee meer reikwijdte oplevert dan strikt noodzakelijk.

Bind ondersteunt overigens access control om in te perken wie bepaalde typen DNS vragen mag stellen; normaliter gebeurt zoiets op basis van IP nummers, maar met ingang van bind 9 is het ook mogelijk hiervoor gebruik te maken van sleutels, zodat weer een spoofing variant zinloos wordt. Met deze access control is bijvoorbeeld in te stellen dat een AXFR (domain transfer) alleen toegestaan is wanneer die DNS vraag is ondertekend met de gedeelde sleutel.

Algemeen controleerbare DNS antwoorden

Een computer die een DNS vraag stelt, zal dat doorgaans doen via een deel van het operating systeem dat de resolver heet; die spreekt op zijn beurt vaak een name server op het lokale netwerk aan. Deze lokale server gaat op zoek naar oorspronkelijke name servers voor domeinen, en retourneert het antwoord op de gestelde DNS vraag.

Om de invloed van tussenliggende spelers te reduceren is het nodig dat de uiteindelijke resolver de DNS antwoorden authenticeert; wanneer het niet anders kan zou desnoods de name server op een LAN kunnen worden vertrouwd om dit te doen. Als een lokale resolver de controle zou moeten doen maar er niet toe in staat is, dan kan een tussenoplossing zijn als de name server niet ergens op het LAN, maar op elk workstation draait (en verzoeken doorstuurt naar de name servers op het LAN, maar ze op elk workstation controleert).

Zoals uitgelegd is het aantal resolvers dat een domein opvraagt onbepaald, en dus is het niet mogelijk om te werken met gedeelde geheimen; er moet dus wel met public key mechanismen worden gewerkt. Het controleren van een public key handtekening is doorgaans minder inspannend dan het creëren ervan; om nu te voorkomen dat name servers overbelast raken worden de handtekeningen op alle denkbare antwoorden die de name server kan geven zo veel mogelijk vooraf aangemaakt en letterlijk in de name server ingelezen. Dat houdt dus in dat er een extra administratieve handeling nodig is, namelijk het ondertekenen van een zone.

Voor dat ondertekenen moet eerst een sleutelpaar (publieke en geheime sleutel) worden aangemaakt; de publieke sleutel moet wijd verbreid worden en de geheime sleutel kan dan worden gebruikt om de zone te ondertekenen op de master. De master zendt dat alles vervolgens naar de slaves, en alle resolvers kunnen dan de wijd verbreide publieke sleutel gebruiken om de informatie uit de zones te controleren.

Een sleutel aanmaken gaat wederom met dnssec-keygen, maar nu met een ander algoritme en langere sleutels.

dnssec-keygen -a DSA -b 768 -n ZONE openfortress.nl.
De weggeschreven files met .key en .private extensies bevatten nu verschillende sleutels, omdat het niet om symmetrische sleutels gaat zoals in het vorige voorbeeld. De publieke sleutel is de enige die veilig binnen een eventuele sandbox voor de name server kan worden geplaatst. Het idee is dat deze met een $INCLUDE commando in de zone file wordt ingevoegd.

De geheime sleutel wordt nergens in DNS opgenomen (dan zou er weinig geheims meer aan zijn) maar is nodig voor het ondertekenen van de zone. Er van uit gaand dat de niet-ondertekende zone informatie in een file openfortress.nl staat, kan die zone ondertekend worden met een commando als

dnssec-signzone -o openfortress.nl zone/openfortress.nl \
	keys/Kopenfortress.nl.+123+12345.private
De uitvoer (met extensie .signed toegevoegd) is een zone-file die in de master name server voor het domein kan worden ingevoerd in plaats van de unsigned versie. Telkens wanneer de zone wordt ververst moet die opnieuw worden ondertekend met de geheime sleutel.

Beheer van publieke sleutels

De sleutels in DNS zijn doorgaans korter dan aangeraden wordt voor langdurig gebruik in systemen zoals SSH, TLS/SSL en PGP. Dat is enerzijds om de controles efficiënt te houden, anderzijds om de afmetingen niet te groot te maken, want DNS werkt beter met kortere datablokken.

Kortere sleutels kunnen sneller gekraakt worden en moeten dus vaker ververst worden, ofwel vervangen door andere sleutels. Naarmate een sleutel langer in gebruik is (en er meer computerkracht aan een kraak besteed kan zijn) en naarmate meer DNS informatie opgelepeld is (waardoor meer invoer voor kraakprocessen bestaat) moet dat vaker gebeuren; DNS moet dan ook sleutelverversingen ondersteunen, en ze doet dat door de nieuwe sleutel door een hogere instantie te laten ondertekenen.

Dit brengt de vraag te berde waarop het vertrouwen in een sleutel gebaseerd is. En dat is doorgaans een doorgeefspelletje, waarbij het KEY record met een sleutel ondertekend is door een SIG record, waarbij gebruik is gemaakt van een "hogere" sleutel, die op zijn beurt weer dezelfde behandeling kan krijgen.

Zulke hogere sleutels tekenen voor lagere sleutels middels het commando dnssec-signkey; dit zal doorgaans gedaan worden door een andere DNS admin, die de te ondertekenen sleutel ontvangt in een pakketje dat aangemaakt wordt met dnssec-makekeyset. Ook in deze vertrouwensrelatie voorziet DNSsec dus.

Dit vertrouwensspel eindigt bij een ultiem vertrouwde sleutel, of `root key'. Zo'n sleutel kan de sleutel zijn van een soort centrale organisatie die de entries in de root name servers ondertekent; of het kan een lokaal toegepaste sleutel zijn waarvan op andere wijze het vertrouwen is vastgesteld. Het idee is dat de root keys algemeen bekend zullen zijn, terwijl voor de lokaal toegepaste sleutels handmatig aanpassingen mogelijk zijn.

In de named.conf file kan het vertrouwen in een publieke sleutel worden uitgedrukt middels declaraties als:

trusted-keys { 512 3 157 "B0ekenka5t/3eBoek/Pulg=="; } ;
Dit zijn de `root keys' die, direkt of indirekt, kunnen tekenen voor de DNS records die gevalideerd dienen te worden. Voor lokaal gebruik kan hier de lokale sleutel worden gebruikt, wat het vertrouwensspel verder onnodig maakt.

Efficiëntie van DNSsec

Het moge duidelijk zijn dat DNSsec niet zonder inbreuk op snelheid is; het maken en controleren van handtekeningen gaat met enige werkdruk gepaard.

Het verkeer tussen master en slaves is met een gedeelde sleutel ondertekend, wat in wezen inhoudt dat een MD5 secure hash moet worden berekend over alles wat wordt verzonden of ontvangen; dit is geen extreem dure operatie, en aangezien het hier gaat om de relatief zeldzame werklast ten gevolge van wijzigingen of cache-updates van de zone informatie, en dan ook nog alleen onderling tussen oorspronkelijke name servers, is dit geen grote kostenpost.

Een grotere werklast schuilt in het ondertekenen van de zone informatie, maar zoals getoond kan dat doorgaans offline worden uitgevoerd. Dit houdt in dat alleen bij wijzigen van zone-informatie en bij verversen van de sleutels een beetje werk gedaan moet worden door de systeembeheerder; pas wanneer de zone-informatie dynamisch aanpasbaar moet zijn, zoals bij gebruik van Active Directory, kan het nodig zijn anders te werk te gaan.

Het controleren van de handtekeningen op de zone-informatie is het werk van de lokale resolver, en die heeft er wel meer werk aan; dit komt doordat bij een publieke sleutel ook doorgevraagd moet worden om vertrouwen in die sleutel te krijgen. Dat zijn sequentieel aaneengeschakelde DNS vragen, en de wachttijd van een aantal DNS vragen moet dus worden opgeteld.

Een groter probleem is dat er nogal wat meer informatie verhandelt wordt met DNSsec. Dat kan zomaar het zesvoudige zijn van de `insecure' versie van de data. En dat betekent dat alle name server componenten, van master en slaves tot resolver aan toe, meer opslagruimte nodig hebben. En dus sneller zullen gaan swappen.

Maar meer nog is er het probleem dat zowel DNS vraag als antwoord via UDP maximaal 512 octets lang mogen zijn. Met name het antwoord loopt bij DNSsec een groot risiko om niet te passen. Als dat optreedt, dan wordt dat afgevlagd in het antwoord, en als de resolver daar reden toe ziet, kan die de DNS vraag wpnieuw zenden, maar dan via TCP. De extra overhead is in dat geval niet gering, en dit maakt DNS meteen een heel stuk minder efficiënt.

Invoering van DNSsec

Een secure name server is begrijpelijk voor elke name server en elke resolver; om handtekeningen moet expliciet worden gevraagd (bij dig geef je als optie +dnssec). Omschakeling van alle name servers op DNSsec is dus met onmiddelijke ingang mogelijk. Op het moment is dat nog lang niet overal gebeurd, maar een grote stap zou zijn dat de root name servers hun entries zouden vermelden met DNSsec toevoegingen; vandaaruit kan dan vertrouwelijk worden afgedaald in de namenboom.

De NLnet labs hebben diverse studies uitgevoerd naar het ondertekenen van de zones voor een aantal top-levels, te weten .de, .nl en .com, en ze werkt aan het online krijgen van een DNSsec root service voor .nl domeinen. Wat nog niet duidelijk is, is hoe zeker te stellen is of een domein DNSsec gebruikt (en navenant controleerbaar is) of niet (en maar moet worden genomen zoals het komt).

Onafhankelijk van wat er gebeurt met de root name servers, is het prima mogelijk om op lokaal niveau met DNSsec te beginnen. Bijvoorbeeld op een LAN kunnen intranet-adressen er mee beveiligd worden; vooral wanneer het mogelijk is dat onbekende personen inpluggen in een bedrijfs-LAN is dat nuttig. Het is mogelijk om binnen zo'n beperkt terrein iedereen te voorzien van de vertrouwde publieke sleutel waar de hele DNSsec veiligheid dan aan opgehangen wordt.

De invoering van DNSsec voorkomt weliswaar DNS spoofing, maar het blijft evengoed mogelijk om lokaal ARP of DHCP te spoofen -- oplossingen op dat niveau blijven dus nodig, en liefst even dynamisch als die protocollen zijn omwille van de beheersbaarheid. Zo gezegd lijkt IPsec een algemenere oplossing te bieden; maar daarvoor komen de sleutels weer vaak uit DNS.

Een paar primaire diensten staan ter beschikking van wie met DNSsec wil experimenteren; zo is er een slave name service op secondary.com, en ook viel nlnetlabs.nl al. En natuurlijk is er bind 9, dat downloadbaar is van de welbekende plek, isc.org. Het geheel van DNSsec is gedocumenteerd vanaf RFC 2065.

Samenvatting

DNSsec biedt een compleet, maar ook complex antwoord op DNS spoofing op diverse plekken. Het is echter niet gezegd dat dit alle problemen oplost; spoofing blijft voorlopig mogelijk op diverse andere plaatsen.

DNSsec maakt gebruik van digitale handtekeningen op de verzonden informatie. De bind nameserver ondersteunt DNSsec volledig vanaf versie 9.

DNSsec is nog niet globaal ingevoerd in het Internet, maar staat te trappelen van ongeduld. De technologie is er in elk geval, en die is ook nu al inzetbaar op lokaal niveau, bijvoorbeeld binnen de eigen LAN, ook al omdat een DNSsec server probleemloos samenwerkt met een normale resolver.

Dit document is copyright ©2002 OpenFortress. Verspreid niet dit document maar de link erheen, zodat toekomstige updates zichtbaar blijven.


 
   ------ 8< ---------- 8< ----------- 8< ------ | OpenFortress*