Infrastructuur en platform
Als DNS omvalt, valt alles om: hoe wij onze nameservers overeind houden
Deze week had Sectigo een grote storing die enkele uren duurde. Wat er precies misging laten we aan hen, maar het laat wel zien hoe snel je afhankelijk bent van één grote partij die je niet in de hand hebt. Dat is precies de reden dat wij onze eigen nameservers draaien. Bij DNS is een storing namelijk nog een graadje erger: valt DNS weg, dan valt alles weg. Geen website, geen mail, geen certificaten.
Wat DNS eigenlijk doet
DNS (Domain Name System) vertaalt een naam als devnomads.nl naar het IP-adres waar een computer echt naartoe kan. Elke keer dat iemand je site opent of een mail naar je stuurt, gaat daar eerst een DNS-vraag aan vooraf. Krijgt die vraag geen antwoord, dan kunnen je servers perfect draaien, niemand vindt ze.
Dat je zonder DNS ook geen certificaten hebt, is minder voor de hand liggend. Wij hebben doorlopend duizenden Let's Encrypt-certificaten in beheer, die we aanvragen en vernieuwen met dns-01 challenges. Let's Encrypt geeft ons dan de instructie om een specifiek record in de DNS van het domein te zetten. Staat dat er, dan weten zij dat wij echt over dat domein gaan en er een certificaat voor mogen aanvragen. Zonder werkende DNS kan die controle niet plaatsvinden en komt er dus ook geen certificaat.
Buiten ons eigen netwerk
Onze hardware staat bij Eurofiber Cloud Infra in Steenbergen, met eigen AS- nummer en eigen IP-adressen. Je zou verwachten dat onze nameservers daar ook staan. Dat doen ze bewust niet. Ze draaien bij verschillende grote cloudproviders, buiten ons eigen netwerk maar wel binnen Europa. Gewoon unicast, dus losse NS-records met elk een eigen IP-adres, zonder anycast-trucs. Valt ons netwerk weg door een stroomstoring of een fout in een BGP-announcement, dan blijft DNS antwoorden. Inkomende mail komt dan terecht op onze offsite locatie bij KoloDC, die de mail vasthoudt en alsnog aflevert zodra alles weer bereikbaar is.
Hiermee ruil je één afhankelijkheid in voor een paar andere, dat klopt. Maar het zijn verschillende grote cloudproviders. De kans dat die tegelijk omvallen, en dan ook nog samen met ons eigen netwerk, is nagenoeg nul.
Random subdomain attacks
De grootste bedreiging voor een nameserver is tegenwoordig niet een DDoS met ruw geweld, maar een random subdomain attack. Een aanvaller vuurt miljoenen vragen af naar namen die niet bestaan: k3j9x.jouwdomein.nl, p0qwe.jouwdomein.nl en zo verder. Antwoorden op bestaande namen kan een nameserver prima cachen, maar deze namen zijn elke keer nieuw, dus elke vraag dwingt hem om in zijn database te kijken. Die database valt om, en daarmee elke zone op die server.
Wij draaien PowerDNS met MySQL als backend en dnsdist ervoor als load balancer. MySQL is niet de snelste backend die je voor PowerDNS kunt kiezen, wel een heel betrouwbare: wijzigingen staan via replicatie direct op alle nameservers, zonder zone transfers en zonder vertraging. dnsdist heeft een packet cache en een set snelle filters: rate limits per IP-adres via eBPF in de kernel, dynamische blokkades voor clients die te veel NXDOMAIN-antwoorden krijgen en een blokkade van 60 seconden op een zone zodra bijna alle vragen op niet-bestaande namen uitkomen. Dat laatste is grof: de zone is dan even weg, maar de database blijft leven.
Alleen bestaande namen doorlaten
Voor het fijnere werk hebben we zelf dnsprotector gebouwd. dnsdist stuurt via dnstap een kopie van elke vraag en elk antwoord naar dnsprotector, dat per domein een venster van vijf minuten bijhoudt en elke 30 seconden naar vier dingen kijkt: hoeveel vragen per seconde er komen, hoeveel verschillende subdomeinen er langskomen, welk deel daarvan nog nooit eerder gezien is en hoeveel antwoorden NXDOMAIN zijn. Een druk maar legitiem domein scoort hoog op het eerste en laag op de rest, want het serveert steeds dezelfde echte namen. Een aanval scoort op alle vier.
Zodra alle vier de voorwaarden kloppen, krijgen wij een notificatie en zet dnsprotector via de console van dnsdist een filter voor die zone aan. Het haalt alle bestaande recordnamen van de zone uit de database en zet die in een allowlist. Alles binnen de zone dat niet op die lijst staat, wordt gedropt nog voordat het bij de database komt. Namen waarvan we al weten dat ze niet bestaan, zoeken we dus niet eens meer op. Geen herstart van dnsdist, de bestaande records van de klant blijven gewoon resolven. Zakt de aanval vijf minuten lang onder de drempels, dan haalt dnsprotector het filter er zelf weer af.
Een maand geleden kwam de grootste aanval binnen die we tot nu toe gezien hebben: ruim 800000 vragen per seconde per nameserver, net onder de 2,5 miljoen per seconde verdeeld over de machines. Er is niks down geweest. De aangevallen zone bleef antwoorden op zijn echte namen en alle andere zones hebben er niets van gemerkt.
Eerlijk is eerlijk: die allowlist heeft een prijs. Zolang het filter actief is, offeren we nieuwe records en wildcards van de aangevallen zone tijdelijk op. Voeg je midden in een aanval een record toe, dan werkt dat pas zodra het weer rustig is. Dat vinden wij een prima ruil tegenover een database die omvalt voor iedereen.
DNSSEC erbovenop
Dat filter is nog om een tweede reden belangrijk. Voor het leeuwendeel van ons domeinportfolio staat DNSSEC aan: elk antwoord wordt digitaal ondertekend, zodat een resolver kan controleren dat het echt van onze nameservers komt en niet onderweg is aangepast. Wij doen dat met live signing: de sleutels staan in dezelfde MySQL-database en PowerDNS berekent de handtekening op het moment dat het antwoord de deur uitgaat, in plaats van een vooraf ondertekende zone uit te lezen. Dat is zwaarder, en bij een NXDOMAIN-antwoord het zwaarst, omdat PowerDNS dan ook moet bewijzen dat de naam niet bestaat. Een random subdomain attack op een ondertekende zone kost dus dubbel. Omdat het filter die vragen al dropt voordat ze bij PowerDNS komen, kan live signing met MySQL als backend prima. In het portal zet je DNSSEC per domein zelf aan of uit.
Dezelfde tooling voor jou
Alles wat hierboven staat, bedienen wij via onze eigen API. Die is publiek, net als devnomads-cli, de client die je via PyPI installeert. DNS zit daar volledig in: alles wat in het portal kan, kan ook vanaf de commandline of vanuit je eigen deploy-script. De CLI heeft ook de ACME-client aan boord die wij zelf voor die duizenden certificaten gebruiken. Het liefst beheren we die gewoon voor je, maar wil je het zelf in de hand houden, dan kan dat.
Wat je daar vandaag mee kunt:
- installeer devnomads-cli en beheer je zones vanaf de commandline
- koppel je deploy-pipeline aan de API om apps en containers te (her)starten
- zet DNSSEC aan in het portal voor domeinen waar het nog uit staat
- controleer op internet.nl hoe je domein er nu voor staat
Wat er nog aankomt
Binnenkort komt er een update van de publieke API waarmee zo goed als ons volledige productaanbod erin zit. Dan beheer je niet alleen DNS, maar vrijwel alles wat je bij ons afneemt vanuit dezelfde CLI en met dezelfde tokens.
Benieuwd hoe jouw DNS er nu voor staat, of twijfel je of je nameservers een aanval van deze omvang aankunnen? Stuur ons gewoon een berichtje, dan kijken we mee.